IPFW でファイアウォールを作るための TIPS

目次

1. 概要
2. IPFW を導入する際の注意点
2.1. IPFW では防げない攻撃
2.2. IPFW と ftp
2.3. FreeBSD のバージョンについて
3. IPFW の設定法
3.1. 基本的な設定方法
3.2. 基本的なルールセット構成
3.3. keep-state のすすめ
3.4. Windows マシンを守るために
3.5. ログについて
3.6. 外部公開用 ftp サーバの設定法
4. その他の TIPS
4.1. フィルタリングブリッジの設定法
4.2. リモートから設定する際の注意点
4.3. IPFW のオーバーヘッド
4.4. log の書き忘れに注意

1. 概要

FreeBSD でファイアウォールを作る方法には、大雑把に言って以下の3通りがあります。
1. IPFW を使い、パケットフィルタを構築する
パケットフィルタとは、ルータ上で IP パケットのルーティングを制限するシステムのことで、チョークと呼ばれることもあります。LAN とインターネットの間に置き、必要最小限の IP パケットのみをルーティングするよう設定することにより、外部から LAN への攻撃を非常に困難にすることができます。
IPFW image
IPFW は FreeBSD に昔から組み込まれていたパケットフィルタ機能で、現在でも積極的にサポートが行われています。FreeBSD で提供される IP パケット操作用の機能(natd や dummynet やブリッジ機能)とも親和性が高いので、FreeBSD コミュニティでは広く用いられています。

2. IP Filter を使い、パケットフィルタを構築する
IP Filter は、FreeBSD に特化せず Solaris や IRIX など幅広いプラットフォームで動作する汎用パケットフィルタシステムです。最近の FreeBSD では標準で IP Filter 機能を取り込んでいるので IPFW 同様手軽に使うことができます。IP Filter と IPFW のどちらが優れているかは簡単な問題ではなく、最近でも FreeBSD-security メーリングリスト上で議論されていました。

3. FWTK などを使い、Proxy サーバとして構築する
上記 1, 2 と違い、IP パケットのレベルではなくアプリケーション層(Telnet, FTP 等)の Proxy サーバ(代理サーバ)として動作させる方法です。きめ細かいアクセス制御が可能ですが、利用者から見るとやや操作が繁雑になります。上記のパケットフィルタと合わせて使用することも可能です。
ここでは、1. の IPFW を使ってパケットフィルタを構築する方法について説明します。この方法については既に FreeBSD 日本語ハンドブックの中に丁寧なドキュメントがあるので、以下ではハンドブックには書かれていない落とし穴や実践的な TIPS について述べます。

2. IPFW を導入する際の注意点

2.1. IPFW では防げない攻撃

一般に、パケットフィルタでは以下のような攻撃を防ぐことはできません。 逆に、パケットフィルタとは外部からの攻撃を上記 2 点に絞り込むものという見方もできます。

2.2. IPFW と ftp

IPFW を導入してインターネットから LAN への TCP 接続を遮断する設定をすると、LAN からインターネットへの ftp ができなくなることがあります。この場合は、ftp のデータ転送モードを passive にすることにより ftp が可能になります。(Solaris 付属の ftp のように、ftp クライアントが passive モードに対応していないようなら、ファイアウォール上で ftp プロクシサーバを立ち上げるか、ftp コマンド自体を fff (Firewall Friendly Ftp) 等に入れ換えてしまう方がよいでしょう。)

同様に、IPFW の導入によりインターネットから LAN 内の ftp サーバとのデータのやりとりができなくなることがあります。もちろん LAN 内の ftp サーバを外部に公開する設定は必要ですが、それを行なってもまだデータのやり取りに失敗することがあります。これを防ぐには、後述のように ftp サーバの利用するポートを限定して公開する必要があります。

2.3. FreeBSD のバージョンについて

FreeBSD のバージョンによって、IPFW が提供する機能も変化します。たとえば、3.3-RELEASE のころには使えなかった keep-state 機能が 4.1-RELEASE では使えるようになっています。その他、マイナーなバグフィクス等も頻繁に行われているので、FreeBSD のバージョンはなるべく新しいものにした方がいいでしょう。

3. IPFW の設定法

3.1. 基本的な設定方法

IPFW の設定を行う最も簡単な方法は、/etc/rc.conf に以下の行を追加した後、/etc/rc.firewall 中のシェル変数を適宜編集することです。
firewall_type="<ファイアウォールのタイプ>"
firewall_enable="YES"
ここで<ファイアウォールのタイプ>には open, client, simple などを指定できます。(指定できるタイプの一覧は、/etc/rc.firewall 中にあります。)

ファイアウォールのタイプとしてファイル名を指定することにより、IPFW のルールセットを独自に作ることもできます。simple や client などの設定ではすぐに不満が生じるでしょうから、最初から独自のルールセットを作成することをお勧めします。

独自のルールセットファイルを使う場合、/etc/rc.conf 中に例えば

firewall_flags="-p /usr/bin/cpp"
という行を追加することにより、ルールセットファイルを cpp で前処理させることができます。

3.2. 基本的なルールセット構成

ルールセットの構成は LAN の形態に強く依存しますが、多くの場合以下のような設定がいいと思います。
  1. ループバックパケットの許可
  2. アドレス詐称パケットの拒否
  3. TCP 通信の許可
  4. 外部への TCP 接続の許可
  5. 外部から LAN 内の公開サーバへの TCP 接続の許可
  6. (上記以外の)TCP 接続の禁止
  7. keep-state を使った、LAN から外部への UDP 通信の許可
  8. 外部から LAN 内の公開サーバへの UDP 通信の許可
  9. (上記以外の)UDP 通信の禁止
  10. いくつかの ICMP 通信の許可
  11. (上記以外の)一切の通信の禁止
ここに具体的な設定例を挙げておきます。 /etc/rc.firewall 内の設定も参考になるでしょう。実際の設定にあたっては、man ipfw や前に挙げたFreeBSD 日本語ハンドブックを参照しながら慎重に編集してください。

3.3. keep-state のすすめ

keep-state 命令は最近の IPFW で使えるようになった命令です。これを使うことにより、LAN 上のクライアントがインターネットのサーバにアクセスした時にその事実を記憶しておき、そのインターネットのサーバから LAN 上のクライアントへのレスポンスを一定時間許可することができます。この機能は UDP のフィルタリングに有用で、例えば以下のように設定することにより、LAN 上の UDP クライアント(traceroute や ICQ 等)にインターネットへのアクセスを許しながら、インターネットから LAN 上の UDP サーバへの UDP パケットの送信を禁止することができます。
allow udp from <LAN のアドレス> to any keep-state
check-state
deny log udp from any to any
1 行目で LAN からインターネットへの UDP によるアクセスを許可すると同時にその記録をとり、2 行目で 1 行目の記録と同じ経路を通るパケット(逆方向、つまりインターネットから LAN への向きでもよい)に許可を出し、3 行目でそれ以外のパケットの通過を全て禁じています。詳細については man ipfw を参照してください。

keep-state は必ず check-state 命令と組み合わせて使いますが、マシンが遅い場合この check-state 命令のオーバーヘッドに注意する必要があります。check-state 命令では、トラフィックにもよりますが通常のルール数百行から数千行に相当する処理が必要になることがあります。この命令はルールセット中のできるだけ後の方で指定するとよいでしょう。

TCP パケットについても keep-state の指定をすることができますが、keep-state による通信の記憶はパケットのやり取りがないと一定時間で消えてしまうので、長時間パケットを送らないことがある TCP サービス(ssh や telnet など)のアクセス制御に keep-state を使うことは危険です。

3.4. Windows マシンを守るために

Windows マシンを外部の攻撃から守るには、以下の 4 命令をルールセットに追加します。
deny log udp from any to any 137-139,445
deny log udp from any 137-139,445 to any
deny log tcp from any to any 137-139,445
deny log tcp from any 137-139,445 to any
これで NetBIOS 関連の通信は全て遮断できます。ただし、Windows には NetBIOS 以外にも脆弱な個所が多くある(Outlook や IE など)ので、それらのセキュリティホールについてはマイクロソフトからのパッチを当てるなど個別に対応する必要があります。

3.5. ログについて

IPFW に引っかかったパケットについての情報は syslogd を介してログに取られます。ログレベルは /etc/syslog.conf で言うところの security.info になります。FreeBSD のバージョンによってはこのレベルのログはファイルに保存されませんが、その場合は /etc/syslog.conf を適宜編集することをお勧めします。このログには攻撃の試みや、設定ミスによる正規ユーザの占め出しに関する情報を含んでいるので、一定期間毎に管理者に自動的にメールするように設定するとよいでしょう。

3.6. 外部公開用 ftp サーバの設定法

インターネットからのアクセスを許す ftp サーバについては、まず
allow tcp from any to <サーバのアドレス> ftp
として FTP の接続を許します。次に、passive モードでのデータ転送用のポート範囲を定め、外部からその範囲内のポートへの TCP 接続を許可する必要があります。データ転送用ポートの範囲設定については、ftp サーバによって方法が違うので、使用している ftp サーバのマニュアルを参照してください(不可能な場合もあります。)

FreeBSD 付属の ftpd は、デフォルトでポート範囲を絞り込むようになっています。実際のポート範囲については sysctl 変数 net.inet.ip.portrange.hifirst がポート番号の下限に、net.inet.ip.portrange.hilastが上限になります。(sysctl 変数については man sysctl を参照してください。4.1-RELEASE のデフォルトでは下限が 49152 で上限が 65535 です。) 例えば、/etc/rc.firewall の最後に

sysctl -w net.inet.ip.portrange.hifirst=50000
sysctl -w net.inet.ip.portrange.hilast=51000
の 2 行を追加することにより、ポートの範囲を 50000 から 51000 の間に絞ることができます。

ポート範囲の設定が終わったら、それをルールセットに反映させます。例えばポート範囲が 50000 で上限が 51000 なら、以下の行をルールセットに加えます。

allow tcp from any to <サーバのアドレス> 50000-51000

4. その他の TIPS

4.1. フィルタリングブリッジの設定法

FreeBSD には IP パケットをブリッジする機能が含まれており、これと IPFW を組み合わせることにより、フィルタリングブリッジを簡単に構築できます。フィルタリングブリッジのルールセット設定にあたって注意すべきことは特になく、普通のパケットフィルタと同様に記述するだけで動作します。ただし、ARP パケット等をブリッジするには、カーネルコンフィギュレーションファイルに
options IPFIREWALL_DEFAULT_TO_ACCEPT
の行を加えてカーネルを再コンパイルすることが必要です。 ブリッジ機能についての詳細は man bridge を参照してください。

4.2. リモートから設定する際の注意点

起動後に IPFW の設定を変更する際には、ルールセットを記述したファイルを編集しては ipfw コマンドに処理させるということを繰り返します。リモートからログインしてこの作業を行う時には、ipfw コマンドに -q オプションを付けて実行しないと、ipfw コマンドの実行時にリモートログインの接続そのものを切られてしまい、ipfw コマンドも途中で中断され、再ログインも不可能になってしまうことがあります。こうなると、コンソールからしか復帰できなくなってしまいます。

-q オプションをつけてもリモートログインの接続を切られる可能性が僅かながら存在する(ipfw コマンドの実行と同時に wall 出力を受ける場合など)ので、単に

ipfw -p /usr/bin/cpp -q ruleset-file
とするのではなく
(sleep 3; ipfw -p /usr/bin/cpp -q ruleset-file) &
などとして、突然切断されても ipfw コマンドは実行されるように設定しておくことをお勧めします。

4.3. IPFW のオーバーヘッド

最近の PC は速いので、大抵の場合 IPFW のオーバーヘッドは問題にならないと思います。FreeBSD FAQ の中に IPFW のオーバーヘッドの測定結果やパフォーマンスを上げるコツが書いてあるので、気になる人は覗いてみてください。

4.4. log の書き忘れに注意

試行錯誤を繰り返しながらルールセットを書いていると、deny の後の log の指定を忘れることがよくあります。-p オプションで指定するプリプロセッサにより "deny log" を表す識別子を設定するなどして log の書き忘れを防止するとよいでしょう。

natori@is.s.u-tokyo.ac.jp
Last modified: Thu Jan 31 00:43:54 JST 2002