14.2. ファイヤーウォールとパケットフィルタリング
ファイヤーウォールはネットワークゲートウェイをフィルタするもので、ゲートウェイを通過しなければいけないパケットだけに有効です。それ故、ファイヤーウォールはパケットにとってファイヤーウォールが唯一の経路である場合だけに有効です。
標準的な設定が存在しないということは (そして「過程であって、成果ではない」モットーに従うということは) ややこしい初期設定の不要な解決策が存在しないという事を意味します。しかしながら、netfilter ファイヤーウォールの設定を簡単に行うためのツールが存在し、ツールはフィルタリングルールをグラフィカルに表現する機能を備えています。fwbuilder
がこの種のツールの中で最良のツールであることは疑いありません。
Linux カーネルには netfilter ファイヤーウォールが組み込まれています。iptables
と ip6tables
コマンドを使うことで、netfilter ファイヤーウォールをユーザ空間から制御する事が可能です。iptables
と ip6tables
コマンドの違いは、iptables
が IPv4 ネットワークを取り扱うのに対し、ip6tables
は IPv6 ネットワークを取り扱うという点です。おそらく IPv4 と IPv6 のネットワークプロトコルスタックは長きに渡り共存するでしょうから、両方のツールを並行して実行する必要があります。
netfilter は 4 種類の異なるテーブルを使います。テーブルには、パケットに対する 3 種類の操作を規制するためのルールを保存します:
filter
はフィルタリングルール (パケットを受け入れる、拒否する、無視するなど) に関係します;
nat
はパケットの送信元や宛先アドレスおよびポート番号の変換に関係します; このテーブルは IPv4 だけに存在することに注意してください;
mangle
は IP パケットに対するその他の変換にに関係します (ToS - Type of Service - フィールドやオプションを含みます);
raw
を使うことで、パケットが接続追跡システムに到達する前にパケットを手作業で別の変更を加える事が可能です。
それぞれのテーブルには、チェインと呼ばれるルールのリストが含まれます。ファイヤーウォールは事前に定義された状況に基いてパケットを取り扱うために標準的なチェインを使います。管理者は他のチェインを作成する事が可能です。このチェインを使うには、標準的なチェインの 1 つから (直接的か間接的かのいずれか一方の方法で) このチェインを参照します。
filter
テーブルは 3 種類の標準的なチェインを備えています:
INPUT
: 宛先がファイヤーウォール自身のパケットに関係します;
OUTPUT
: ファイヤーウォールから送信されたパケットに関係します;
FORWARD
: ファイヤーウォールを通過するパケットに関係します (ファイヤーウォールはパケットの送信元でも宛先でもありません)。
nat
テーブルも 3 種類のの標準的なチェインを備えています:
PREROUTING
: パケットの到着後すぐにパケットを修正します;
POSTROUTING
: パケットを宛先に送信する準備が完了した時にパケットを修正します;
OUTPUT
: ファイヤーウォールそれ自身によって生成されたパケットを修正します。
各チェインはルールのリストです; 各ルールは一連の条件とその条件に一致する場合に実行される動作です。パケットを処理する場合、ファイヤーウォールは適切なチェインを 1 つづつ検査します; あるルールの条件に一致したら、処理を続けるために特定の動作に「ジャンプ」します(このためコマンドには -j
オプションが存在します)。最も一般的な挙動は標準化されており、それぞれの挙動に対する専用の動作が存在します。標準的な動作が選択されると、チェインの処理は中止されます。なぜなら、パケットの運命は既に決まっているからです (以下で言及されている除外に一致しなければ):
ACCEPT
: 対象のパケットの通過を許可します;
REJECT
: 対象のパケットを拒否して ICMP エラーを返答します (iptables
の --reject-with type
オプションを使えば返答するエラーの種類を選ぶ事が可能です);
DROP
: 対象のパケットを削除 (無視) します;
LOG
: 対象のパケットと一緒にメッセージをログに記録 (syslogd
を使って) します; ログ記録が選択された場合チェインの処理は中止されない点に注意してください。チェインの実行は次のルールに進みます。このため、拒否されたパケットをログに記録するには、LOG と REJECT/DROP ルールの両方が必要です;
ULOG
: ulogd
を介してメッセージをログに記録します。ulogd
は大量のメッセージを処理する場合に syslogd
よりも効率が良いです; LOG と同様、この場合も処理は呼び出されたチェインの次のルールに進む点に注意してください;
chain_name: 指定したチェインに飛んで、チェインのルールを評価します;
RETURN
: 現在のチェインの処理を中止し、呼び出されたチェインに戻ります; 現在のチェインが標準的なチェインの場合、呼び出されがチェインはありませんから、代わりにデフォルトの動作 (iptables
の -P
オプションで定義された動作) が実行されます;
SNAT
(nat
テーブル、つまり Wheezy の IPv4 の中だけでのみ使う事が可能です - IPv6 の NAT サポートは Linux 3.7 カーネルから導入されました): Source NAT を適用します (追加オプションを使って適用する正確な変更を設定します);
DNAT
(nat
テーブル、つまり Wheezy の IPv4 の中だけでのみ使う事が可能です): Destination NAT を適用します (追加オプションを使って適用する正確な変更を設定します);
MASQUERADE
(nat
テーブル、つまり Wheezy の IPv4 の中だけでのみ使う事が可能です): マスカレードを適用します (これは Source NAT の特別な場合です);
REDIRECT
(nat
テーブル、つまり Wheezy の IPv4 の中だけでのみ使う事が可能です): ファイヤーウォールの指定したポートに対象のパケットを転送します; これを使って、クライアント側に特別な設定をせずとも動作する透過的なウェブプロキシをセットアップする事が可能です。なぜなら、クライアントは宛先に接続していると思っていても、実際の通信はプロキシを通過しているからです。
その他の動作、特に mangle
テーブルに関する動作、はこの本の範囲を超えています。iptables(8) と ip6tables(8) には包括的なリストが含まれています。
14.2.2. iptables
と ip6tables
の構文
iptables
と ip6tables
コマンドを使って、テーブル、チェイン、ルールを操作する事が可能です。-t table
オプションで操作対象のテーブルを指定します (デフォルトの場合、filter
テーブルを操作します)。
-N chain
オプションは新しいチェインを作成します。-X chain
は空で使われていないチェインを削除します。-A chain rule
はルールをチェインの最後に追加します。-I chain rule_num rule
オプションは指定したルール番号 rule_num の前にルールを挿入します。-D chain rule_num
(または -D chain rule
) オプションはチェインからルールを削除します; 初めの構文はルール番号を指定してルールを削除し、後の構文はルール内容を指定してルールを削除します。-F chain
オプションはチェインをクリアします (チェインに含まれるすべてのルールを削除します); チェインを指定しなかった場合、テーブルに含まれるすべてのルールを削除します。-L chain
オプションはチェインに含まれるルールを表示します。最後に、-P chain action
オプションは指定したチェインのデフォルト動作、「ポリシー」、を定義します; ポリシーを設定できるのは標準的なチェインだけという点に注意してください。
それぞれのルールは conditions -j action action_options
の形で指定します。復数の条件が同じルールとして表現された場合、復数の条件は結合 (論理 and) されます。つまり、各条件の結果を更に限定する事を意味します。
-p protocol
条件は IP パケットのプロトコルフィールドに一致します。最も普通の値は tcp
、udp
、icmp
、icmpv6
です。条件の前に感嘆符を付けることで、その条件を否定した事になります。つまり「指定したプロトコル以外のすべてのプロトコルを使ったパケット」に一致します。条件否定の方法は -p
オプションに限らず、他のすべての条件に適用する事が可能です。
-s address
または -s network/mask
条件は対象のパケットの送信元アドレスに一致します。同様に、-d address
または -d network/mask
は宛先アドレスに一致します。
-i interface
条件は指定したネットワークインターフェースから受信したパケットを選択します。-o interface
は指定したインターフェースから送信されるパケットを選択します。
上で説明した一般的な条件ごとに、条件の範囲を狭めるためのオプションが数多く存在します。例えば、-p tcp
条件は TCP ポート番号を指定して条件範囲を狭める事が可能です。これを行うには、--source-port port
と --destination-port port
を使います。
--state state
条件は接続中のパケットの状態を検査します (接続追跡を行うための ipt_conntrack
カーネルモジュールが必要です)。NEW
状態は新しい接続の開始するパケットを意味します; ESTABLISHED
は既に存在する接続に関連するパケットに一致します。RELATED
は既存の接続に関連する新しい接続を開始するパケットに一致します (これは FTP プロトコルの「アクティブ」モードを使ったftp-data
接続の際に便利です)。
前の節で利用可能な動作を説明しましたが、その動作に対するオプションを説明していませんでした。例えば、LOG
動作は以下のオプションを持ちます:
--log-priority
は記録する syslog
メッセージの優先度を指定します。デフォルトの場合 warning
以上の優先度を持つメッセージが記録されます;
--log-prefix
はログに記録するメッセージを特徴づけるために行の先頭に付けるテキストを指定します;
--log-tcp-sequence
、--log-tcp-options
、--log-ip-options
はログメッセージに含める追加的なデータを指定します: それぞれ TCP シーケンス番号、TCP オプション、IP オプションをログメッセージに含めます。
DNAT
動作には --to-destination address:port
オプションを指定する事が可能です。これは新しい宛先 IP アドレスおよびポート番号を指定するオプションです。同様に、SNAT
には --to-source address:port
を指定する事が可能です。これは新しい送信元 IP アドレスおよびポート番号を指定するオプションです。
REDIRECT
動作には --to-ports port(s)
オプションを指定する事が可能です。これはパケットの転送先ポート番号またはポート番号範囲を指定します (REDIRECT
動作は Wheezy 上の NAT を有効化している場合にのみ使う事が可能です。つまりこれは IPv4 だけで使える事を意味します)。
1 つのルールを作成するには、iptables
/ip6tables
を 1 回実行する必要があります。これらのコマンドを手作業で実行することは退屈なので、通常スクリプトの形で保存しておきます。こうすることで、マシンの起動時に同じ設定を自動的に適用する事が可能です。このスクリプトは手作業で書かなければいけませんが、fwbuilder
等の高レベルツールを使ってスクリプトを準備する事も興味深いでしょう。
原理は簡単です。まず最初に、実際のルールに適用するすべての要素を宣言する必要があります:
ネットワークインターフェースとそれを使うファイヤーウォール自身;
対応する IP アドレス範囲とそれを使うネットワーク;
サーバ;
サーバでホストされているサービスに対応するポート番号。
オブジェクトに対する単純なドラッグアンドドロップ動作を使ってルールを作成します。一部のコンテキストメニューを使ってルールの条件を変更する (例えば条件を否定する) 事が可能です。そして、動作を選んで設定する必要があります。
IPv6 に関心があるなら、IPv4 と IPv6 で別々のルールセットを作成するか、片方だけを作成してオブジェクトに割り当てられたアドレスに応じて fwbuilder
にそのルールを変換してもらうか、のどちらか一方を行う事が可能です。
fwbuilder
は定義されたルールに従ってファイヤーウォールを設定するためのスクリプトを生成する事が可能です。モジュール式のアーキテクチャのお陰で、fwbuilder
は様々なファイヤーウォールシステム (Linux の iptables
、FreeBSD の ipf
、OpenBSD の pf
) を設定するためのスクリプトを生成する事が可能です。
Squeeze 以降の fwbuilder パッケージには、グラフィカルインターフェースと様々なファイヤーウォールシステム用のモジュール (以前、これらはシステム毎に復数のパッケージに分割されていました) が含まれます:
#
aptitude install fwbuilder
ファイヤーウォールが断続的な PPP ネットワーク接続を保護するように設定されていた場合、スクリプトを /etc/ppp/ip-up.d/0iptables
に配置する事が最も単純な方法です (名前にドットを含まないファイルだけが考慮されます)。ファイヤーウォールは PPP 接続が確立された時点で毎回再読込されます。
別のやり方として、設定スクリプトを /etc/network/interfaces
ファイルの up
指示文に登録する方法も推奨されます。以下の例では、設定スクリプトは /usr/local/etc/arrakis.fw
に保存されています。
例14.1 ファイヤーウォールスクリプト呼び出す interfaces
ファイル
auto eth0
iface eth0 inet static
address 192.168.0.1
network 192.168.0.0
netmask 255.255.255.0
broadcast 192.168.0.255
up /usr/local/etc/arrakis.fw