実践で学ぶ、一歩進んだサーバ構築・運用術

第 8 回 ファイアウォール (後編)


ACK フラグに基づくフィルタリング

TCP の場合, 接続するには 3-ウエイ・ハンドシェイク が完了することが不可欠であることを 思い出してください。 3-ウエイ・ハンドシェイクを構成する 3 つのパケットのうち どれか 1 つだけでも捨ててしまえば, 接続不可能になります。 内向き接続における全パケットを捨てる必要はありません。 3 つのパケットの中でも最初の SYN パケットを捨ててしまえば, 最も効率が良いですし, SYN フラッディング攻撃 を防ぐこともできます。

SYN パケットは TCP のパケットの中で 唯一 ACK フラグが立っていないパケットなので, ACK フラグの値を見るだけで SYN パケットか否かを判別できます。 したがってフィルタリングの条件は次のような非常に単純なものになります。


ACK フラグが 0 で,かつ内向きパケットを捨てる


外向き接続の場合, SYN パケットは外向きパケットですからこの条件を満たさず, かつ SYN パケット以外のすべてのパケットは ACK フラグが 1 ですから, やはり条件を満たしません。 だから外向き接続のためのパケットはいずれも破棄されません。 一方, 内向き接続の場合, SYN パケットは内向きパケットですから上記条件を満し, 破棄されてしまいます。 したがって SYN パケットは内部のサーバーに届くことはなく, 3-ウエイ・ハンドシェイクが始まりさえしませんから, 内向き接続は不可能です。

最近のダイヤルアップ・ルーターは デフォルトがこのような設定になっているものが多いようです(図 4)。 プロバイダへダイヤルアップ接続する人のほとんどすべてにとって, Web とメールの読み書きなど, 外向き接続ができれば十分なので, 当然と言えるでしょう。

ダイヤルアップ・ルーターによるフィルタリング
図 4 ダイヤルアップ・ルーターによるフィルタリング

ダイヤルアップ・ルーターではなく, 内部 LAN 上の PC に TA あるいはモデムを接続してダイヤルアップ接続する場合 (図 5), その PC がダイヤルアップ・ルーターの役割を果たす デュアルホーム・ホストになります。 PPP 接続の設定だけでなく, フィルタリングの設定にも気を配らなければなりません。

内部 LAN とモデムあるいは TA に接続された PC におけるフィルタリング
図 5 内部 LAN とモデムあるいは TA に接続された PC におけるフィルタリング

Linux の場合, フィルタリングの設定を行うのは ipchains コマンドの役割です。 まずデュアルホーム・ホストにおける設定方法を説明します。

ipchains

Linux カーネルではフィルタリングの条件は, ルールのチェーン(chain ,連鎖)として表現します。 つまり設定された複数のルールを順番に見ていって, パケットの内容がルールの条件部とマッチする最初のルールが適用されます。

Linux カーネルには図 6 に示すような 3 本のチェーンがあります。

フィルタリング・チェーン
図 6 フィルタリング・チェーン

入力用チェーンは, ホストに入ってくるパケットに対して適用されるルールのチェーンです。 入力用チェーンで廃棄されたパケットは, ホスト上のプログラムに届くことはありません。

出力用チェーンは, ホストから出ていくパケットに対して適用されるルールのチェーンです。 ホスト上のプログラムが送信したパケットのうち 特定の条件を満たすものを捨てることができます。

中継用チェーンは, ホストが中継するパケットに対して適用されるルールのチェーンです。 ホストをルーターとして用いる場合, ホスト上のプログラムとは関係ないパケットをホストが中継することになりますが, この時特定の条件を満すパケットを捨てることができます。 図 6 から明らかなように, あるパケットがこのホストで中継されるためには, 中継用チェーンを通過するだけでなく, 入力用チェーンと出力用チェーンの両方も通過しなければなりません。

さて, 目標は前述したように「ACK フラグが 0 で,内向きのパケット」の廃棄です。 このホストに届くパケットも, このホストで中継されて内部 LAN に届くパケットも, ACK フラグが 0 であれば破棄しなければなりません。 このホストに届くパケットに対して適用されるチェーンは入力用チェーンだけで, 入力用チェーンは中継されるパケットに対しても適用されますから, 入力用チェーンを設定すればよいことになります。

入力用チェーンにおいて, ACK フラグが 0 で, 内向きのパケットを廃棄するには, root になって図 7 のように実行します。 「-I input」は, 入力用チェーンの先頭にルールを挿入する, という意味です。 出力用チェーン, 中継用チェーンにルールを設定する場合は, それぞれ「-I output」,「-I forward」を指定します。 先頭に挿入するのではなく, 末尾に追加する場合は, 「-I」の代りに「- A 」を指定します。 「-j DENY」が, ルールの条件にマッチしたパケットに対して行う動作で, 「DENY」はパケットの通過を拒否する, つまりパケットを廃棄するという意味です*9。 通過を許可する場合は, 「-j ACCEPT 」を指定します。


# ipchains -I input -j DENY -i ppp0 -p tcp -y
図 7 入力用チェーンで ACK フラグが 0 の内向きパケットを廃棄する

残りのパラメータ「-i ppp0 -p tcp -y」がルールの条件部です。 「-i ppp0」はパケットが入ってきたインタフェースが ppp0 である, という条件です。 ppp0 はダイヤルアップ接続で用いられるインタフェースですが, ppp0 が使用中(あるいは使用不可)の場合, ppp1 以降が用いられるので注意が必要です。

ダイヤルアップ接続が完了したとき, /etc/ppp/ip-up (通常はシェル・スクリプト)が呼ばれますが, この時 1 番目のパラメータにインタフェース名が渡される*10 ので, /etc/ppp/ip-up 内でチェーンの設定を行うのが良いでしょう。

入力インタフェースがイーサネット・アダプタである場合は, eth0 などのインタフェース名を指定することになります。 「-p tcp」はパケットのプロトコルが TCP である, という条件です。 「-y」はパケットが SYN パケット, すなわち ACK フラグが 0 であるという条件です。

以上の条件がすべて成立したとき, 「-j DENY」が実行されます。 すなわち上記条件のすべてを満すパケットは廃棄されます。

チェーンの内容を確認するには, 図 8 のように実行します。 「-L input」は入力用チェーンのルールをすべて表示する, という意味です。 「-v」は詳細表示を行うためのオプションで, これを指定しないと入力インタフェースの条件などが表示されません。


# ipchains -L input -v Chain input (policy ACCEPT: 1031475 packets, 160506770 bytes): pkts bytes target prot opt tosa tosx ifname mark outsize source destination ports 0 0 DENY tcp -y---- 0xFF 0x00 ppp0 anywhere anywhere any -> any
図 8 チェーンの内容を確認する

チェーンのルールを削除するには, 「-I」の代りに「-D」を指定します。 例えば, 上記で入力用チェーンに設定したルールを削除するには, 図 9 のように実行します。


# ipchains -D input -j DENY -i ppp0 -p tcp -y
図 9 入力用チェーンに設定したルールを削除する

チェーンのルールをすべて削除したい場合は図 10 のように実行します。 /etc/rc.local などのシェル・スクリプトにおいて ipchains コマンドを実行してチェーンを設定する場合は, 最初に図 10 のコマンドを実行して チェーンを初期化するようにすると良いでしょう*11。


# ipchains -F input
図 10 チェーンのルールをすべて削除する

パケットがチェーン内のどのルールともマッチしなかった場合のデフォルトの動作は, ACCEPT すなわちパケットの通過許可です。 入力用チェーンのデフォルトを DENY にしたい場合は, 「-P」オプションを指定して図 11 のように実行します。 ただし, デフォルトを DENY にした場合は, パケットの通過を許可するルールを設定しない限り, TCP 以外のパケット(例えば ICMP)もすべて捨ててしまいます。 TCP に限りデフォルトを廃棄にしたい場合は, 図 12 のように実行して入力チェーンの末尾に 「TCP パケットならば廃棄」というルールを追加すると良いでしょう。 パケット通過のルールはチェーンの先頭から挿入するようにすれば, どのルールにもマッチしなかった TCP パケットは 最後のこのルールによって廃棄されます。


# ipchains -P input DENY
図 11 入力用チェーンのデフォルトをDENY にする


# ipchains -A input -j DENY -p tcp -l
図 12 TCP に限り廃棄をデフォルトにする

「-l」オプションは, このルールにマッチするパケットの記録を syslog へ送ります。 例えば私のマシンの場合, 図 13 のように記録されます。 これはホスト「211.120.2.190」の 4944 番ポートから, ホスト「210.145.125.162」(これは私のマシン)の 143 番ポート(IMAP サービス) あての TCP(PROTO=6)パケットを「input」チェーンで DENY したことを意味します。


Sep 10 13:42:43 asao kernel: Packet log: input DENY eth0 PROTO=6 211.120.2.190:4944 210.145.125.162:143 L=60 S=0x00 I=17146 F=0x4000 T=48 SYN (#21)
図 13 syslog におけるパケットの記録

記録しておくと, ポート・スキャンを受けたときすぐ分かります*12。 ただし, すべてのポート・スキャンをいちいち監視していては 時間がいくらあっても足りないので, ログ・ファイルから珍しいポートへのアクセスのログのみをピックアップして 管理者へメールを送るように設定しておくと良いでしょう。

*9
DENY の代りにREJECT を指定することもできます。 DENY はパケットをただ捨てるだけですが, REJECT は捨てたことを ICMP で送信元へ知らせます。
*10
詳しくは pppd のマニュアルを参照してください。
*11
初期化を行わずに挿入だけを行うシェル・スクリプトだと, そのシェル・スクリプトを実行するたびに同じルールが挿入されてしまい, 無駄になります。
*12
分かったからといっても, 既にパケットは破棄してしまっているのだし, 特に対策すべきことは何もないのですが, どんなポート・スキャンがはやっているかを把握することは 何かの役に立つかも知れません。

(送信元アドレスに基づくフィルタリング)


本稿は日経Linux 2000 年 11 月号に掲載された、 実践で学ぶ、一歩進んだサーバ構築・運用術, 第 8 回「ファイアウォール (後編)」を日経BP 社の許可を得て転載したものです。

Copyright(C)2000 by 仙石浩明 <sengoku@gcd.org>
無断転載を禁じます

| home | up |

sengoku@gcd.org