IPFW(8)

名称
ipfw - IP ファイアウォールとトラフィックシェイパの制御プログラム

書式
ipfw [-q] [ -p preproc [-D macro[=value]] [-U macro]] pathname ipfw [-f | -q] flush ipfw [-q] {zero | resetlog | delete} [number ...] ipfw [-s [field]] [-adeftN] {list | show} [number ...] ipfw [-q] add [number] rule-body ipfw pipe number config pipe-config-options ipfw pipe {delete | list | show} [number ...] ipfw queue number config queue-config-options ipfw queue {delete | list | show} [number ...]

解説
ipfw は、 FreeBSD の ipfirewall(4) と dummynet(4) トラフィックシェイパを制御するユーザインタフェースです。

ファイアウォール設定は、番号付けされたルールのリストからなります。 あるルールにマッチしそれに関連する動作が実行されるまで、 各入出力 IP パケットはルールのリストに対し照合されます。 動作とシステムの設定によっては、マッチしたルールの直後で、 パケットがファイアウォールに再注入され、 更に処理が継続することもあります。 全てのルールが全てのインタフェースに適用されますので、 チェックの回数が最小となるようなルール集合を書くのは システム管理者の責任です。

どの設定も常に、 DEFAULT ルール (番号 65535) を含みます。このルールは変更できず、 全パケットにマッチします。 デフォルトルールに関連付けるルールは deny か allow のどちらかになりますが、 これはどのようにカーネルを設定したかに依存します。

ルール集合が keep-state または limit のオプション付きのルールを含む場合、 ipfw は ステートフル (状態依存型) で動作します。すなわち、あるマッチの結果、 マッチしたパケットのパラメータにちょうど一致するルールが 動的に生成されます。

これらの動的ルールの寿命は有限で、 check-state または keep-state ルールが最初に生じた場所でチェックされます。 動的ルールは、合法的なトラフィックをオンデマンドで ファイアウォールを通過させるために用いることが普通です。 ipfw のステートフルな動作について更に情報が必要ならば、 以下の ルール書式 または 使用例 セクションを参照して下さい。

動的ルールも含めすべてのルールは、 それに関連するカウンタをいくつか持っています。 それは、パケットカウント、バイトカウント、ログカウント、 最後にマッチした時刻を示すタイムスタンプです。 カウンタは、 ipfw コマンドによって、表示およびリセット可能です。

ルールの追加は add コマンドにて可能です。 個々のルールの削除は delete コマンドにて可能であり、すべてのルールの削除は flush コマンドにて可能です。 ルールの表示は、 show コマンドおよび list コマンドにて可能です。 これらにより、オプションでカウンタ内容も含めて表示させることができます。 最後に、カウンタのリセットは zero コマンドおよび resetlog コマンドにて可能です。

次のオプションが利用可能です:

-a  リスト中にカウンタ値を示します。 show コマンドは、このオプションを暗黙的に指定しただけのものです。

-d  リスト中に、静的ルールに加えて動的ルールも表示します。

-e  -d オプションも指定された場合、 リスト中に、期限切れの動的ルールも表示します。

-f  誤って使用すると問題を起す可能性のあるコマンド、 すなわち flush に対して、実行の確認を行いません。 注: プロセスに関連付けられた tty が無い場合、このオプションが 暗黙のうちに指定されたとして処理されます。

-q  add, zero, resetlog, flush 実行中、動作について報告しません (暗黙のうちに -f が指定されます)。 スクリプト (例えば ‘sh /etc/rc.firewall’) の中で複数の ipfw コマンドを実行してルールを変更する場合や、 リモートログインセッション経由で多数の ipfw ルールを含むファイルを処理することによりルールを変更する場合に 有用です。 通常 (冗長) モードで (デフォルトカーネル設定で) flush を行った場合、 メッセージを表示します。 すべてのルールが捨てられますので、 メッセージはログインセッションへ渡せません。 つまり、リモートログインセッション経由の場合、セッションはクローズされ、 残りのルールセットは処理されません。 この状態から回復するためにはコンソールへのアクセスが必要になります。

-t  リスト作成時に、最後にマッチしたタイムスタンプを表示します。

-N  出力中のアドレスとサービス名を解決しようとします。

-s [field]
    パイプ経由でリスト出力している際に、4つのカウンタの1つについて 整列させます (現在のパケット数)。

設定を簡単にするために、ルールをファイルに記述して、 これを ipfw の最初の書式行を使って処理します。 pathname には絶対パス名を使用する必要があります。 このファイルからは 1 行ずつ読み込まれ、 ipfw ユーティリティへの引数となります。

-p preproc を使用して、 pathname がパイプされるプリプロセッサを指定することもできます。 有用なプリプロセッサには、 cpp(1) と m4(1) があります。 preproc の最初の文字がスラッシュ (‘/’) から始まらない場合、 PATH を使用した通常の名前検索が行われます。 ipfw が実行されるときまでに全ファイルシステムが (まだ) マウントされないような環境 (例えば NFS 経由でマウントされる場合) では、このことに注意してください。 ひとたび -p が指定されると、オプションとして -D と -U の指定を続けることが可能となり、これらがプリプロセッサに渡されます。 これにより、(ローカルホスト名により条件付けするなど) 柔軟性のある設定ファイルを作成可能となり、IP アドレスのように 頻繁に必要となる引数を集中管理するためのマクロを使用可能となります。

後述の トラフィックシェイパ設定 の節で示すように、 ipfw pipe コマンドを使用して、トラフィックシェイパを構築可能です。

ルール書式
ipfw ルールフォーマットは次の通りです。

[prob match_probability] action [log [logamount number]] proto from src to dst [interface-spec] [options]

各パケットをフィルタする際には、以下の情報に基づくことができます。

送受信インタフェース
    (名前またはアドレス)
方向  (入力または出力)
送信元および宛先 IP アドレス
    (マスク使用可)
プロトコル
    (TCP, UDP, ICMP 等)
送信元および宛先ポート
    (リスト、範囲、マスクのいずれか)
TCP フラグ
IP フラグメントフラグ
IP オプション
ICMP タイプ
パケットに関連付けられたソケットのユーザ ID とグループ ID

送信元 IP アドレスや宛先 TCP/UDP ポートによるフィルタは 危険があることに注意してください。 なぜなら、これらの詐称は簡単だからです。

prob match_probability
    指定した確率 (0 から 1 までの浮動小数点数です) でのみマッチが宣言されます。 ランダムにパケットを落とす応用として用いる場合や、( dummynet(4) と共に使用して) パケット到達順序の乱れを引き起こす複数経路の効果をシミュレートする際に 有用です。

action:

    allow
        マッチするパケットを通過させ、マッチングを終了します。 pass, permit, accept はこれの別名です。

    deny
        マッチするパケットを破棄し、マッチングを終了します。 drop は deny の別名です。

    reject
        (この使用は推奨されません) マッチするパケットを破棄し、 ICMP の host unreachable を送信し、 マッチングを終了します。

    unreach code
        マッチするパケットを破棄し、 ICMP の unreachable に code を付けて送信します。ここで、 code は、0 から 256 までの数字、もしくは、以下に列挙する別名のいずれかです: net, host, protocol, port, needfrag, srcfail, net-unknown, host-unknown, isolated, net-prohib, host-prohib, tosnet, toshost, filter-prohib, host-precedence, precedence-cutoff 。マッチングは終了します。

    reset
        TCP パケットのみ対象。 パケットを破棄し、TCP の reset (RST) を送信し、 マッチングを終了します。

    count
        ルールにマッチするパケットすべてのカウンタを更新し、 引続きマッチングを行ないます。

    check-state
        動的ルール集合に対してパケットのチェックを行ないます。 マッチした場合、マッチングは終了します。 マッチしなかった場合、次のルールに移ります。 check-state ルールが見つからないときは、動的ルール集合は最初の keep-state ルールの場所でチェックされます。

    divert port
        マッチするパケットを port で指定されたポートにバインドされている divert(4) ソケットに送り、マッチングを終了します。

    tee port
        マッチするパケットのコピーを port で指定されたポートにバインドされている divert(4) ソケットに送ります。 検索を終了し、元のパケットは受理されます (ただし後述の バグ を参照してください)。

    fwd ipaddr[,port]
        マッチしたパケットの次のホップを ipaddr に変更します。これはドット付き 4 つ組の IP アドレスでもホスト名でもよいです。 ipaddr が直接到達可能なアドレスではない場合、その IP に対して ローカルルーティングテーブルでみつかった経路を使用します。 ipaddr がローカルアドレスの場合、 fwd ルールにパケットがマッチすると、そのパケットをローカルマシンの port に転換します。 その際、 ソケットのローカルアドレスは、 パケットの元々の宛先の IP アドレスのままとします。 netstat(1) エントリが奇妙に見えるようになりますが、 これは透過的プロキシサーバのためにあります。 IP が ローカルアドレスではない場合、ポート番号は (指定されていても) 無視されます。 パケットがローカルに生成されたときにも、アドレスをマップします。 検索はこのルールがマッチしたときに終了します。 ポート番号が与えられなかった場合、 外部マシンのポート Y へのパケットは ローカルポート Y へ転送されるように、 パケット中のポート番号が使用されます。 カーネルは、 オプション IPFIREWALL_FORWARD 付きでコンパイルされている必要があります。 ブリッジ機能は、転送が実装されている部分で ip_input() と ip_output() をバイパスすることで、ローカルシステム宛ではないパケットを転送します。 fwd 動作はパケットの内容をまったく変更しないため、 転送先システムがそのようなパケットを取り込むルールを持たない限り、 当該パケットは通常そのシステムが拒否します。

    pipe pipe_nr
        パケットを dummynet(4) “パイプ” へ渡します (バンド幅制限、遅延等のため)。 更なる情報については トラフィックシェイパ設定 の節を参照してください。 検索は終了します。 しかし、パイプから抜けたときに sysctl(8) 変数 net.inet.ip.fw.one_pass がセットされていない場合、 パケットはファイアウォールコードへ再度渡されて次のルールから開始します。

    queue queue_nr
        パケットを dummynet(4) “queue” へ渡します (WF2Q を使ったバンド幅制限用)。

    skipto number
        number より小さな番号のルールを飛び越して、 number 以上の番号のルールで最初に存在するものから、マッチングを継続します。

log [logamount number]
    カーネルが IPFIREWALL_VERBOSE オプション付きでコンパイルされている場合に、 log キーワードが指定されているルールとマッチした時、 メッセージを LOG_SECURITY ファシリティで syslogd(8) でログします。 注: デフォルトでは、ログは /var/log/security ファイルに追加されます ( syslog.conf(5) を参照してください)。 カーネルが、 IPFIREWALL_VERBOSE_LIMIT オプション付きでコンパイルされている場合、 デフォルトでは、 一連のルールに対し指定されたパケット 数を受信した後、メッセージの表示を中止し、 net.inet.ip.fw.verbose_limit がその数に設定されます。 しかし logamount number が使用された場合、 net.inet.ip.fw.verbose_limit の代りにこの number がデフォルトのログ制限になり、値 “0” を指定すると、ロギングの制限は取り除かれます。 このエントリに対するロギングカウンタまたはパケットカウンタを クリアすれば、ロギングは再び有効になります。

    コンソールログとデフォルトログ制限数は、 sysctl(8) を通じて MIB ベース net.inet.ip.fw にて動的に設定できます。

proto
    名前または数値で指定する IP プロトコル (詳細は /etc/protocols のリストを参照のこと)。 ip または all のキーワードを使用すると、すべてのプロトコルがマッチします。

src と dst:
    any | me | [not] <address/mask> [ports]

    any を指定すると、ルールはすべての IP 番号とマッチします。

    me を指定すると、ルールはシステム上で構成されたすべての IP 番号とマッチします。

    <address/mask> は以下のように指定できます。

    ipno
        IP 番号を 1.2.3.4 の形式で指定します。 この IP 番号にのみマッチします。

    ipno/bits
        IP 番号とネットマスクの幅を 1.2.3.4/24 の形式で指定します。 この例の場合は 1.2.3.0 から 1.2.3.255 のアドレスがマッチします。

    ipno:mask
        IP 番号とネットマスクを 1.2.3.4:255.255.240.0 の形式で指定します。 この場合は 1.2.0.0 から 1.2.15.255 のアドレスがマッチします。

    アドレスの前に not を付けることによって、マッチの意味を反転させる ことができます (指定されたアドレス以外のすべてのアドレスがマッチします)。 これはポート番号の選択には影響しません。

    TCP と UDP ではさらに、 ports を以下のように指定できます。

    {port|port-port|port:mask} [,port[,...]]

    記号 ‘-’ による表現は、ポート範囲 (両端含む) を指定します。

    記号 ‘’: による表現は、ポートとマスクを指定します。 マッチが宣言されるのは、 パケット中のポート番号がルール中のポート番号にマッチするときですが、 マッチ対象のビットはマスク中で指定されたものに限定されます。

    ポート番号の代わりに (ファイル /etc/services から取った) サービス名を使用できます。 ポート範囲指定の書式は、最初の値としてのみ指定できます。 列挙出来るポート数は /usr/src/sys/netinet/ip_fw.h で IP_FW_MAX_PORTS として定義されています。 バックスラッシュ (‘\’) を使用することにより、サービス名中の (‘-’) 文字をエスケープ可能です:

        ipfw add count tcp from any ftp\\-data-ftp to any

    断片化されたパケットでオフセットが非 0 のもの (すなわち、最初の断片ではないもの) は、 1 つ以上のポート指定を持つルールにはマッチしません。 断片化されたパケットへのマッチングに関する詳細は frag オプションを参照してください。

interface-spec
    次の指定子の組み合わせを使用可能です:

    in  入力パケットにのみマッチします。

    out 出力パケットにのみマッチします。

    via ifX
        パケットはインタフェース ifX を通過せねばなりません。

    via if*
        パケットはインタフェース ifX を通過せねばなりません。この X はどんなユニット番号でもかまいません。

    via any
        パケットは いずれか のインタフェースを通過せねばなりません。

    via ipno
        パケットは、 IP アドレス ipno を持つインタフェースを通過せねばなりません。

    via を用いると、常時指定されたインタフェースがチェックされます。 recv や xmit を、 via の代わりに指定すると、 受信、もしくは送信インタフェースのみが (おのおの) チェックされます。 両方を指定すれば、 受信インタフェースと送信インタフェースの両方に基づきパケットを マッチさせることが可能になります。 例 :

        ipfw add 100 deny ip from any to any out recv ed0 xmit ed1

    recv で指定したインタフェースでは、受信と送信、両方のパケットをチェックできます。 それに対し、 xmit で指定したインタフェースでは、送信パケットのみとなります。 それゆえに、 xmit を指定すると out が、必須です ( in は不可)。 via と共に xmit もしくは、 recv を指定する事はできません。

    パケットは、受信用ないし送信用インタフェースを持たない場合があります。 ローカルホストで発生したパケットには受信用のインタフェースはありませんし、 ローカルホスト内宛のパケットには送信用インタフェースはありません。

options:

    keep-state [method]
        マッチの際に、ファイアウォールが動的ルールを生成します。このルールの デフォルトの動作は、同一プロトコルを用いる発信元と宛先の IP/port 間で双方向に通過するパケットへのマッチです。 このルールの生存期間は有限です ( sysctl(8) 変数の集合により制御されます)。この生存期間は、パケットのマッチが 生じるたびに更新されます。

    limit {src-addr | src-port | dst-addr | dst-port} N
        ファイアウォールは、 ルールで指定されるパラメータにおいては、 N 個の接続だけを許可します。 始点および終点のアドレスやポートは、1 個以上指定可能です。

    bridged
        ブリッジされるパケットにのみマッチします。 これはマルチキャストやブロードキャストのパケットを扱う際に有用です。 これ以外の方法では、パケットは、ブリッジの際に一度、 ローカルスタックに渡される際にもう一度と、 ファイアウォールを 2 度通過してしまいます。

        パフォーマンス上のわずかな損失はともかく、 pipe を用いる際にも問題になります。これは、バンド幅、キュー占有度などの カウンタに関して、同じパケットが 2 度カウントされてしまうためです。

    frag
        パケットが断片 (フラグメント) 化されたデータグラムの一部で、 かつデータグラムの先頭の断片でない場合にマッチします。 frag を、 tcpflags や TCP/UDP ポート指定と共に使用することはできません。

    ipoptions spec
        IP ヘッダが、 spec に指定されたコンマで区切られたオプションのリストを含む場合にのみマッチします。 サポートされている IP オプションは

        ssrr (strict source route), lsrr (loose source route), rr (record packet route), ts (timestamp) です。 ‘’! によって、特定のオプションを含まない指定が記述できます。

    tcpoptions spec
        TCP ヘッダが、 spec に指定されたコンマで区切られたオプションのリストを含む場合にのみマッチします。 サポートされている TCP オプションは

        mss (maximum segment size), window (tcp window advertisement), sack (selective ack), ts (rfc1323 timestamp), cc (rfc1644 t/tcp connection count) です。 ‘’! によって、特定のオプションを含まない指定が記述できます。

    established
        TCP パケットのみに適用されます。 RST または ACK ビットがセットされているパケットのみマッチします。

    setup
        TCP パケットのみに適用されます。 SYN ビットがセットされ ACK がセットされていないパケットのみマッチします。

    tcpflags spec
        TCP パケットのみに適用されます。 TCP ヘッダが spec に指定されたコンマで区切られたフラグのリストを含む場合にのみマッチします。 サポートされているフラグは、

        fin, syn, rst, psh, ack, urg です。 ‘’! によって、特定のフラグを含まない指定を記述できます。 tcpflags 指定を含むルールは、非 0 のオフセットを持つ断片化されたパケットに マッチすることはありません。 断片化されたパケットに関するマッチについての詳細は frag オプションを参照してください。

    icmptypes types
        ICMP パケットのみに適用されます。 ICMP タイプが types で指定されたリスト中に存在する場合にのみマッチします。 リストは範囲指定でも、タイプおのおのをコンマで区切ったものでも どちらの組み合わせでもかまいません。 サポートされている ICMP タイプは次の通りです:

        エコー返答 (0), 終点不到達 (3), 発信抑制 (4), リダイレクト (5), エコー要求 (8), ルータ広告 (9), ルータ要請 (10), 時間超過 (11), IP ヘッダ異常 (12), タイムスタンプ要求 (13), タイムスタンプ応答 (14), 情報要求 (15), 情報返答 (16), アドレスマスク要求 (17), アドレスマスク応答 (18)

    uid user
        user が送信したまたは受信する、 すべての TCP パケットと UDP パケットにマッチします。 user は、名前でも ID 番号でもマッチします。

    gid group
        group が送信したまたは受信する、 すべての TCP パケットと UDP パケットにマッチします。 group は、名前でも ID 番号でもマッチします。

トラフィックシェイパ設定
ipfw ユーティリティは、 dummynet(4) トラフィックシェイパへのユーザインタフェースも提供します。 シェイパは、ユーザが指定したマスクを IP ヘッダの異なったフィールドに 適用することにより、パケットを フロー (flow) に分割します。 同じフローに属するパケットは 2 つの異なったオブジェクトへ渡されます。 それは パイプ (pipe) または キュー (queue) と呼ばれるものです。 パイプ は、与えられたバンド幅、遅延時間、キューの長さ、パケット喪失率を もつリンクをエミュレートします。 このパラメータに従い、パケットはパイプ中を遷移します。

キュー は、WF2Q+ ポリシを実装するために使用する抽象化です。 キューは、各フローに対し、重みと参照パイプを関連付けます。 それから、同じパイプに結び付けられたすべてのフローは、 WF2Q+ ポリシに従い、 パイプによって固定されたレートでスケジュールされます。

ipfw パイプ設定書式は次の通りです。

pipe number config [bw bandwidth | device] [delay ms-delay] [ queue {slots | size}] [plr loss-probability] [mask mask-specifier] [buckets hash-table-size] [ red | gred w_q/min_th/max_th/max_p]

ipfw キュー設定書式は次の通りです。

queue number config [pipe pipe_nr] [weight weight] [ queue {slots | size}] [plr loss-probability] [mask mask-specifier] [buckets hash-table-size] [ red | gred w_q/min_th/max_th/max_p]

次のパラメータをパイプに対して設定可能です:

bw bandwidth | device
    バンド幅であり、単位は [K|M] {bit/s|Byte/s}. で測定します。

    値 0 (デフォルト) は無限のバンド幅を意味します。 単位は数値の直後に続けて書く必要があり、次のようにします。

        ipfw pipe 1 config bw 300Kbit/s queue 50KBytes

    数値の代りにデバイス名が指定された場合、 送信クロックは指定したデバイスから与えられます。 現在のところ、 tun(4) デバイスのみが ppp(8) と組み合わせて使用するために、この機能を提供しています。

delay ms-delay
    遅延時間であり、ミリ秒単位で指定します。 値は、クロックティックの倍数 (典型的には 10ms ですが、 カーネルを "options HZ=1000" で動作させて精度を 1ms 以下にすると良い ことが経験的に知られています) に丸められます。 デフォルト値は 0 であり、遅延無しを意味します。

queue {slots | sizeKbytes}
    キューの大きさであり、スロット数か KBytes です。 デフォルト値は 50 スロットであり、 イーサネットデバイスの典型的なキューの大きさです。 低速リンクではキューの大きさを短くすべきことに注意してください。 さもないと、トラフィックは甚大なキュー遅延による影響を受けてしまいます。 例えば、 50 個の最大イーサネットパケット (1500 バイト) は 600Kbit であり、 30Kbit/s のパイプでは 20 秒のキューを意味します。 より大きな MTU のインタフェースからパケットを受け取るときには、 より悪い結果となります。 例えば、ループバックインタフェースにおいて 16KB パケットを受け取るときです。

plr packet-loss-rate
    パケット喪失率です。 引数 packet-loss-rate は 0 と 1 の間の浮動小数点数であり、 0 は喪失無しを意味し、1 は 100% の喪失を意味します。 喪失率は内部的には 31 ビットで表現されます。

mask mask-specifier
    dummynet(4) では、フローごとのキューを生成可能です。 フロー識別子は、パイプ設定において指定される IP アドレス、ポート、プロトコルタイプでマスクすることで構築されます。 マスク後に同じ識別子を持つパケットは、同じキューに落ちます。 使用可能なマスク指定子は、次を組み合わせたものです: dst-ip mask, src-ip mask, dst-port mask, src-port mask, proto mask, all 。 最後の指定子は、 すべてのフィールドのすべてのビットが重要であることを意味しています。 pipe 設定中で使用される場合、 各フローにはパイプのレートに等しいレートが割り当てられます。 queue 設定中で使用される場合、 各フローにはキューの重みに等しい重みが割り当てられ、 同じパイプを構成するキューは重みに比例してバンド幅を共有します。

buckets hash-table-size
    様々なキューを格納するために使用するハッシュ表の大きさを指定します。 デフォルト値は 64 であり、 sysctl(8) 変数 net.inet.ip.dummynet.hash_size で制御され、使用可能な範囲は 16 から 1024 です。

pipe pipe_nr
    キューを指定したパイプに接続します。 複数のキュー (通常は異なった重み) を同一のパイプに接続可能です。 この場合、このキュー集合に対する集約レートを、このパイプが指定します。

weight weight
    このキューに適合するフローに使用する重みを指定します。 重みは 1..100 の範囲であることが必要であり、デフォルトは 1 です。

red | gred w_q/min_th/max_th/max_p
    RED キュー管理アルゴリズムを使用します。 w_q と max_p は 0 から 1 (0 を含みません) の範囲の浮動小数点数であり、 min_th と max_th はキュー管理用の閾値を指定する整数です (キューがバイト数で指定された場合は閾値はバイトで計算され、 そうでない場合はスロット数で計算されます)。 dummynet(4) は、gentle RED という変型 (gred) もサポートします。 RED の動作を制御するために、3 個の sysctl(8) 変数を使用可能です:

    net.inet.ip.dummynet.red_lookup_depth
        リンクがアイドルの時の、平均キューの計算精度を指定します (デフォルトは 256 であり、0 より大きい必要があります)

    net.inet.ip.dummynet.red_avg_pkt_size
        パケットサイズの平均の期待値を指定します (デフォルトは 512 であり、0 より大きい必要があります)

    net.inet.ip.dummynet.red_max_pkt_size
        パケットサイズの最大値の期待値を指定します。 キューの閾値がバイトの場合のみ使用されます (デフォルトは 1500 であり、0 より大きい必要があります)

チェックリスト
ルールを構成する際に考慮すべき重要な点を述べます。

•   かならず送信パケットと受信パケットの両方のパケットをフィルタリングします。 ほとんどのネットワークコネクションではパケットが双方向に流れることが必要です。

•   テストは細心の注意を払って行ないます。テストの際にはコンソールの近くにいる のがよいでしょう。 コンソールに近寄れない場合、 /usr/share/examples/ipfw/change_rules.sh にあるような自動回復スクリプトを使用してください。

•   ループバックインタフェースのことを忘れてはなりません。

細かい事柄

•   フラグメント化されたデータグラムが無条件で破棄される状況があります。 TCP パケットは、最低 20 バイトの TCP ヘッダを含まない場合、破棄されます。 UDP パケットは、完全な 8 バイトの UDP ヘッダを含まない場合、破棄されます。 ICMP パケットは、4 バイトの ICMP ヘッダ、 すなわち ICMP タイプとコードとチェックサムを含まない場合、破棄されます。 これらのパケットは、単に “pullup failed” としてログされます。 何故なら、パケット中に有意なログエントリを生成するだけの有用なデータが 含まれないかもしれないためです。

•   無条件で破棄されるもう 1 種類のパケットは、 フラグメントオフセットが 1 の TCP パケットフラグメントです。 これはパケットとしては有効なものですが、利用目的はファイアウォールを かいくぐることしかありません。 ログが有効な場合、 これらのパケットはルール -1 により破棄されたと報告されます。

•   ネットワーク越しにログインしている場合、 kld(4) バージョンの ipfw をロードすることはそれほど単純なことではありません。 以下のコマンドを奨めます。

        kldload /modules/ipfw.ko && \
        ipfw add 32000 allow ip from any to any

    これに引続き、同じような状況で

        ipfw flush

    とするのは良くありません。

•   システムセキュリティレベルが 3 以上に設定されている場合、 IP フィルタリストを変更できません (システムセキュリティレベルについては init(8) を参照してください)。

パケットの行き先変更
指定されたポートにバインドされた divert(4) ソケットは、 そのポートへ行き先変更されたパケットを、 全部受けとります。 宛先ポートにバインドされたソケットがない場合や、 カーネルがパケットの行き先変更ソケットをサポートするようには コンパイルされていない場合、 パケットは破棄されます。

SYSCTL 変数
ファイアウォールの動作を制御する sysctl(8) 変数の集合があります。 デフォルト値 (どの値が実際に使用されるかは sysctl で確認してください) と意味と共に、これらを以下に列挙します。

net.inet.ip.fw.debug: 1
    ipfw が生成するデバッグメッセージを制御します。

net.inet.ip.fw.one_pass: 1
    セットされると、 dummynet(4) パイプから出て来たパケットは、ふたたびファイアウォールを通さないようにします。 セットされない場合、pipe 処理のあと、 パケットは再びファイアウォールに挿入され、次のルールから再開されます。

net.inet.ip.fw.verbose: 1
    冗長なメッセージを出力するようにします。

net.inet.ip.fw.enable: 1
    ファイアウォールを動作可能にします。 この変数を 0 に設定すると、ファイアウォールをコンパイルして 仕込んでいてもファイアウォールなしで動作します。

net.inet.ip.fw.verbose_limit: 0
    冗長なファイアウォールが生成するメッセージの数を制限します。

net.inet.ip.fw.dyn_buckets: 256

net.inet.ip.fw.curr_dyn_buckets: 256
    動的ルールを保持するために使用するハッシュ表の設定サイズと 現在のサイズです。この値は 2 のべき乗にする必要があります。 ハッシュ表のサイズの変更は、表が空の場合のみ行なわれます。 したがって、実行中に表のサイズを変更するためには、 flush してルール集合を再ロードする必要があるでしょう。

net.inet.ip.fw.dyn_count: 3
    現在の動的ルールの数です (読み込み専用)。

net.inet.ip.fw.dyn_max: 1000
    動的ルールの最大値です。この限界にいきつくと、 古いルールが無効になるまでは、それ以上、動的ルールを 組み込むことはできません。

net.inet.ip.fw.dyn_ack_lifetime: 300

net.inet.ip.fw.dyn_syn_lifetime: 20

net.inet.ip.fw.dyn_fin_lifetime: 1

net.inet.ip.fw.dyn_rst_lifetime: 1

net.inet.ip.fw.dyn_udp_lifetime: 5

net.inet.ip.fw.dyn_short_lifetime: 30
    これらの値は、動的ルールの生存期間を秒単位でコントロールします。 最初の SYN 交換の際に、生存期間が short になり、 SYN を両方とも見た後に増やされ、最後の FIN 交換の間、 または RST が生じる際に再び減らされます。

使用例
次のコマンドは cracker.evil.org から wolf.tambov.su の telnet ポートへ送られるすべての TCP パケットを拒否するルールを追加します。

    ipfw add deny tcp from cracker.evil.org to wolf.tambov.su telnet

次のコマンドはクラッカーのネットワーク全体からホスト my への すべてのコネクションを拒否します。

    ipfw add deny ip from 123.45.67.0/24 to my.host.org

最初に効率良く (動的ルールを用いずに) アクセスを制限する方法は、 次のルールを用いることです。

    ipfw add allow tcp from any to any established
    ipfw add allow tcp from net1 portlist1 to net2 portlist2 setup
    ipfw add allow tcp from net3 portlist3 to net3 portlist3 setup
    ...
    ipfw add deny tcp from any to any

最初のルールは通常の TCP パケットにすぐにマッチしますが、 最初の SYN パケットにはマッチしません。 指定した発信元/宛先の組の SYN パケットのみ、次の setup ルールにマッチします。これら以外の SYN パケットは、最後の deny ルールにより却下されます。

にせの TCP パケットを含む怒涛の攻撃 (flood attack) から サイトを保護するためには、次の動的ルールを用いた方が安全です。

    ipfw add check-state
    ipfw add deny tcp from any to any established
    ipfw add allow tcp from my-net to any setup keep-state

これらのルールにより、ファイアウォールは、自分たちのネットワークの 内側から到着する通常の SYN パケットで始まるコネクションに対して のみ動的ルールを組み込みます。動的ルールは、最初の check-state ルール、または、 keep-state ルールに遭遇した時点でチェックされます。 ルール集合のスキャン量を最小にするために、 check-state ルールは、ルール集合の最初のほうに置くことになるのが普通です。 実際の燃費は変動します。

ユーザが開ける接続数を制限するには、次のタイプのルールを使用可能です:

    ipfw add allow tcp from my-net/24 to any setup limit src-addr 10
    ipfw add allow tcp from any to me setup limit src-addr 4

前者 (ゲートウェイ上で動作することを仮定) は、/24 ネット上の各ホストが 最大 10 個の TCP 接続を開くことを許します。 後者は、サーバ上に設定可能であり、 単一のクライアントが同時に 4 個を越える接続を使用できないようにします。

注意: ステートフルなルールは、怒涛の SYN 攻撃により極めて大量の動的ルールを 作ってしまい、サービス不能攻撃を受けることになる可能性があります。 ファイアウォールの動作をコントロールする sysctl(8) 変数に従いファイアウォールが動作することによって、 このような攻撃の影響を部分的にでも制限することはできます。

次はカウントされている情報とタイムスタンプ情報を見る list コマンドのよい例です。

    ipfw -at list

これはタイムスタンプを省略して次のように指定できます。

    ipfw -a list

これは次の指定と等価です。

    ipfw show

次のルールは 192.168.2.0/24 からのすべての受信パケットを、5000 番のポートに 行き先変更するものです。

    ipfw divert 5000 ip from 192.168.2.0/24 to any in

次のルールは、 ipfw と dummynet(4) をシミュレーションなどで使う際の使用方法を示しています。

このルールは 5% の確率でランダムにパケットを落します。

    ipfw add prob 0.05 deny ip from any to any in

同様の効果は dummynet パイプで実現可能です:

    ipfw add pipe 10 ip from any to any
    ipfw pipe 10 config plr 0.05

人工的にバンド幅を制限するためにパイプを使用可能です。 例えばルータとして動作するマシン上で、 192.168.2.0/24 上のローカルクライアントからのトラフィックを制限したい場合、 次のようにします:

    ipfw add pipe 1 ip from 192.168.2.0/24 to any out
    ipfw pipe 1 config bw 300Kbit/s queue 50KBytes

out 指示子を使用しているので、ルールが 2 度使われないことに注意してください。 ipfw ルールは、実際には、 入力パケットと出力パケットの両方に適用されることを覚えておいてください。

バンド幅に制限がある双方向リンクをシミュレートする場合、 正しい方法は次の通りです:

    ipfw add pipe 1 ip from any to any out
    ipfw add pipe 2 ip from any to any in
    ipfw pipe 1 config bw 64Kbit/s queue 10Kbytes
    ipfw pipe 2 config bw 64Kbit/s queue 10Kbytes

上述の方法は非常に有用な場合があり、 例えばあなたの装飾的なウェブページが 低速リンクのみで接続されている在宅ユーザにどう見えているか 知りたい場合に有用です。 半二重メディア (例えば appletalk, Ethernet, IRDA) をシミュレートしたい 場合を除き、単一のパイプを両方の方向に使用すべきではありません。 両方のパイプが同じ設定である必要はないので、 非対称リンクをシミュレート可能です。

RED キュー管理アルゴリズムを使用してネットワーク性能を検証するには、 次のようにします:

    ipfw add pipe 1 ip from any to any
    ipfw pipe 1 config bw 500Kbit/s queue 100 red 0.002/30/80/0.1

トラフィックシェイパの他の典型的な応用は、 いくばくかの通信遅延を導入することです。 これは、遠隔手続き呼び出しを多用するアプリケーションで、 バンド幅よりも接続のラウンドトリップ時間がしばしば制約条件となる アプリケーションに、大きな影響を与えます:

    ipfw add pipe 1 ip from any to any out
    ipfw add pipe 2 ip from any to any in
    ipfw pipe 1 config delay 250ms bw 1Mbit/s
    ipfw pipe 2 config delay 250ms bw 1Mbit/s

フローごとのキューはさまざまな用途に有用です。 非常に単純な用途は、トラフィックの計数です:

    ipfw add pipe 1 tcp from any to any
    ipfw add pipe 1 udp from any to any
    ipfw add pipe 1 ip from any to any
    ipfw pipe 1 config mask all

上述のルールセットは、 すべてのトラフィックに対するキューを生成 (して統計情報を収集) します。 パイプには制限をつけていないので、統計情報を集める効果しかありません。 最後のルールだけでなく 3 個のルールが必要なことに注意してください。 ipfw が IP パケットのマッチを試みるときにポートを考慮しないため、 別々のポート上の接続は我々には同じものに見えます。

より洗練された例は、 ネットワークの出力トラフィックを、 ネットワーク毎に制約するのではなく、ホスト毎に制約するものです:

    ipfw add pipe 1 ip from 192.168.2.0/24 to any out
    ipfw add pipe 2 ip from any to 192.168.2.0/24 in
    ipfw pipe 1 config mask src-ip 0x000000ff bw 200Kbit/s queue 20Kbytes
    ipfw pipe 2 config mask dst-ip 0x000000ff bw 200Kbit/s queue 20Kbytes

実装に関する注
パケットが ipfw に処理される回数は様々です。 基本的には、カーネル関数 ip_input(), ip_output(), bdg_forward() が起動される度に ipfw が起動されます。 つまり、 終点の 1 個がローカルホストにある接続では、パケットは 1 回処理されます。 終点の 2 個両方がローカルホストにある接続または このホストがルーティングするパケットに対しては、2 回処理されます (ゲートウェイとしての動作)。 このホストがブリッジするパケットに対しては、1 回処理されます (ブリッジとしての動作)。

関連項目
cpp(1), m4(1), bridge(4), divert(4), dummynet(4), ip(4), ipfirewall(4), protocols(5), services(5), init(8), kldload(8), reboot(8), sysctl(8), syslogd(8)

バグ
この数年で文法が大きくなってしまい、 非常にすっきりしているとは言い難いです。

WARNING!!WARNING!!WARNING!!WARNING!!WARNING!!WARNING!!WARNING!!

このプログラムはコンピュータをかなり使いにくい状態にしてしまう 可能性があります。 はじめて使用する時はコンソール上で実行し、理解していない操作は 絶対に実行しない ようにして下さい。

連続したエントリの操作もしくは追加に際し、 サービス名やプロトコル名は使用できません。

入ってきたパケットの断片 (フラグメント) が divert によって行き先を変更されるか tee されると、ソケットに配送される前にパケットは再構成されます。

tee ルールにマッチするパケットは、 即時に受理されるべきではなく、ルールリストを更に通るべきです。 これは、以降のバージョンで修正されるかもしれません。

作者
Ugen J. S. Antsilevich, Poul-Henning Kamp, Alex Nash, Archie Cobbs, Luigi Rizzo.

-nosplit API は Daniel Boulet が BSDI 用に記述したコードに基づいています。

dummynet(4) トラフィックシェイパは Akamba Corp がサポートしました。

歴史
ipfw は、 FreeBSD 2.0 で最初に現れました。 dummynet(4) は FreeBSD 2.2.8 から導入されました。 ステートフル拡張は、 FreeBSD 4.0 から導入されました。