オフィシャルサイト: netfilter.org
日本語man: Manpage of IPTABLES (JM)

iptables

非常に役に立つ HOWTO に、 Oskar Andreasson の Iptables tutorial がある。日本語訳が存在しなかったので翻訳した (2006/01 本家にも掲載されました - Thank you, Oskar !)。

iptables は、カーネルが利用するIPパケットフィルタのルールを、操作するためのユーティリティ。カーネルそのものと密接に関係しており、kernel-2.2 では ipchains が使われていた。kernel-2.4 以降、 iptables が標準となる。ipchains とは比べものにならないほど、膨大な種類の操作オプションが用意されている。ipchains との最も大きな違いは、パケットを既存のコネクションとの関係性によって識別できる「コネクショントラッキング (接続追跡)」 というメカニズムを実装していること。この conntrack 機構のおかげで、いわゆる「ステートフルファイヤーウォール」が実現でき、主接続の他にも不特定ポートの子接続を張りたがる FTP や IRC などといった通信に対しても、1024 より上のポートを全部開けておくというような危なっかしい設定をする必要は無くなった。最低限のポートを開放するだけ (FTP なら 21 だけ) で、必要な通信を阻害することなく、厳格な規制が掛けられる。

RedHat 7.x では、kernel は 2.4 でありながら、言いなりでセットアップすると iptables と ipchains が両方ともインストールされてしまう。ipchains が動いている限り、iptables は働かないので、ipchains を rc から外すなどして止めなくてはならない (さっさとアンインストールすべし)。

Table of Contents

テーブルの階層構造

テーブル
チェーンのまとまり。filter, nat, mangle の3種がある。組み込まれているチェーンは、テーブルの種類によって少し異なる。
チェーン
ルールのまとまりによるフィルタリングアルゴリズム。PREROUTING, INPUT, OUTPUT, FORWARD, POSTROUTING 及び、ユーザ定義チェーンがある。
ルール
「パケットがこれこれだったら、そいつをこう操作せよ」 という指示。操作は ACCEPT, DROP, REJECT, LOG, RETURN, TOS, TTL, MARK, DNAT, SNAT, MASQUERADE, QUEUE, REDIRECT などか、その他拡張ターゲットのうちいずれか。テーブル-チェーンの種類によって、指定できる動作は異なる。

PRE とはいつか、POST とはどの時点か、など、知っておいたほうがいいが、とても語り尽くせない。Iptables Tutorial (FrozenTux - Oskar Andreasson) がものすごく役に立つ。読んでいるうちに、どこにも日本語訳がないことがわかったので全文訳した - Iptables チュートリアル 全文訳 (翻訳ミスを見つけたら指摘をお願いします)。

ルールの書式
基本書式:
iptables [-t table] command rule

大文字と小文字は区別される。以下、command 部、rule 部に分けて説明。

コマンド部

ルール操作に関する主なコマンド

"-t table " を省略した場合、filter テーブルを指定したのと同じ意味となる。

[-t table] -A chain rule Append。チェーンの最後尾にルールを加える
[-t table] -D chain (rule|rule_No.) Delete。ルールの正確な記述または番号で指定したルールを削除
[-t table] -I chain [rule_No.] rule Insert。番号で指定した位置にルールを挿入。番号を省略するとチェーンの先頭に入る
[-t table] -R chain rule_No. new_rule Replace。rule_No. で指定したルールを new_rule で置き換え

チェーン操作に関する主なコマンド

"-t table " を省略した場合、-N, -P では上記と同じ、-F, -Z, -L, -X はすべてのテーブルが対象となる。

[-t table] -N new_chain_name New。新規のユーザ定義チェーンを作成する
[-t table] -P chain policy Policy。チェーンの基本ポリシーをセットする。ルールでドロップして残りは受け入れる (ACCEPT) か、ルールでアクセプトして残りを拒否する (DROP) かのいずれか。ユーザ定義チェーンには使えない
[-t table] -F [chain] Flush。指定した chain のルールをすべて削除 (-D を一挙に行うのと同義)。chain を省略すると table 内の全チェーンが対象に
[-t table] -X [chain] 指定したユーザ定義チェーンそのものを削除する。ただし、他のチェーンのターゲットとして使用されているチェーンは削除できない。chain を省略するとすべての ユーザ定義チェーン を削除
[-t table] -Z [chain] Zero。指定したチェーン中のパケットカウンタをゼロに
[-t table] -L [chain] [options] 指定したチェーンにあるルールをリスト出力。options には以下のものがある:
-n : アドレスをリゾルブせず数字のまま表現。プロトコルも数字になる
--line-numbers : チェーン毎のルールNo.を表示。コマンド -D, -I, -R の事前準備として不可欠な手段

ルール部

ルール部の基本書式:
条件 -j 動作または他のユーザ定義チェーン[オプション]

パケットの一致条件に使用する主なパラメータ

"!" を挟むと意味を反転 (否定) できる。

-p [!] protocol tcp, udp, icmp, all のいずれか。all は「ありとあらゆるプロトコル」ではなく、tcp, udp, icmp を指す。指定無しは all と同じ
-s [!] address[/mask] 送信元アドレス。ネットマスクは4オクテット書式、CIDR書式とも可
-d [!] address[/mask] 宛先アドレス
-i [!] interface[+] 入ってくるインターフェイス。eth+ などとすると eth0, eth1.. .にマッチ
-o [!] interface[+] 出て行くインターフェイス

条件の拡張

-m module

を使ってカーネルモジュールをロードすると、さらに様々なパケットマッチが行える。ある種のモジュールはパラメータに応じて自動的にロードされるので、"-m module " は省略可能なこともある。RedHat系では、デフォルトでかなりの種類のパケットマッチカーネルモジュールがコンパイルされているため、カーネルのリビルドは滅多に必要とならない。どうしても動かない場合や、モジュールのロード状態を確認したいときは、lsmod してみるとよい。

以下が、主なモジュールとその機能の超抜粋。マッチ拡張はこの他にも山のようにある。

tcp モジュール

--sport [!] port[:port_end] 送信元ポート。単port または port から port_end の範囲指定
--dport [!] port[:port_end] 宛先ポート
--tcp-flags [!] test[,test..] set test で列挙されたTCPフラグ (ACK,SYNなど) のうち set だけが立ったパケットにマッチ
[!] --syn 上記の省略表記。"--tcp-flags SYN,RST,ACK SYN" と同義

udp モジュール

--sport [!] port[:port_end] 送信元ポート。単 port または port から port_end の範囲指定
--dport [!] port[:port_end] 宛先ポート

icmp モジュール

--icmp-type [!] type ICMPパケットのタイプで判定。タイプ数字、タイプ名による指定とも可。使用可能なタイプ名は "iptables -p icmp -h" で見れる。タイプ 0 (echo-reply) と 8 (echo-request) だけ通せば、とりあえず ping は成立する

state, conntrack モジュール

パケットが既存のコネクションと関連性があるか、あればどういった関連性かによって、パケットのマッチを行う。state モジュールをロードすると conntrack (コネクション追跡) モジュールもロードされる (OS や ディストリビューション、設定方法によっては、あらかじめ conntrack モジュールを modprobe しておかなくてはならない場合もある)。

--state STATE[,STATE..] 接続とパケットとの関係性によってマッチングを行う

STATE には以下の種類がある:

ESTABLISHED 過去に要求->応答 が行われた接続に属するパケット。または、そのパケットによって要求 -> 応答 のセットが確立するパケット。
RELATED ESTABLISHED な接続によって開かれた新たな接続に属するパケット。例えばFTPのコントロールポートによって開かれるFTPデータストリーム用不特定ポートや、HTTPの子ポートなど。
NEW まだ何らの応答も行われていない、初めてのパケット。
INVALID 上記のどの状態にも当てはまらないパケット。大抵は DROP すべきパケット。

multiport モジュール

飛び飛びのポートやポート範囲を一度に指定 (最大15個) できる。 -p tcp または -p udp と組み合わせないと働かない。

--sports port,port[,port..] 送信元ポート
--dports port,port[,port..] 宛先ポート
--ports port,port[,port..] 送信元と宛先ポートがともに port である場合にマッチ

動作 (ジャンプターゲット) の主なもの


ACCEPT 受け入れる
DROP 黙って捨てる
REJECT [--reject-with reply_type] パケットを捨てると同時に、送り主には ICMP メッセージや、RST パケット (来たのがTCPパケットであった場合に限る) を返して終わる。返すメッセージは --reject-with xxx オプションで指定できる。xxx は勝手な文字列等ではなく、ICMP プロトコルで規定された様々なメッセージタイプか、tcp-reset (TCP の リセットパケット) に限る。オプションを指定しない場合にデフォルトで返される返答は "Port Unreachable" の ICMP メッセージ
DNAT --to-destination address[:port] 宛先アドレスを書き換える。書き換え先のアドレスを --to-destination 引数で指定し、これには、 192.168.1.1-192.168.1.8 といったように範囲 (ただし -p tcp-p udp を併用している場合に限る) を指定することも可能。 :port も指定すれば、ポートも同時に書き換えることも可能
SNAT --to-source address[:portA-portB] 送信元アドレスを書き換える。書き換え先のアドレスは --to-source 引数で指定し、これには、範囲を指定することも可能。通常、SNAT される際にはポートは書き換えされないが、複数のホストが同じ書き換え先アドレスを使いそうになった際には、自動的にポートも変換される。:portA-portB も指定しておく (ただし -p tcp-p udp を併用している時に限る) と、そうした際の書き換え先ポートを、portA から portB までの範囲に絞り込むことができる
MASQUERADE [--to-ports port[-port]] 言ってみれば、SNAT の自動化バージョン。パケットの送信元アドレスを、パケットが入ってきたインターフェースのアドレスへと書き換える。変更先のアドレスは自動的に判断されるので、指定の必要がない (指定できない)。SNAT と同様にポートナンバーやその範囲を制限することもできる。ただし、この --to-ports が指定できるのは、そのルールが -p tcp-p udp を併用している場合のみ。マスカレードは、書き換え先のアドレスを決定するために、処理の度に特定のインターフェースのIPを調べるので、SNAT よりもややマシンパワーを食う。インターフェースのアドレスが固定ならば、マスカレードを安易に使わずに SNAT を使うべき
LOG [--option] syslog に渡す。渡す際のオプションを指定することも可能で、指定可能なオプションには、--log-level x (x は debug, info, notice などの syslog レベル), --log-prefix "yyy " (yyy は各ログの頭に追記する任意の文字列) などがある。他のターゲットとは異なり、この処理を受けた後も、パケットはチェーンを進み続けるので、他のルールでも処理を受ける可能性も残される。例えば、LOGターゲットを持つルールの次に、DROPターゲットを持つルールを同じ評価条件を仕掛けて書いておけば、「パケットが何々だったらLOGを採ってから捨てる」 という合わせ技が可能
RETURN このターゲットにマッチした時点で、そのパケットはそのチェーンのどのルールにもマッチしなかったのと同じ扱いになる。組み込みチェーン内であれば、そのチェーンのポリシーを適用する。ユーザ定義チェーンに飛ばされていた時には、その呼び出し元 (親) チェーンへ戻す
user_defined_chain user_defined_chain で指定したユーザ定義チェーンへ迂回させる。飛ばされ先のチェーンでマッチしなかったら、パケットはこのチェーンに戻ってきて、このルールの次のルールから先で引き続き評価を受ける