IPFW(8)

名称
ipfw - IPファイアウォール制御ユーティリィティ

書式
ipfw [ -q] file ipfw [ -f | -q] flush ipfw [ -q] zero [number ...] ipfw delete number ... ipfw [-aftN] list [number ...] ipfw [ -ftN] show [number ...] ipfw [ -q] add [number] action [log] proto from src to dst [via name | ipno] [options]

解説
書式の 1 行目のようにファイル名を指定した場合は、 file を 1 行ずつ、引数として読み込みます。

ipfw はパケットごとに、マッチするルールが見つかるまでルールリストを調べます。 各ルールにはパケット数とパケットサイズの 2 つのカウンタが用意されていて、 パケットがマッチするとカウンタ値は更新されます。

全ルールは 1 から 65534 の範囲の行番号で順序付けられます。この番号によって ルールの並べ変えと削除を行ないます。 ルールのマッチングは昇順で行なわれ、最初にマッチしたものが適用されます。 複数のルールが同じ番号を共有することも可能です。この場合はルールが追加された 順序でマッチングが行なわれます。

番号を指定せずにルールを追加した場合は、直前のルールの番号に 100 を加えたものと なります。 ルールの番号が 65534 より大きい場合は、新しいルールは最後のルールに追加されます 。

delete 操作は number で指定された番号を持つ最初のルールを、もし有れば、削除します。

list 操作は現在のルール一覧を出力します。

show 操作は `ipfw -a list' と同じ結果を出力します。

zero 操作は number で指定された番号を持つルールのカウンタをクリアします。

flush 操作は全ルールを削除します。

記号 `#' で始まる行および空行は無視されます。

どんな場合でも次のルールは存在します:

    65535 deny all from any to any

全パケットを拒否するのがデフォルトのポリシーです。 これを修正し、必要なルールを設定して下さい。

しかしながら、カーネルオプション “IPFIREWALL_DEFAULT_TO_ACCEPT” が有効な場合、ルールは次のようになります:

    65535 allow all from any to any

このバリエーションでは全てが通過可能です。 このオプションを有効にしてよいのは特定の状況だけであり、 例えば通常は解放しており、 必要に応じてサービス拒否 (denial-of-service) フィルタとなる ファイアウォールシステムを使用する場合がこれに該当します。

オプションは以下のものが利用可能です。

-a  list 操作の時、カウンタの値を表示します。 show の項を参照のこと。

-f  操作を実行する際に確認メッセージを表示しません。 flush 操作も無条件に実行されます。 （注意） プロセスに tty が関連付けられていない場合には、 このオプションが指定されているものとして実行されます。

-q  ルールを add, zero, flush する際に、メッセージの出力を抑制します ( --f も含まれます)。 このオプションは、リモートログインセッションでルールを調整する際に、 (例えば sh /etc/rc.firewall のようにして)スクリプトの中から複数の ipfw コマンド を 実行する場合や、 多数の ipfw ルールを記述したファイルを用いる場合に 便利です。 flush 操作が通常の(冗舌な)状態(デフォルトのカーネルの設定) で実行されると、メッセージが出力されます。 ここで、すべてのルールは削除されるので、メッセージをログインセッションに 送ることができず、ログインセッションがクローズされてしまうので、 残りのルールセットは実行されません。 この状態を修復するにはコンソールへのアクセスが必要となります。

-t  list 操作の時に、最後にマッチしたパケットのタイムスタンプを表示します。

-N  IPアドレスとサービス名をリゾルブしてホスト名で表示します。

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 の (RST) を送信し、終了します。

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

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

tee port
    マッチするパケットのコピーを port で指定されたポートにバインドされている divert(4) ソケットに送り、引続きマッチングを行ないます。 この機能は未実装です。

fwd ipaddr [,port]
    マッチしたパケットの次のホップを ipaddr に変更します。これはドット付き 4 つ組の IP アドレスでもホスト名でもよいです。 ipaddr が直接到達可能なアドレスではない場合、その IP に対して ローカルルーティングテーブルでみつかる経路を使用します。 ipaddr がローカルアドレスの場合、 リモートホストからこのシステムにパケットが到着すると、 そのパケットをローカルマシンの port に転換します。 その際、 ソケットのローカルアドレスは、 パケットの元々の宛先の IP アドレスのままとします。 これは透過的プロキシサーバのためにあります。 IP が ローカルアドレスではない場合、ポート番号は (指定されていても) 無視され、 ルールはシステムから出て行くパケットに対してのみ適用されます。 また、」 パケットローカルに生成された時にもアドレスをローカルポートにマップします。 検索はルールがマッチしたときに終了します。 ポート番号が与えられなかった場合、パケット中のポート番号が使用され、 外部マシンのポート Y へのパケットは ローカルポート Y へ転送されます。 カーネルは、 オプション IPFIREWALL_FORWARD 付きでコンパイルされている必要があります。

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

パケットが divert や tee のどちらかひとつ以上、もしくは両方の組み合わせの、複数のルールにマッチした場合、 最後のものを除き、無視します。

カーネルが IPFIREWALL_VERBOSE オプション付きでコンパイルされている場合に、``log'' が指定されているルールと マッチした時は、メッセージをコンソールに表示します。 もし、 IPFIREWALL_VERBOSE_LIMIT オプション付きでコンパイルされている場合、一連のルールに対し指定されたパケット 数を受信した後、メッセージの表示を中止します。 パケットのカウンタをクリアすれば再びメッセージを出力します。

コンソールへの表示とその制限数は、 sysctl(8) を通し、直接設定できます。

proto:

ip  全パケットがマッチします。別名 all も使えます。

tcp TCP パケットのみマッチします。

udp UDP パケットのみマッチします。

icmp
    ICMP パケットのみマッチします。

<number|name>
    指定されたプロトコルのパケットのみマッチします ( /etc/protocols のリストを参照の事)

src と dst:

<address/mask>
    [ports]

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

ipno
    IP番号を 1.2.3.4 の形式で指定します。指定されたアドレスのみがマッチします。

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[,...]]

ポート番号の代わりに(ファイル /etc/services から取った)サービス名を使用できます。 port-port の書式で、最初の値に限り範囲指定できます。 列挙出来るポート数は /usr/src/sys/netinet/ip_fw.h で IP_FW_MAX_PORTS として定義されています。

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

マッチングのルールは、入ってくるパケットか、出ていくパケット、もしくはその両方 に対し適応されます。 in を指定すれば、入ってくるパケットのみにルールを適応します。 out を指定すれば、出ていくパケットのみに適応します。

特定のインタフェースを通過するパケットには、 via を用いてインタフェースを指定します:

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:

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

in  ネットワークから受信したパケットのみマッチします。

out ネットワークへ送信するパケットのみマッチします。

ipoptions spec
    IP ヘッダが、 spec に指定されたコンマで区切られたオプションのリストを含む場合にのみマッチします。 サポートされている IP オプションは ssrr (strict source route), lsrr (loose source route), rr (record packet route), ts (timestamp) です。 ``!'' によって、特定のオプションを含めないよう指定できます。

established
    RST または ACK ビットがセットされているパケットのみマッチします。 このビットがセットされることがあるのは TCP のパケットのみです。

setup
    SYN ビットがセットされ ACK がセットされていないパケットのみマッチします。 このビットがセットされることがあるのは TCP のパケットのみです。

tcpflags spec
    TCP ヘッダが spec に指定されたコンマで区切られたフラグのリストを含む場合にのみマッチします。 サポートされているフラグは、 fin, syn, rst, psh, ack, urg です。 ``!'' によって、特定のフラグを含めないよう指定できます。 tcpflags 仕様を含むルールは非 0 のオフセットを持つ断片化されたパケットに マッチすることはありません。 断片化されたパケットに関するマッチについての詳細は frag オプションを参照してください。

icmptypes types
    ICMP タイプが types で指定されたリスト中に存在する場合にのみ適用されるルールとなります。 リストはレンジの組み合わせでも、各タイプをコンマで区切ったものでもどちらでも かまいません。

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

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

•   テストは細心の注意を払って行ないます。テストの際にはコンソールの近くにいる のがよいでしょう。

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

長所
ファイアウォールが常に破棄するパケットが 1 種類あります。 フラグメントオフセットが 1 のフラグメントパケットです。 これはパケットとしては有効なものですが、利用目的はファイアウォールを かいくぐることしかありません。

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

    modload /lkm/ipfw_mod.o && \
    ipfw add 32000 allow all from any to any

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

    ipfw flush

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

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

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

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

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

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

次はカウントされている情報とタイムスタンプを見る例です

    ipfw -at l

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

    ipfw -a l

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

    ipfw divert 5000 all from 192.168.2.0/24 to any in

関連項目
divert(4), ip(4), ipfirewall(4), protocols(5), services(5), reboot(8), sysctl(8), syslogd(8)

バグ

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

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

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

入ってきたパケットの断片(フラグメント)が divert によって行き先を変更されると、ソケットに配送される前に、組み立て直しをします。 それに対し、 tee を経由した断片(フラグメント)は、組み立て直しされません。

ポートの別名でダッシュ (-) を含むものは、リストの最初には書けません。

作者
Ugen J. S. Antsilevich, Poul-Henning Kamp, Alex Nash, Archie Cobbs. API は Daniel Boulet が BSDI 向けに記述したコードに基づいています。

歴史
ipfw は、FreeBSD 2.0 で最初に現れました。