この章は、あなたの必要に叶うパケットフィルタを構築するために、実際に知っておかなければならないことを全て説明します。
カーネルは起動時に 3つのルールリストを保持しています。
これらのリストはファイアウォールチェイン、または単にチェインと呼ばれます。
3つのチェインは、 input, output そして forward と呼ばれます。
パケットが (例えば、イーサネットカードを通じて) 入って来ると、カーネルはそのパケットの「運命」を決定するために input
チェインを使います。
パケットがこのステップで生き残ると、カーネルはパケットを次にどこに送るかを決定します。(これをルーティングと呼びます。)
パケットが他のマシンへ行くと定められているならば、 forward
チェインを調べます。
最後に、パケットが出力される前に、カーネルは output
チェインを調べます。
1つのチェインは複数のルールのチェックリストから構成されています。 各々のルールは「もし、パケットのヘッダーがこんなだったら、パケットをこのようにしなさい」と指示します。 もし、あるルールがパケットとマッチしなければ、チェイン内の次のルールが調べられます。 最終的に、調べるルールが無くなったら、カーネルはそのチェインのポリシー(方針)を見て何をするか決めます。 セキュリティ意識の強いシステムでは、このポリシーは普通、パケットを DROP するようにカーネルに指示します。
ASCII アートファンのために、マシンに入来するパケットの完全な通り道をここに記します。
(訳注: この文書では日本語文字コードを用いた "JIS アート" を作成しております。
いわゆる全角文字と半角文字が混在する "JIS アート" を、 Netscape Navigator/Communicator や Microsoft Internet Explorer で表示させると、半角文字の幅と全角文字の幅の比が一致しない為に、『ガタガタに崩れた図面』になってしまいます。
html 版 を見る際には、 lynx や w3m 等のテキストブラウザをお薦めします。)
┌──────────────────────────────────┐ │ lo インターフェース│ │ ACCEPT/ │ ↓ REDIRECT ┏━━━━━┓ ┌────┐ ACCEPT│ →チ→正→┌────┐→マ→┃ルーティン┃→│forward │──→┌────┐→ ェ 当 │ input │ ス ┃グの決定 ┃ │チェイン│┌─→│ output │ ッ 性 │チェイン│ カ ┗━━━━━┛ └────┘│┌→│チェイン│ ク │ └────┘ レ │ │ ││ └────┘ サ │ │ ー ↓ │ ││ │ ム │ │ ド ローカルプロセス ↓ ││ ↓ │ ↓ ↓ 外 │ DENY/ ││ DENY/ │ DENY DENY/ し │ REJECT ││ REJECT ↓ REJECT │ │ ││ DENY │ └──────────┘│ └────────────────┘以下に各々の段階での説明を逐一記します。
パケットが幾つかの方法にて壊されていないかをテストします。 パケットが壊れていれば、否定されます。
各々のファイアウォールチェインの前にそれらのパケットの正当性のチェックが一つあります。 しかし、 input チェインのそれが最も重要です。 幾つかの異常なパケットは規則チェックコードを混乱させる恐れがあります。 それらはここで否定されます。 (これが発生すると syslog にメッセージが記録されます。)
パケットがテストされる最初のファイアウォールチェインです。
チェインの判断が DENY
(否定) または REJECT
(拒絶) でなければ、
パケットの動きは続きます。
パケットが以前にマスカレードされたパケットに対する応答なら、マスカレードが外され、 output
チェインまで一気に処理を飛ばします。
IP マスカレードを使っていなければ、意図的に上記の図から消去できます。
(パケット中の)宛先フィールドはルーティングコードによって、このパケットがローカルプロセスに行くべきなのか (ローカルプロセスの章を参照して下さい) 、リモートマシンに転送されるのか (フォワードチェインの章を参照して下さい) を決定するために調べられます。
マシン上で稼働するプロセスはルーティングの決定の段階の後のパケットを受け取れると共に、パケットを送信できます。 (送信パケットはルーティング決定ステップを経て、 output チェインを通過します。)
ローカルプロセスからのパケットがローカルプロセスに行くものならば、それらは `lo' と設定されたインターフェースで output チェインを通り抜け、再び `lo' インターフェースで input チェインに入ります。 lo インターフェースは通常ループバックインターフェースと呼ばれます。
パケットがローカルプロセスで生成されたものでないなら、 forward チェインがチェックされ、さもなくば、パケットは output チェインへ行きます。
このチェインにはこのマシンから他へ転送される全てのパケットが通過します。
このチェインには出力される直前の全てのパケットが通過します。
先ず、この文書にて扱うお手持ちの ipchains のバージョンを、以下のように参照しましょう:
$ ipchains --version
ipchains 1.3.9, 17-Mar-1999
注記として、1.3.4 (`--sport' のような長いオプションがありません) か、 1.3.8 以降をお薦めします; これらは大変安定しています。
個々の事項についてのもっと詳しい説明が必要なら、ipchains にはかなり詳しいマニュアルページ (man ipchains
) があります。
特に詳しく内容を知りたいなら、プログラミングインターフェース(man 4 ipfw
) か、或は 2.1.x のカーネルソース内の net/ipv4/ip_fw.c
ファイルを調べると良いでしょう。
これらは (明らかに) 信頼できます。
ソースパッケージには Scott Bronson による素晴らしいクィックリファレンスカードもあります。 A4判または US レターサイズの PostScript(TM) の両方があります。
ipchains
を使って色々なことができます。
先ず、全体のチェインを管理する操作。
あなたは 3つの組み込み済みチェインである、 input
, output
, forward
(これらは削除できません)から始めます。
チェイン内のルールを操作するには様々な方法があります:
マスカレーディングに関する操作が少ないながらあります。
それらを配置するに相応しい場所の要望の為に ipchains
に含まれています。
最後の (そして恐らく最も便利な) 機能は、指定したパケットが指定したチェインを通過するなら、そのパケットがどうなるのかを試しにチェックできることです。
ipchains コマンドが起動される前 (注意: 幾つかのディストリビューションでは初期化スクリプト内で ipchains を起動しています) は、組み込み済みのルール (`input', `forward' と `output') 以外には何もありません。 そして各々のチェインは ACCEPT (許可) のポリシーに設定されています。 これは全てを受け入れることと等価です。
ルールを操作すること ― それは ipchains の基本です。 ほとんどの場合、普通、あなたは追加 (-A) と削除 (-D) コマンドを使うことになるでしょう。 残りのコマンド(挿入の -I と置換の -R )は、これらの概念を単純に(機能)拡張したものです。
各々のルールには、パケットが満たすべき条件のセットと、条件が満たされたときにすること(‘ターゲット’)を指定します。 例えば、IP アドレス 127.0.0.1 からやって来る全ての ICMP パケットを破棄したいとします。 その場合の条件はプロトコルが ICMP で、ソースアドレスが 127.0.0.1 で、ターゲットは `DENY'(否定) です。
127.0.0.1 は `ループバック' インターフェイスで、それはあなたのマシンが実際のネットワークに繋がっていなくても存在します。 `ping' プログラムでそのようなパケット (ping は 単純に ICMP タイプ8 (エコー要求)を送り、全ての協力的なホストは親切にも ICMP タイプ 0 (エコー応答)のパケットでそれに応えます)を発生させるのに使います。 これはテストに役立ちます。
# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.2 ms
--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.2/0.2/0.2 ms
# ipchains -A input -s 127.0.0.1 -p icmp -j DENY
# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
--- 127.0.0.1 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
#
ご覧のとおり最初の ping が成功しています(`-c 1' は ping にパケットを 1個だけ送るように指示しています)。
次にルールを `INPUT' チェインに追加 (-A) します。ルールの指定は、 127.0.0.1 から (`-s 127.0.0.1') でプロトコル ICMP (`-p icmp') のパケットは、DENY へジャンプする (`-j DENY') です。
それから 2番目の ping でルールをテストします。 帰って来ない応答を待つのを ping が止めるまで少しの間があるでしょう。
ルールを削除するには 2通りの方法があります。 1番目は、例えば、 input チェインにはルールが 1個だけしかないのを分っている場合では、番号を使って以下のように削除できます:
# ipchains -D input 1
#
INPUT チェインのルール番号 1 を削除。
2番目の方法は -A コマンドをそっくり写して -A を -D に置き換えたものです。 これはルールが複雑なチェインの場合で、例えば、取り除きたいのがルール 37 だと探し当てるためにルールを数えたくない場合に有効です。 この場合、次のように使います:
# ipchains -D input -s 127.0.0.1 -p icmp -j DENY
#
-D の書き方は、 -A (または -I か -R) コマンドの時と正確に同じオプションでなければなりません。
もし、同一チェイン中に複数のマッチするルールがあったら、最初のものだけが削除されます。
これまでに、プロトコルを指定する `-p' オプションと、ソースアドレスを指定する `-s' オプションを見てきましたが、この他にもパケットの特徴を指定する様々なオプションがあります。 これから、その概要をあますところなくお話します。
ソース (-s) 及び宛先 (-d) IP アドレスは 4通りの指定方法があります。 もっとも一般的な方法は完全に記述された名前(FQDN)を使うことで、例えば、`localhost' とか `www.linuxhq.com' です。 2番目の方法は `127.0.0.1'のような IP アドレスを指定する方法です。
# ipchains -A input -s 0/0 -j DENY
#
上記の効果は `-s' オプションを指定しないのと全く同じなので、こんな使 い方はめったにしません。
`-s' と `-d' を含む多くのフラグは、`!' (否定の宣言) をその引数の前に 置くことができます。 `-s' や `-d' の場合は与えられたアドレスと等しくないアドレスとマッチ します。 例えば、 `-s ! localhost' はローカルホストからでない全てのパケットと マッチします。
`!' の前後にスペースを入れるのを忘れないで下さい。本当に必要なのです。
プロトコルは `-p' フラグで指定します。 プロトコルの値は番号(あなたが IP のプロトコルの数値番号を知って いる場合)か `TCP', `UDP' または `ICMP' という特定の名称で指定します。 大文字小文字の区別はしませんから、`tcp' も `TCP' と同じ働きをします。
プロトコル名称はそれを否定するために `!' を前に付けることができます。 例えば、`-p ! TCP' は TCP でないパケットを指定します。
特別な場合である TCP 或は UDP のプロトコルが指定された時には、 TCP 或は UDP のポート、或は含まれるポートの範囲 (しかし、後述の フラグメントの処理を参照して下さい) を指し示す拡張引数が存在し得ます。 範囲は文字 `:' で表現します。例えば `6000:6010' は 6000 から 6010 迄の 範囲に含まれる11個のポート番号を示します。 もし下限値が省略されれば、デフォルトの 0 を意味します。 上限値が省略されれば、デフォルトの 65535 を意味します。 ですから、1024番以下のポートの TCP 接続を指定するには、書き方は `-p TCP -s 0.0.0.0/0 :1023' とします。 ポート番号は `www' のように、名前でも指定できます。
注記として、ポート指定の前には否定を意味する `!' を置くことができます。 ですから、 WWW パケット以外の全ての TCP パケットを指定するには、以下の ように指定します。
-p TCP -d 0.0.0.0/0 ! www
以下の指定と、
-p TCP -d ! 192.168.1.1 www
以下の指定は全く違うことをしっかり認識して下さい。
-p TCP -d 192.168.1.1 ! www
最初の例は、 192.168.1.1 以外の全てのマシンの WWW ポートへの TCP パケット を指定します。 次の例は、 WWW ポートを除く全てのポートにおける 192.168.1.1 への TCP 接続を指定します。
最後に、このケースは WWW ポートでなく、 192.168.1.1 でもないことを 意味します:
-p TCP -d ! 192.168.1.1 ! www
ICMP にもまたオプション引数がありますが、 ICMP はポートを持ち得ません。 (ICMP にはタイプとコードがあります) それらには異なる意味があります。
`-s' オプションの後に ICMP ネームを用いる (ipchains -h icmp
を用いて、
ネームを一覧表示します) か、 ICMP タイプとコードの数値を用いるかで、
それらを指定します。
タイプは `-s' オプションの後に、コードは `-d' オプションの後に指定し
ます。
ICMP ネームはかなり長いです: 他とはっきり区別できる分だけの長い文字列 であれば十分です。
最も一般的な ICMP パケットの小さな一覧を以下に示します:
番号 ネーム 必要とされるもの
0 echo-reply ping
3 destination-unreachable 全ての TCP/UDP トラフィック
5 redirect ルーティングデーモンが動作していない時の
ルーティング
8 echo-request ping
11 time-exceeded traceroute
ICMP ネームは `!' を置けないことに注意して下さい。
絶対に絶対に絶対に、 ICMP タイプ3 メッセージの全部をブロックしないで!! (後述の ICMP パケットを参照して下さい)
`-i' オプションはマッチすべきインターフェイスの名前を指定します。
インターフェイスとは、パケットが入って来るか、または出て行く
物理デバイスです。ifconig
コマンドを使って `up' である
(すなわち、今動いている)インターフェイスをリストアップできます。
入来するパケット (すなわち、 input
チェインを通過するパケット) の
インターフェースは、それらが流れ込んで来るインターフェースであるもの
と見なされます。
論理的には、出て行くパケット (output
チェインを通過するパケット) の
インターフェースは、それらが出て行くであろうインターフェースでありま
す。
forward
チェインを通過するパケットのインターフェースもまた、それらが
出て行くであろうインターフェースです; 私には、これは全くの独断に思えます。
(訳注: ここで著者は forward チェインのインターフェースを出力インター フェースにしたことに抗議しているように思えます。 たぶん著者は入力と出力の両方指定できたほうがよいと思っていて、でも、 ipchains にはインターフェイスを指定するオプションが -i の1つしかない ので、どちらかにせざるおえなかった。と言う話だと思います。 ipchains の後継である iptables では、 FORWARD チェインで、入力と出力 の両方のインターフェイスを指定できるようになってます。)
現在存在していないインターフェイスを指定することは全く問題がありません
が、指定したインターフェイスが up して来るまでルールがマッチすることは
ありません。これはダイアルアップ PPP リンク(通常インターフェイスは
ppp0
)や同様のものについて非常に有効です。
特別なケースとして、インターフェース名の最後が `+' で終わるものは、
(現在存在していようとなかろうと) その文字列から始まる全てのインター
フェースにマッチします。
例えば、全ての PPP インターフェースにマッチするルールを指定するには、
-i ppp+
オプションが使えます。
指定したインターフェイスと一致しないパケットにマッチするように インターフェイス名の前には `!' を置くことができます。
一方向だけ TCP コネクションを許可し、他方は許可しないようにすることは 往々にして有効です。例えば、あなたが外部の WWW サーバーと接続したいが、 そのサーバーからの接続を許可したくないときです。
そのサーバーから来る TCP パケットをブロックすることは自然な方法です。 残念なことに、TCP コネクションにはとにかく両方向のパケットが行き来する ことが必要です。
その解決方法は、コネクション要求に用いられるパケットのみをブロックす ることです。 このようなパケットは SYN パケットと呼ばれます。 (技術的には、SYN フラグが設定されていて、 FIN と ACK フラグがクリア されているパケットを指しますが、我々はこれを SYN パケットと呼びます。) それらのパケットだけを許可しないことで、その場の接続要求を止められま す。
`-y' フラグはこのために使われます: これは TCP プロトコルを指定されて いる場合においてのみ有効です。 例えば、 192.168.1.1 から要求される TCP コネクションを指定するには:
-p TCP -s 192.168.1.1 -y
もう一度、このフラグはその前に `!' を置くことによって (訳注: ! -y として) 否定することができ、それは接続開始のパケットを除く全てのパケットを 意味します。
時に、一度にケーブルに送り出すにはパケットが大き過ぎることがあります。 こんなときは、パケットはフラグメントに分割され、複数のパケットで送られ ます。受信点でこれらのフラグメントを再び集めて完全なパケットに再構成 します。
フラグメントの問題点は、先程リストアップした仕様の幾つか (特に、ソースポート、宛先ポート、 ICMP タイプ、 ICMP コード、 或は TCP SYN フラグ) は、カーネルに、最初のフラグメントにだけ含まれている パケットの始めの部分を覗くように要求している点にあります。
あなたのマシンが外部ネットワークにのみ接続されるなら、カーネルの "IP: 常にデフラグメントする" を Y に設定してコンパイルすることにより、 通過する全てのフラグメントを再構築するように Linux カーネルに命ずる ことができます。 これは問題をうまく回避します。
そうでなければ、フィルタリングルールがフラグメントをどのように扱うか
を理解することが重要です。
情報が無ければどんなフィルタリングルールもマッチしません。
この意味するところは 1番目のフラグメントは他のパケットと同じように扱
われます。
2番目以降のフラグメントは異なります。
従って、 -p TCP -s 192.168.1.1 www
というルール (ソースポートが `www'
の指定)は、フラグメント(1番目のフラグメント以外)と決してマッチ
しません。
同様に否定のルール -p TCP -s 192.168.1.1 ! www
もマッチしません。
とはいえ、`-f' フラグを用いて、 2番目及びそれ以降のフラグメントに 合致するルールを指定できます。 明らかに、このようなフラグメントルールには TCP や UDP ポート、 ICMP タイプ、 ICMP コード或は TCP SYN フラグを指定するのは間違いで す。
また、`!' を `-f' の前に付けて、 2番目以降のフラグメントと適合しな いルールの指定もできます。
通常、フィルタリングは 1番目のフラグメントに効力があるので、目的の ホストでのフラグメントの再組み立てを妨げるため、2番目以降のフラグメント を通過させることは安全とみなされています。とはいえ、フラグメントを送る ことにより簡単にマシンをクラッシュさせることができるバグが知られて います。調べて下さいね。
ネットワーク管理者のための注記: 異常なパケット(TCP, UDP および ICMP の パケットで短すぎてファイアーウォールのコードがポート番号または ICMP の コードと種類を読めないもの)は、フラグメントと同様に取り扱われます。 フラグメントの位置が 8 から始まるTCP パケットだけが明白にファイアウォー ルコードによって破棄されます。(これが発生すると syslog にメッセージが 現れます。)
例えば、次のルールは 192.168.1.1 へ行くフラグメントはどれでも破棄します:
# ipchains -A output -f -d 192.168.1.1 -j DENY
#
さて、今我々はルールを用いてパケットにマッチさせる方法の全てを知り ました。 パケットがルールにマッチすると、以下に記すことが起こります:
これら以外の種類については、重要度に応じて手を付けたいと思います。
ターゲットはルールにマッチするパケットに対し何をすべきかをカーネルに 指示します。 ipchains はターゲットの指定に `-j' を用います。(`ジャンプする'と考え て下さい) ターゲット名は 8文字以下でなければならず、また大小文字を区別します: "RETURN" と "return" は全く別物です。
最も単純なケースは指定されるターゲットが全くない場合です。 このルールのタイプ (しばしば `計数' ルールと呼ばれます) は単純に一定のパケットのタイプをカウントするのに便利です。 このルールにマッチするか否かにかかわらず、カーネルは単純にチェイン 内の次のルールを検査します。 例えば、 192.168.1.1 からのパケットの数を数えるには、以下のように できます:
# ipchains -A input -s 192.168.1.1
#
(`ipchains -L -v' を用いて、各々のルールに関連付けられたバイト及び パケットカウンタを見れます。)
6つの特別なターゲットがあります。
最初の 3つの ACCEPT
, REJECT
と DENY
はとても単純です。
ACCEPT
はパケットの通過を許可します。
DENY
はあたかもパケットを受け取っていないかのように破棄します。
REJECT
はパケットを破棄しますが、(もしそれが ICMP パケットでないなら)
宛先は未到達であることを知らせる ICMP 返答を、ソースに対して生成
します。
次の一つ、 MASQ
はカーネルにパケットをマスカレードすることを知らせ
ます。
これを動作させるには、カーネルが IP マスカレーディングを有効にして
コンパイルされている必要があります。
詳細については、 Masquerading-HOWTO と、付録の
ipchains と ipfwadm との違いを見て下さい。
このターゲットは forward
チェインを通過するパケットにおいてのみ有
効です。
他の主要な特別なターゲットは、カーネルに対して、何処から発生したかを
問わずにパケットをローカルポートへ送る、 REDIRECT
です。
これはプロトコルに TCP または UDP を指定しているルールにおいてのみ指
定できます。
任意に、ポート (名前又は番号) は `-j REDIRECT' と指定できます。
これはパケットが他のポートへアドレスされていたとしても特定のポートへ
転送させる効果を持ちます。
このターゲットは input
チェインを通過するパケットにおいてのみ有効です。
最後の特別なターゲットは RETURN
で、直ちにチェインの最後に落し込むこ
とと等価です。(後述の
ポリシーを設定するを参照して下さい。)
他のターゲットはユーザー指定のチェインを示します。 (後述の チェインの操作で説明しています。) パケットはそのチェイン内のルールを通過し始めます。 そのユーザ定義チェインでの検査が全て終ってもパケットの運命が 決まらなければ、現在のチェインに戻り、その次のルールから検査 を再開します。
ASCII アートの時間です。2つの(おばかさんな)チェイン: input
(組み込み済みチェイン)と test
(ユーザ定義チェイン)で考えま
しょう。
`input' `test' ┌──────────────┐ ┌─────────────┐ │ルール 1: -p ICMP -j REJECT │ │ルール 1: -s 192.168.1.1 │ ├──────────────┤ ├─────────────┤ │ルール 2: -p TCP -j Test │ │ルール 2: -d 192.168.1.1 │ ├──────────────┤ └─────────────┘ │ルール 3: -p UDP -j DENY │ └──────────────┘
192.168.1.1 から来て 1.2.3.4 へ向かう TCP パケットについて考えましょう。
パケットは input
チェインに入り、まず、ルール 1 が検査されます
― マッチしません。
ルール 2 がマッチして、そのターゲットは Test
なので、次に検査される
ルールは Test
の先頭です。
Test
のルール 1 はマッチしますが、ターゲットを指定していないので、
次のルールであるルール 2 が検査されます。
これはマッチしないので、チェインの終わりに達しました。
先程検査したルール 2 のある input
チェインに戻り、それで今度はルール 3
が検査されますが、これもまたマッチしません。
それで、パケットの経路は次のようになります:
v __________________________ `input' | / `Test' v ┌───────────|─/ ┌──────────|─┐ │ルール 1 | /│ │ルール 1 | │ ├───────────|/-┤ ├──────────|─┤ │ルール 2 / │ │ルール 2 | │ ├───────────-─┤ └──────────v─┘ │ルール 3 /─┼─\_______________________/ └───────────|─┘ v
ユーザ定義チェインを効果的に使う方法は、 ファイアウォールルールをどのように構築するかの章を参照して下さい。
これはルールにマッチすることの副次的効果です; マッチしたパケットを `-l' フラグを用いてログに記録することができま す。 普通、通常のパケットにおいてログを記録したくはないでしょうけど、例 外的なイベントを見たい時に便利な特徴です。
この情報のカーネルのログは以下のような感じです:
Packet log: input DENY eth0 PROTO=17 192.168.2.1:53 192.168.1.1:1025
L=34 S=0x00 I=18 F=0x0000 T=254
このログメッセージは簡潔に設計されており、ネットワークの権威者の為 だけに便利な技術情報を含んでいますが、あとの我々にも有用です。 簡単に説明すると以下のようになります:
標準的な Linux システムでは、カーネルの出力は klogd (カーネルロギング デーモン) にて捕捉され、 syslogd (システムロギングデーモン) に渡され ます。 `/etc/syslog.conf' は、各々の `facility' (我々の場合は、facility は "カーネル"です) の宛先と、 `level' (ipchains の為に、使われる level は "info" です)を指定することによって、 syslogd の振る舞いを制御しま す。
例えば、私の (Debian) /etc/syslog.conf は `kern.info' にマッチする 2行を含んでいます:
kern.* -/var/log/kern.log
*.=info;*.=notice;*.=warn;\
auth,authpriv.none;\
cron,daemon.none;\
mail,news.none -/var/log/messages
これらはメッセージが `/var/log/kern.log' と `/var/log/messages' に 複製されることを示しています。 詳細は `man syslog.conf' を見て下さい。
IP ヘッダには滅多に使われない 4つのビットがあり、「サービスの型」 (TOS) ビットと呼ばれています。 それらはパケットが取り扱われる用途に影響します; 4つのビットは "Minimum Delay"(最小遅延), "Maximum Throughput" (最大処理能力), "Maximum Reliability"(最大信頼値) そして "Minimum Cost" (最小コスト) です。 それらのビットの一つだけが設定を許されます。 TOS 操作コードの作者の Rob van Nieuwkerk は以下のように述べています:
特に "Minimum Delay"(最小遅延) が私にとって重要です。 私は上流の (Linux) ルータで"対話型"パケットの為にこのスイッチをオン しています。 私のマシンは 33.6k モデムで外部と接続されています。 Linux はパケットに 3つのキューで優先順位を付けています。 この方法で私は大量のダウンロードと同時に許容できる対話的なパフォー マンスを得ています。 (これはシリアルドライバにそのような巨大なキューがなければ良いのです が、待ち時間は1.5秒に落されます。)
注意: 明らかに、あなたは入って来るパケットに対して制御はできません。 あなたは自身の Linux box を去っていくパケットの優先順位だけを制御 できます。 他の方法で優先順位をやりくりするなら、 RSVP のようなプロトコルが 必要です。(これに関しては私は何も知らないので、私には聞かないで下 さい。)
最も一般的な使用方法は telnet と ftp のコントロールコネクションに "Minimum Delay" を設定し、 FTP データに "Maximum Throughput" を設 定するものです。 以下のようになります:
ipchains -A output -p tcp -d 0.0.0.0/0 telnet -t 0x01 0x10
ipchains -A output -p tcp -d 0.0.0.0/0 ftp -t 0x01 0x10
ipchains -A output -p tcp -s 0.0.0.0/0 ftp-data -t 0x01 0x08
`-t' フラグは 2つの特別なパラメータを持ち、それらは16進で指定します。 それらはTOS ビットを複雑にいじくり回します: 最初のマスクはパケットの現在の TOS に AND (論理積)されます。 2番目のマスクはそれに対して XOR (排他的論理和)されます。 これで激しく混乱するのでしたら、以下の一覧を使って下さい:
TOS 名 値 一般的な用途
Minimum Delay 0x01 0x10 ftp, telnet
Maximum Throughput 0x01 0x08 ftp-data
Maximum Reliability 0x01 0x04 snmp
Minimum Cost 0x01 0x02 nntp
Andi Kleen は以下のように指摘しています。 (後々に残すために表現を 軟らかくしています。)
多分、TOS ビットの議論については、 ifconfig の txqueuelen パラメータの参照を追加するのに便利でしょう。 デバイスのキュー長の初期値はイーサネットカードの為に調整され、モデムにおいてはそれは長すぎて、 (TOSに則ったキューの) 3バンドのスケジューラを作成し、それらの働きは微々たるものです。 モデムやシングル b チャネルの ISDN 接続において、この値を 4-10 の間に設定するのは良いと思います; 太いデバイスならより長いキューが必要です。 これはカーネルバージョン 2.0 と 2.1 の問題でしたが、 2.1 においてそれは (最新の nettools を用いて) ifconfig フラグで可能になり、 2.0 においてはデバイスドライバのソースにパッチを適用して可能になります。
ですので、モデムでの PPP 接続における TOS 操作の最大の恩恵を得るには、 あなたのマシンの /etc/ppp/ip-up スクリプト内で `ifconfig $1 txqueuelen' を実行することです。 これを使う際の値はモデムの速度とモデム内のバッファの総量に依存します; 以下に Andi の私への返答をそのまま再度掲載します:
与えられたコンフィギュレーションの最適値は経験が必要です。 もしルータ上のキューが短すぎると、パケットを取りこぼしてしまいます。 そして勿論 TOS の書き換えもなく効果を得ることになり、単に TOS の書き 換えは非協力的なプログラムに効果をもたらします。 (しかし全ての標準的な Linux システムプログラムは協力的です。)
これは Alexey Kuznetsov による新たな"高品質通信"の実装によって、複雑 で強力な相互作用を有効にします。 2.1 シリーズカーネル以降のmarkベースのフォワーディングと同様に良好で す。 更なるニュースとしてはこれが使えるようになったことです。 このオプションは 2.0 カーネルシリーズでは全く無視されます。
(訳注: Quality of Service は、 QoS と略され、ネットワーク流量制限を 指します。これはカーネルのコンフィギュレーションスイッチに CONFIG_NET_QOS として存在します。)
ipchains のとても有効な特徴は、チェイン中の関連するルールをグループ
化できることです。
お望みのチェインは何でも呼び出せますが、組み込み済みチェイン (input
,
output
と forward
) やターゲット (MASQ
, REDIRECT
, ACCEPT
, DENY
, REJECT
或は RETURN
) を壊さない為に、十分長い名前を使って下さい。
将来の拡張に備えて、ラベル名の全部に大文字を使わないことをお勧めします。
チェインの名前は最大 8文字まで使えます。
新しいチェインを作りましょう。私はとっても創造力に富んだ野郎なので、
それを test
と名付けます。
# ipchains -N test
#
これは簡単です。 さて、あなたはこれまで詳細に述べてきたように、これにルールを入れる ことができます。
チェインを削除するのも同様に簡単です。
# ipchains -X test
#
なぜ `-X' かって? うーん、よい文字が全て取られてしまったのです。
チェインを削除するには 2つの制限があります: そのチェインは空である必要があり(後述の チェインを空にするを見て下さい)、しかも、決してどのルールのターゲットにもなっていないことです。 組み込み済みの 3つのチェインはどれも削除できません。
チェインから全てのルールを取り去り空にするのは簡単で、`-F' コマンド を使います。
# ipchains -F forward
#
もし、チェイン名を指定しなければ、全てのチェインを空にします。
チェイン中の全てのルールをリストアップするには、`-L' コマンドを使い ます。
# ipchains -L input
Chain input (refcnt = 1): (policy ACCEPT)
target prot opt source destination ports
ACCEPT icmp ----- anywhere anywhere any
# ipchains -L test
Chain test (refcnt = 0):
target prot opt source destination ports
DENY icmp ----- localnet/24 anywhere any
#
test
に表示されている `refcnt' は、test
をターゲットに指定している
ルールの数です。
この数が 0 でないと(かつチェインが空であること)、そのチェインを削除
することはできません。
もし、チェイン名を指定しなければ、空のも含めて全てのチェインについて リストアップされます。
`-L' には 3つのオプションがあります。
(大抵の人々は DNS を使っていますが) DNS が適切に設定
されていない場合や DNS の要求をフィルターアウトしている場合は、
ipchains
が IP アドレスを調べようとするときに長く待たされます。
それを防ぐのに `-n' (数値)オプションはとても有効です。
このオプションは TCP や UDP ポートについても名前ではなく番号で表示
します。
`-v' オプションはルールの詳細を全て、例えば、パケットやバイトの カウンター、TOS マスク、インターフェイス、そしてパケットマークを 表示します。 このオプションを指定しなければ、これらの値は省略されます。
# ipchains -v -L input
Chain input (refcnt = 1): (policy ACCEPT)
pkts bytes target prot opt tosa tosx ifname mark source destination ports
10 840 ACCEPT icmp ----- 0xFF 0x00 lo anywhere anywhere any
注記として、パケットとバイトのカウンターは、1000, 1,000,000 および 1,000,000,000 を、それぞれ `K', `M' および `G' の接尾辞を使って表示 します。 `-x' (拡張数値)オプションを使うと、値の大きさにかかわらず完全な数値 を同様に表示します。
カウンターをリセットできると便利です。これは `-Z' (カウンタをゼロにする) オプションでできます。例えば:
# ipchains -v -L input
Chain input (refcnt = 1): (policy ACCEPT)
pkts bytes target prot opt tosa tosx ifname mark source destination ports
10 840 ACCEPT icmp ----- 0xFF 0x00 lo anywhere anywhere any
# ipchains -Z input
# ipchains -v -L input
Chain input (refcnt = 1): (policy ACCEPT)
pkts bytes target prot opt tosa tosx ifname mark source destination ports
0 0 ACCEPT icmp ----- 0xFF 0x00 lo anywhere anywhere any
#
このやり方では、リセットする直前のカウンタ値を知る必要があるときに 問題になります。 上記の方法では、`-L' から `-Z' コマンドまでの間にいくつかのパケット が通過するかもしれません。 そのため、カウンターを読むと同時にリセットするには、`-L' と `-Z' を 同時に使います。 残念ながら、あなたがこれを使うと、単一のチェインを操作できません: 一旦全てのチェインをリストアップしてゼロにする必要があります。
# ipchains -L -v -Z
Chain input (policy ACCEPT):
pkts bytes target prot opt tosa tosx ifname mark source destination ports
10 840 ACCEPT icmp ----- 0xFF 0x00 lo anywhere anywhere any
Chain forward (refcnt = 1): (policy ACCEPT)
Chain output (refcnt = 1): (policy ACCEPT)
Chain test (refcnt = 0):
0 0 DENY icmp ----- 0xFF 0x00 ppp0 localnet/24 anywhere any
# ipchains -L -v
Chain input (policy ACCEPT):
pkts bytes target prot opt tosa tosx ifname mark source destination ports
10 840 ACCEPT icmp ----- 0xFF 0x00 lo anywhere anywhere any
Chain forward (refcnt = 1): (policy ACCEPT)
Chain output (refcnt = 1): (policy ACCEPT)
Chain test (refcnt = 0):
0 0 DENY icmp ----- 0xFF 0x00 ppp0 localnet/24 anywhere any
#
以前にパケットがどのようにチェインを通り抜けるのかを、前述の
ターゲットの指定にて論じたとき、パケット
が組み込み済みチェインの終わりに達した時に何が起きるのかを大体述べまし
た。
この場合、チェインのポリシーがそのパケットの運命を決定します。
組み込み済みチェイン(input
, output
および forward
)だけがポリシーを持っ
ています。
なぜなら、パケットがユーザ定義チェインの終わりまで下り落ちると、前の
チェインに戻って行くからです。
ポリシーは最初から 4つまでの特別なターゲットのいずれかです:
ACCEPT
, DENY
, REJECT
或は MASQ
です。
MASQ
は `forward' チェインにおいてのみ有効です。
また、重要な注意点として、組み込み済みチェイン中のルールにおける RETURN
ターゲットは、パケットがルールにマッチした時に明示的にチェインのポリシー
をターゲットにするため便利です。
IP マスカレーディングを微調整する幾つかのパラメータがあります。
それらは ipchains
に組み込まれています。
何故なら、その機能の為に別のツールを書くのは良くないからです。
(しかしこれは変更されるでしょう。)
IP マスカレーディングのコマンドは `-M' で、今マスカレードされている コネクションをリストアップするために `-L' と組み合わせられ、マスカ レーディングの値を調整するために `-S' と組み合わせられます。
`-L' コマンドは `-n' (ホスト名やポート名ではなく、数値を表示します。) か、または `-v' (まさにあなたが注意する、マスカレードコネクションの シーケンス番号の詳細を表示します。)を伴います。
`-S' コマンドは以下の 3つのタイムアウト値を設定します、それらは 秒単位です: TCP セッション、 FIN パケット後の TCP セッションと、 UDP パケット です。 もしそれらの値の一つを変更したくないならば、単純に `0' が与えられ ます。
既定値は `/usr/src/linux/include/net/ip_masq.h' にリストアップさ れており、 現在はそれぞれ 15 秒、 2秒 そして 5秒です。
変更される最も一般的な値は、 ftp の為に変更する最初の値です。 (後述の FTP の悪夢を参照して下さい。)
マスカレーディングのタイムアウト値を設定できません!に列挙したタイムアウトの設定に関する問題に注意して下さい。
時にあなたのマシンに一定のパケットが入り込む際に何が起こるのかを
見たいと思うことでしょう。
あなたのファイアウォールチェインをデバッグする時など。
ipchains
はこれを有効にさせる `-C' コマンドを装備しています。
その際、カーネルが本当のパケットを診断するのに用いるルーチンと正
確に同じルーチンを用います。
パケットをテストするチェインは、引数 `-C' の後にパケットのテストを
するチェインの名前を指定します。
カーネルは常に input
, output
または forward
チェイン、と移って行き
ますが、テストはどのチェインからでも始めることができます。
`packet' の詳細は、ファイアウォールルールを指定する為に用いられる のと同じ書き方を用いて指定します。 特に、プロトコル (`-p') 、ソースアドレス (`-s') 、宛先アドレス (`-d') とインターフェース (`-i')は必須です。 もしプロトコルが TCP 又は UDP なら、単一のソースと単一の宛先ポート が指定されなければなりませんし、 ICMP プロトコルにおいては ICMP タ イプが指定されなければなりません。 (フラグメントを示す `-f' フラグを指定していなければ。指定している場合は これらのオプションは不正です。)
プロトコルが TCP ならば (そして `-f' フラグがしていされていなけ れば) 、テストパケットに SYN ビットをセットするのに `-y' フラグを指定 してもよいでしょう。
以下は 192.168.1.1 の60000 ポートから 192.168.1.2 の www ポートへ、 eth0 インターフェースに入り、 `input' チェインに到達する TCP SYN パケットをテストする例です。 (これは典型的な WWW の接続開始の入来です)
# ipchains -C input -p tcp -y -i eth0 -s 192.168.1.1 60000 -d 192.168.1.2 www
packet accepted
#
時に単一のコマンドラインが複数のルールに影響させることができます。
これには二つの方法があります。
最初に、(DNS を用いて)複数の IP アドレスに解決するホスト名を指定
すると、 ipchains
はあなたが各々のアドレスの組み合わせに対して複
数のコマンドを発行したのと同じように振る舞います。
ですから、もしホスト名 `www.foo.com' が 3つの IP アドレスに解決
し、ホスト名 `www.bar.com' が 2つの IP アドレスに解決する場合、
コマンド `ipchains -A input -j reject -s www.bar.com -d www.foo.com'
は、 input
チェインに 6つのルールを追加することとなります。
ipchains
に複数の動作を行わせるもう一つの方法は、双方向フラグ(`-b')
を用います。
このフラグは、 ipchains
にコマンドを 2回入力させたのと同様に振
る舞わせます。
その際の 2回目のコマンドは `-s' と `-d' の引数を反転させたこと
になります。
ですので、 192.168.1.1 に相互にフォワードさせることを禁じさせる
には、以下のようにできます:
# ipchains -b -A forward -j reject -s 192.168.1.1
#
個人的には、 `-b' オプションは好きでないです; もっと便利にしたいなら、後述の ipchains-save を使うを見て下さい。
-b オプションは 挿入 (`-I') 、 削除 (`-D') (でもルールナンバーの 拡張ではありません。) 、追加 (`-A') とチェック (`-C') コマンドと 共に使えます。
もう一つの便利なフラグに `-v' (冗長な) があります。
これは ipchains
があなたのコマンドによって何をしているのかを正確
にプリントアウトします。
あなたが複数のルールをコマンドを施しているのなら、これが便利です。
例えば、以下は 192.168.1.1 と 192.168.1.2 との間でフラグメントの
振る舞いをチェックする例です。
# ipchains -v -b -C input -p tcp -f -s 192.168.1.1 -d 192.168.1.2 -i lo
tcp opt ---f- tos 0xFF 0x00 via lo 192.168.1.1 -> 192.168.1.2 * -> *
packet accepted
tcp opt ---f- tos 0xFF 0x00 via lo 192.168.1.2 -> 192.168.1.1 * -> *
packet accepted
#
私の PC はインターネットへダイヤルアップ PPP 接続されます。 (-i ppp0
)
私はダイヤルアップの度毎にネットニュース (-p TCP -s news.virtual.net.au nntp
)
とメール (-p TCP -s mail.virtual.net.au pop-3
) を PC に取り込みます。
私は Debian の FTP による PC の更新作業を定期的に行います。
(-p TCP -y -s ftp.debian.org.au ftp-data
)
私は ISP のプロキシを介して web へのアクセスを行います
(-p TCP -d proxy.virtual.net.au 8080
)
が、 Dilbert アーカイヴ上の doubleclick.net からの広告バナーを嫌い
ます。
(-p TCP -y -d 199.95.207.0/24
と -p TCP -y -d 199.95.208.0/24
)
私は PC がオンラインの際に誰かが私の PC に対して ftp を試みる
ことに関しては気にしません。 (-p TCP -d $LOCALIP ftp
)
けれども、外部の誰かに私の内部ネットワーク (-s 192.168.1.0/24
)
の IP アドレスを偽装されたくありません。
これは通常、 IP スプーフィング (訳注: 偽装) と呼ばれ、バージョン
2.1.x 以降のカーネルにはこれを防ぐ良い方法があります:
IP 偽装保護(IP Spoof Protection)を、どのように設定したらよいですか?を参照して下さい。
このセットアップはとても単純で、何故なら今私の内部ネットワーク上 には他にマシンがないからです。
私はあらゆるローカルプロセス(すなわち、ネットスケープ、 lynx 等) を doubleclick.net に接続させたくありません。
# ipchains -A output -d 199.95.207.0/24 -j REJECT
# ipchains -A output -d 199.95.208.0/24 -j REJECT
#
さて、私は外へ出て行く様々なパケットに優先順位を設定したいです。
(入って来るパケットに対してこれを行う多くのメリットはありません。)
これらのルールが多数あるので、ppp-out
と名付けたチェインにそれら全てを
入れることは意味のあることです。
# ipchains -N ppp-out
# ipchains -A output -i ppp0 -j ppp-out
#
web のトラフィックと telnet へ最小遅延を設定します。
# ipchains -A ppp-out -p TCP -d proxy.virtual.net.au 8080 -t 0x01 0x10
# ipchains -A ppp-out -p TCP -d 0.0.0.0/0 telnet -t 0x01 0x10
#
ftp データ, nntp, pop-3 に低コストを設定します:
# ipchains -A ppp-out -p TCP -d 0.0.0.0/0 ftp-data -t 0x01 0x02
# ipchains -A ppp-out -p TCP -d 0.0.0.0/0 nntp -t 0x01 0x02
# ipchains -A ppp-out -p TCP -d 0.0.0.0/0 pop-3 -t 0x01 0x02
#
ppp0 インターフェースに入って来るパケットには幾つかの制限があります: `ppp-in' というチェインを作りましょう:
# ipchains -N ppp-in
# ipchains -A input -i ppp0 -j ppp-in
#
さて、 ppp0
に入って来るパケットは 192.168.1.* のソースアドレス
を主張するべきではありません。
ですから、我々はそれらをログに記録して否定 (deny) します:
# ipchains -A ppp-in -s 192.168.1.0/24 -l -j DENY
#
私は DNS の UDP パケット (私は全ての要求を 203.29.16.1 へ転送する キャッシュネームサーバを動かしているので、それらの要求からその DNS だけが返答することを予測します。) と 入って来る ftp と帰って来る ftp-data (これらは1023番以上のポートのみが使われ、且つ6000番近辺の X11 ポー トを使いません。) の TCP パケットのみを許可します。
# ipchains -A ppp-in -p UDP -s 203.29.16.1 -d $LOCALIP dns -j ACCEPT
# ipchains -A ppp-in -p TCP -s 0.0.0.0/0 ftp-data -d $LOCALIP 1024:5999 -j ACCEPT
# ipchains -A ppp-in -p TCP -s 0.0.0.0/0 ftp-data -d $LOCALIP 6010: -j ACCEPT
# ipchains -A ppp-in -p TCP -d $LOCALIP ftp -j ACCEPT
#
帰ってくる TCP の返答パケットを許可します。
# ipchains -A ppp-in -p TCP ! -y -j ACCEPT
#
最後に、ローカルとローカル同士のパケットは OK です:
# ipchains -A input -i lo -j ACCEPT
#
さて、私の input
チェインにおける既定ポリシーは DENY
(否定) です
ので、上述のもの以外は全て破棄します:
# ipchains -P input DENY
#
注意: 私はこの順番でチェインをセットアップしませんでした。 セットアップの最中にパケットが入り込んで来るからです。 最も安全なのは最初に DENY のポリシーを設定することです。 勿論、あなたのルールがホスト名を解決する為に DNS の参照を 要求するなら、問題が発生することでしょう。
まさにあなたのお望み通りのファイアウォールチェインをセットアップし、 そして次回にやったことを思い出そうとするのは辛いことです。
そこで、今セットアップしたあなたのチェインを読み、ファイルに保存す
る、 ipchains-save
というスクリプトです。
ipchains-restore
が何をするかに関してはちょっと待ってて下
さいね。
ipchains-save
は単一のチェイン又は (チェイン名が指定されなければ)
全てのチェインをセーブできます。
オプションとしては `-v' のみが許され、これはセーブされたルールを
(標準エラー出力に) プリントします。
input
, output
そして forward
チェインのポリシーも同様にセーブされ
ます。
# ipchains-save > my_firewall
Saving `input'.
Saving `output'.
Saving `forward'.
Saving `ppp-in'.
Saving `ppp-out'.
#
ipchains-restore
は ipchains-save
で保存されたチェインを復元します。
これは 2つのオプションを持ち得ます:
`-v' は各々のルールが追加されるように説明します。
そして `-f' は以下に説明するように、既に存在するユーザー定義チェイン
を強制的に消去します。
もし、 input チェイン内にユーザー定義チェインがあれば、 ipchains-restore
はそれが既存のチェインなのかをチェックします。
そうであれば、プロンプトが表示され、チェインを消去する (全てのルール
を消去する) か、処理をスキップして現在の設定を保持するかの選択を求め
られます。
もしコマンドラインに `-f' を指定すれば、プロンプトは表示されません:
チェインは消去されます。
例:
# ipchains-restore < my_firewall
Restoring `input'.
Restoring `output'.
Restoring `forward'.
Restoring `ppp-in'.
Chain `ppp-in' already exists. Skip or flush? [S/f]? s
Skipping `ppp-in'.
Restoring `ppp-out'.
Chain `ppp-out' already exists. Skip or flush? [S/f]? f
Flushing `ppp-out'.
#