Linuxで作るファイアウォール[パケットフィルタリング設定編]
第5回 Linuxで作るファイアウォール[パケットフィルタリング設定編]いよいよパケットフィルタリングの設定を始める。しっかりと不要なパケットをブロックできれば、ファイアウォールの内側の安全度はより向上する。パケットの性質やiptablesの動作をここでマスターしてほしい。
前回はNATの設定方法を説明しました。これで見かけ上の経路ができたことになります。今回はファイアウォールの仕上げとして、パケットフィルタリングの設定を行います。
パケットフィルタリングの仕組み
パケットフィルタリングの設定とはいかなるものかを簡単に説明すると、どのようなパケットを通過させるか、あるいは到達を許可/拒否させるかを定義することです。iptablesではIPアドレスやプロトコル、ポート、フラグメントなどで制限をかけることが可能です。さらに、送信先、送信元なのかといった判断もできます。これを行うのが、filterテーブルに含まれるFORWARD、INPUT、OUTPUTという3つのチェインです。まずは3つのチェインの関係を整理しておきましょう。
![]() |
図1 iptablesによるパケットフィルタリングの流れ |
パケットを受信した際、まずパケットの送信先をチェックします。送信先がそのパケットを受信したホストそのものであれば、INPUTチェインに送られて定義されているルールに従って処理され、そのパケットを受け取る場合は適切なサービスに渡されます。送信先が別のホストであればFORWARDチェインに送られ、パケットの通過が許可されれば該当するホストへと転送されます。許可されなかったパケットは、そこで破棄されるというわけです。反対に、そのホストのプログラムによって生成されたパケットはOUTPUTチェインでチェックされ、許可されれば送信先へと送り出されます。
ファイアウォールはインターネットとLANの間でパケットを通過あるいは破棄するのが基本的な役目ですから、FORWARDの設定が中心になります。ただし、ファイアウォール自体に対して何らかの働きかけ(リモートメンテナンスなど)を行いたい場合もあるので、INPUTやOUTPUTの設定も行っておくべきでしょう。
FORWARDチェイン
FORWARDチェインは、ファイアウォールの肝になるチェインです。必要なパケットだけにDMZ上の目的のホストやサービスへアクセスを許可する(ファイアウォールを通過させる)のが、このFORWARDチェインの仕事です。当然のことながら、FORWARDチェインの基本ポリシーはDROP(パケットを破棄)とします。そして、許可するアクセスのみ「穴をあける」設定を行います。
注:デフォルトのFORWARDチェインのポリシーはACEEPT(通過を許可)となっているため、各サーバに対してどのプロトコルでも接続できるはずです。できないようであればNATのルールを見直してください。 |
■基本ポリシーはパケットの破棄
基本的にFORWARDチェインのポリシーはDROPとするので、まず次のコマンドを実行します。
# /sbin/iptables -P FORWARD DROP |
-Pオプションは前回説明したとおり、指定したチェインに対して基本ポリシーを設定するオプションです。これで、ファイアウォールを通過してDMZ上のホストへ到達できる経路はすべて絶たれたことになります。
注:iptablesのデフォルトのテーブルはfilterであるため、-tオプションによるテーブルの指定は省略できます。 |
■通過させるパケットの設定
次にファイアウォールを通過させるパケットの設定です。まずは次のようなルールを想定して設定を行います。
インターネット上のホストからWebサーバ(192.168.0.10)に対するHTTP(80/TCP)のアクセスのみを許可する。
FORWARDチェインに通過を許可するルールを追加するわけですが、注意しなければならないのは、iptablesでは1つのコネクションを1つのルールだけで許可することができないということです。どういうことかをTCPのコネクションを例に説明します。
![]() |
図2 TCP 3Way-HandShake |
TCPのセッションは、
という3つの段階を経て開始されます。
iptablesでは、接続元のホストから接続先のホストへのルール(上図の(1)(3))と接続先のホストから接続元のホストへのルール(上図の(2))とを別々のルールで定義する必要があります(注)。
注:(1)と(3)を別々のルールで定義することも可能です。詳細については後ほど説明します。 |
これを踏まえたうえで、実際のルールを設定していきます。インターネット上のホストから、Webサーバへのアクセスを許可するには次のコマンドを実行します。
# /sbin/iptables -A FORWARD -p tcp --dport
80 -d 192.168.0.10 -j ACCEPT |
上記のオプションは、次の内容をFORWARDチェインに追加(APPEND)したことを意味します。これにより、上図の(1)と(3)が可能になります。
-p | プロトコル:tcp | |
--dport | 送信先ポート:80 | |
-d | 送信先アドレス:192.168.0.10 | |
-j | ターゲット:ACCEPT(パケットの通過を許可) |
次に、Webサーバからインターネット上のホストへの応答パケットを許可するルールを設定します。これが上図の(2)を可能にするルールです。
# /sbin/iptables -A FORWARD -p tcp !
--syn -m state --state ESTABLISHED --sport 80 -s 192.168.0.10 -j ACCEPT |
これで、インターネット上のホストからWebサーバへのHTTPのアクセスは許可されたことになります。
上記のオプションは、次の内容をFORWARDチェインに追加(APPEND)したことを意味します。
-p | プロトコル:tcp | |
--sport | 送信元ポート:80 | |
-s | 送信元アドレス:192.168.0.10 | |
! --syn | フラグ:SYNフラグ以外 | |
-m state --state | ステータス:ESTABLISHED | |
-j | ターゲット:ACCEPT(パケットの通過を許可) |
指定したオプションの中に、先ほどとは違うものが含まれています。それは「フラグ」と「ステータス」です。
●flag(フラグ):
フラグを条件とする拡張マッチングで、「-p tcp」(--protocol tcp)パラメータを指定したときのみ使用できます。
TCPパケットには、フラグとしてSYN、SYN/ACK、ACK、RSTなどがセットされています。iptablesでは次のフラグを指定することができます。
SYN、ACK、FIN、RST、URG、PSH、ALL(すべて)、NONE(すべてなし) |
通常は「--tcp-flags」として、チェックするフラグとセットされているべきフラグを指定します。例えば、
-p tcp --tcp-flags ALL SYN,ACK |
とした場合は「すべてのフラグ(ALL)をチェックし、SYNとACKだけがセットされているTCPパケット」を意味します。
「--syn」は「--tcp-flags SYN,RST,ACK SYN」の省略形で、「SYN、RST、ACKフラグをチェックし、SYNだけがセットされているTCPパケット」という意味になります。上記のオプションには「! --syn」が指定されています。前回も紹介したように「!」は条件を反転させるパラメータですから、「SYNビットがクリアされてACKとFINビットがセットされているTCPパケット」となります。
なぜこのオプションを指定することが必要なのか考えてみましょう。通常、サーバであれば自分自身からほかのホストへ接続することはほとんどないでしょう(注)。上記のルールは、アクセスに対する応答を許可するためのものです。接続の開始にセットされ、シーケンス番号の初期化に使われるSYNフラグがセットされたパケットの通過を許可する必要はないのです。SYNフラグがセットされたパケットの通過を拒否することは、クラッカーに仮に侵入されたとしてもほかのホストへの踏み台とさせないためにとても有効な手段となるのです。
注:SMTPやDNSなど、通常の動作として外部へアクセスするものはもちろん別です。 |
●status(ステータス):
パケットの状態をチェックしたりする際に使用する拡張マッチングで、--stateを使うには「-m state」が必要です。つまり、必ず「-m state --state」という形を取ります。今回の例では引数として「ESTABLISHED」が与えられています。ESTABLISHEDなセッション、つまり双方向のコネクションのパケットを許可するということになります。
NEW | 新コネクションを開始するパケット |
ESTABLISHED | 通常の応答パケットあるいは確立中コネクションの応答 |
RELATED | ICMPエラー、FTPデータコネクションなどのパケット |
INVALID | 無効なパケット |
表 --stateのマッチ条件 |
flagとセットで指定することで、クラッカーに侵入されてしまってもほかのホストへの踏み台とされないようにします。これも大切なセキュリティ対策の1つと考えられます。
以上、Webサーバを例に設定方法を紹介しました。メールサーバやDNSサーバへのアクセス許可も、これを参考にすれば設定できるでしょう。
INPUT/OUTPUTチェイン
外部のホストからファイアウォール自身に、メンテナンスなどのために接続することがあるかもしれません。それを許可するルールを追加するのがINPUTおよびOUTPUTチェインになります。INPUTおよびOUTPUTチェインの設定を行っていないと、ファイアウォールそのもののサービスが無防備になるか、逆にまったくアクセスできないということになってしまいます。
■INPUT/OUTPUTチェインの設定
メンテナンスを行うためのホストを限定し、22/TCP(ssh)での接続を許可するような場合を考えてみましょう。
メンテナンス用ホスト(172.16.1.150)から、ファイアウォールの外側のインターフェイスeth0(172.16.0.100)に対する22/TCP(ssh)による接続を許可する。
INPUTチェインには外部からホストへ入ってくるためのルールを、OUTPUTチェインにはホストから外部へ出ていくためのルールを追加します。FORWARDチェインと同じで、入ってくるパケットに対する応答が外部に出ていくことを許可するルールを作成しなければなりません。
# /sbin/iptables -A INPUT -p tcp -s
172.16.1.150 --dport 22 -d 172.16.0.100 -i eth0 -j ACCEPT |
指定されているオプションはこれまでに説明したものばかりなので、特に説明は必要ないでしょう。ここで注意すべき点は、OUTPUTチェインです。FORWARDチェインを作成したときと同じく、flagとstatusにオプションを指定して外部へ接続できないようにすることです。
ICMPの処理
ホストの生存確認を行うために、pingコマンドを使うことは多いのではないでしょうか。ファイアウォール自身についてはEcho Replyを返す必要はありません。しかしながら、DMZ上のホストに関しては生存確認を行いたいと思うことがあるかもしれません。iptablesでアクセス制御を行っているホストは、ICMPについても意図的に通るようにする必要があります。
■生存確認に必要なICMP-TYPEは?
番号
|
メッセージタイプ
|
0 | Echo Reply |
3 | Destination Unreachable |
4 | Source Quench |
5 | Redirect |
8 | Echo Request |
11 | Time Exceeded |
12 | Parameter Problem |
13 | Timestamp Request |
14 | Timestamp Reply |
15 | Information Request |
16 | Information Reply |
17 | Address Mask Request |
18 | Address Mask Reply |
表 Typeフィールド |
iptablesでは、ICMPのTYPEを指定することができます。pingコマンド使うのであれば、Echo Requestを受け付け、Echo Replyを返すことができればいいのです。このICMP-TYPEについて簡単に説明しておきましょう。
ICMPヘッダの中身は、Typeフィールドから始まります。このTypeフィールドの指定番号によって、ICMPメッセージの種類などが決定されます。ICMPには次のようなTypeメッセージが規定されています。
iptablesでは、この番号を指定することができます。ホストの生存確認はpingコマンドを用いることが多いかと思います。pingコマンドは、Echo Requestを目的のホストに向かって送信し、その応答としてEcho Replyが返ってくるのを確認します。そこで、ここでは生存確認を目的とし、Echo RequestとEcho Replyを双方向に許可するためのルールを追加することにしましょう。iptalbesのオプションとしては「--icmp-type」を指定し、引数としてICMP Type番号を指定します。
生存確認のためメンテナンス用のホスト(172.16.1.150)から、Webサーバ(192.168.0.10)に対するEcho Requestと、その応答のためのEcho Replyを許可する。
# /sbin/iptables -A FORWARD -p icmp
-s 172.16.1.150 --icmp-type 8 -d 192.168.0.10 -i eth0 -j ACCEPT |
この設定もまた、これまでに説明したオプションの指定方法とそれほど違いはありません。プロトコルがICMPになったことに注意すればいいでしょう。
■ブロードキャストあてICMPの拒否
ファイアウォールの外側のインターフェイスに対する生存確認のためのEcho Requestを許可すべきではないでしょう。ましてやブロードキャストあてのicmp-echoには応答する必要もありません。ブロードキャストあてのICMPは、カーネルパラメータを調整することでまったく受け付けなくすることができます。
ブロードキャストあてICMPを拒否する場合は、/etc/sysctl.confファイルに設定を記述します。OS起動時にsysctlコマンドが実行されることで、この設定が反映されます。ブロードキャストあてのicmp-echoを無視するには、設定ファイルに次の1行を追加します。
net.ipv4.icmp_echo_ignore_broadcasts
= 1 |
カーネルパラメータを調整することで、ソースアドレスを偽造していないかチェックするような設定もできますが、これには注意が必要です。あまりやり過ぎると、本来の動作をしなくなってしまう危険があります。
総仕上げ:ルールのスクリプト化
パケットフィルタリングの設定方法について一通り解説してきました。これまでのことが理解できればファイアウォールを構築できるでしょう。では、実際にファイアウォール用のルールを作成していきましょう。
ルールを1つ1つ入力してもよいのですが、OSをリブートするたびに同じ作業を繰り返すことになります。効率的ではないしミスも発生するでしょう。以前に紹介したipchainsと同様に、スクリプトを作成することをお勧めします。以下のようなスクリプトを適当なファイル名で作成します。
#!/bin/sh |
サンプルスクリプト |
注:メールサーバはメールの送信、DNSサーバは名前解決のために外部へ出ていくための経路が必要であろうと仮定しています。 |
スクリプトの作成が終わったら、実行権限を与えて実行すればルールが反映されます。
# chmod 744 filename |
しかし、このままではOSの起動時にこの設定は反映されません。そこで、次のコマンドを実行します。
# /sbin/iptables-save > /etc/sysconfig/iptables |
これでファイアウォールの構築作業は取りあえず完了です。次回は、構築したファイアウォールの動作確認方法などについて説明したいと思います。