[Home] [Kuri] [Sysad] [Internet?] [Blog] [Java] [Windows] [Download] [Profile] [Flash] [+]

FreeBSD で IPFW

FreeBSD には、パケットフィルタリングの機能が標準で備わっています。 それがIPFWです。その設定方法について(わかっている範囲内で) 簡単に書きます。
※ 1999年10月に書いたものですので、内容が古い可能性があります。

目次


1. 環境

当時は FreeBSD 2.2.2R で行いました。
ただし、各ファイルの中身などは、現環境(FreeBSD 3.2R)を元に書いて います。

2. 前準備

2.1 カーネルの再構築

以下のオプションつきのカーネルが必要となります。GENERIC では指定 されていませんので、以下を追加して再構築しましょう。

  options  IPFIREWALL              #firewall
  options  IPFIREWALL_VERBOSE      #print information about dropped packets
  options  "IPFIREWALL_VERBOSE_LIMIT=100" #limit verbosity

最低 IPFIREWALL が必要です。
拒否したパケットのログを syslog でとりたい場合は、IPFIREWALL_VERBOSE が必要になります。
IPFIREWALL_VERBOSE_LIMIT は、ログが大量にならないための制限です。 拒否しているところに大量にアクセスされると、たくさんのログになってし まいますので、上限を指定します。

2.2 rc.conf の変更(追加)

firewall 関連の設定は以下の4つがあります。

  firewall_enable="YES"
  firewall_script="/etc/rc.firewall"
  firewall_quiet="NO"
  firewall_type="/some/where/ipfw.conf"

最初の firewall_enable は、IPFW を使うなら YES です。
firewall_script は、/etc/rc.firewall でいいと思います。
firewall_quiet は、YES にすると、ipfw コマンドに -q オプションを 渡します。 flush などの際にメッセージが出力されますが、それを抑制します。
firewall_type は、rc.firewall を見ればわかると思いますが、以下の ようになっています。

firewall_type意味
open制限なし
clientクライアントとしての最小限な設定(※1)
simpleファイアウォールとしての最小限な設定(※2)
その他設定ファイルとみなし、ipfw コマンドの引数に渡す

※1 は、open よりはやや厳しいですが、クライアントとしての最小限 の設定だけを行います。
※2 は、2つのネットワークインタフェースを持つマシン用の設定で、 通過するパケットに対するフィルタリングも行われます。
※1,※2 は、自分の環境に合わせて rc.firewall を書き換える必要が あります。詳しくは [
こちら] をご覧ください。
※1,※2 では不満な場合などは、設定ファイルを書いてそれを指定すれ ばお好みのファイアウォールにすることができます。
以降では、設定ファイルを指定する方法について述べます。

2.3 reboot

エラーらしきものが出ていないかどうか確認します。

3. 設定ファイルを書く

/sbin/ipfw コマンドの引数に設定ファイルを指定すると、その中のルール を順番に解釈してくれます。
各ルールで指定するものに、番号があります。 番号は unsigned short の範囲内で、小さいほど優先度が高くなります。
65535番に、何も通さないという設定が必ず入ります。 番号を指定しない場合は、直前に指定した番号から 100 足された値に なります。65434 を越える場合は 65434 のままになります。
詳細については man や handbook をご覧ください。
ファイルでなく、ルールをそのまま引数に渡せます。以降では、ルール をそのまま引数に渡す場合の簡単な例を示します。

  # ipfw add 1000 pass all from 127.0.0.1 to 127.0.0.1

これを実行すると、ローカルからローカルへのIPパケットをすべて通す ようになります。
add は追加、1000 は番号、pass は通す(逆は deny)、all はプロトコル の指定ですべて(他に tcp,udp,icmp などがあります)、from 127.0.0.1 は送り元でローカルホスト、to 127.0.0.1 は宛先でこれまたローカル ホスト、です。 つまり、ローカルホストからローカルホストへの、すべてのプロトコル のパケットを通す、を追加してくれ、という意味になります。

  # ipfw add 10000 deny log tcp from 192.47.224.0/24 to 192.46.224.211 23

これは、192.47.224/24 から 192.47.224.211 への telnet を通しません。 ここで log とありますが、これは、このルールに引っかかった場合、 syslog にメッセージを残すように、という意味です。 (ただし IPFIREWALL_VERBOSE がないと残りません。)
以下のようなメッセージが(例えば /var/log/messages に)出力されます。

  /kernel: ipfw: 10000 Deny TCP 192.47.224.11:1026 192.47.224.211:25 via ep0

これを何度も受けて上限を越えると、出力されなくなります。
ipfw flush 10000 としてカウントを 0 に戻せば、またログに残ります。

  # ipfw add deny all from 192.47.224.0/24 to any in via ep0

内側 LAN が 192.47.224/24 で、外側I/F が ep0 だったときの、スプー フィングアタック対策です。 ep0 から、ソースが 192.47.224/24 のパケットが来た時は、アドレスを 偽っているとみなしてパケットを落します。

あとはこれらの組み合わせとなります。
なるべくコンソール上のコマンドライン上でいろいろ試してみてください。 よくないルールを add してしまった場合は、ipfw delete 番号 で消す ことができます。
これでいいという組合せができたら、設定ファイルに書き移して、以下の ように実行してみます。
(注意: リモートや X 上で行わないでください。 flush を実行すると、今までのコネクションがすべて切れます。)

  # ipfw -f flush
  # ipfw 設定ファイル

これで問題なければ、firewall_type にこの設定ファイルのパスを指定し、 reboot してみます。

4. 基本的な考え方

番号の小さい方から、個別の通したいルールを書いていきます。細かな ものほど小さい番号にしておいた方がいいです。
例えば以下のような感じです。

ルール意味
add 1000 pass all from 127.0.0.1 to 127.0.0.1 ローカルホスト同士はなんでも通す
add 2010 pass tcp from any to 192.47.224.211 80 setup 192.47.224.211 への HTTP, FTP のコネクション確立要求 の TCP パケットを通す
add 2010 pass tcp from any to 192.47.224.211 21 setup
add 2100 pass tcp from any to 192.47.224.211 established 192.47.224.211 宛のコネクション確立済の TCP パケットを通す
add 2500 pass all from 192.47.224.211 to any 192.47.224.211 からのパケットをすべて通す
(なし) 上記に該当しないパケットをすべて落す(65535番のデフォルト)

例えば、192.47.224.211 から他のホストに http で問い合わせる場合、 コネクション確立要求パケットは 2500番で許可されていますし、その 返事は 2100番で許可されていますので、問題ないことがわかります。
逆に、192.47.224.211 から DNS サーバに DNS で問い合わせる場合、 問い合わせるパケットは同じく 2500番で許可されていますが、その返事は (UDPの場合)どこにも許可されていませんので、いつまでたっても名前が 引けないことになります。DNS に限れば、以下の1行を add してやれば返事 を受けとれると思います。(番号は適当です。)

    add 2050 pass udp from any 53 to 192.47.224.211


5. ipfw について

細かいオプションについては man 等をご覧ください。

  # ipfw file

ファイルに書いてあるルールを追加します。
ファイルには、1行毎にルールを書けばいいです。

  # ipfw flush

ルールをすべて消します。65535 は消えないです。

  # ipfw zero [number]

カウント数を 0 にします。
IPFIREWALL_VERBOSE_LIMIT の制限に達した場合などに使用します。

  # ipfw delete number

ルールを消します。

  # ipfw list

ルールを出力します。

  # ipfw show

ルールとパケット数を出力します。

  # ipfw add [number] ...

ルールを追加します。

6. /etc/rc.firewall について

client の場合、${ip} を自マシンのIPアドレス、${net}:${mask} を所属する LAN のネットワークアドレスおよびネットマスクとしています。
また、simple の場合、${oif} を外向きのインタフェース、${oip} を外向き のIPアドレス、${onet}:${omask} を所属する外向きのネットワークアドレス およびネットマスク、${iif} を内向きのインタフェース、${iip} を内向き のIPアドレス、${inet}:${imask} を内向きのネットワークアドレスおよび ネットマスクとしています。
client か simple にする際には、それぞれ適切な値を rc.firewall 内に 記述してください。
以下、それぞれのルールについて簡単に述べます。

firewall_typeルール意味
open add 65000 pass all from any to any すべてのプロトコルのパケットを通す
client add pass all from ${ip} to ${net}:${mask} 自マシン(${ip})とLAN(${net})とのすべてのプロトコル のパケットを通す
add pass all from ${net}:${mask} to ${ip}
add pass tcp from any to any established コネクション確立済の TCP のパケットを通す
add pass tcp from any to ${ip} 25 setup 自マシン宛の SMTP(25) へのコネクション確立要求の TCP パケットを通す
add pass tcp from ${ip} to any setup ${ip}からのコネクション確立要求の TCP パケットを通す
add deny tcp from any to any setup 上記に該当しないコネクション確立要求の TCP パケットを落す
add pass udp from any 53 to ${ip} 自マシンからの DNS への問い合わせと返事を通す
add pass udp from ${ip} to any 53
add pass udp from any 123 to ${ip} 自マシンからの NTP への問い合わせと返事を通す
add pass udp from ${ip} to any 123
simple add deny all from ${inet}:${imask} to any in via ${oif} 送り元を偽ったパケットを落す
add deny all from ${onet}:${omask} to any in via ${iif}
add deny all from 192.168.0.0:255.255.0.0 to any via ${oif} RFC1918 で規定されたプライベートアドレスを用いたパケット を落す
add deny all from any to 192.168.0.0:255.255.0.0 via ${oif}
add deny all from 172.16.0.0:255.240.0.0 to any via ${oif}
add deny all from any to 172.16.0.0:255.240.0.0 via ${oif}
add deny all from 10.0.0.0:255.0.0.0 to any via ${oif}
add deny all from any to 10.0.0.0:255.0.0.0 via ${oif}
add pass tcp from any to any established コネクション確立済の TCP のパケットを通す
add pass tcp from any to ${oip} 25 setup 自マシン(${oip})宛の SMTP へのコネクション確立要求の TCP パケットを 通す
add pass tcp from any to ${oip} 53 setup 自マシン(${oip})宛の DNS へのコネクション確立要求の TCP パケットを 通す
add pass tcp from any to ${oip} 80 setup 自マシン(${oip})宛の HTTP へのコネクション確立要求の TCP パケット を通す
add deny log tcp from any to any in via ${oif} setup 上記以外の自マシン(${oip})宛のコネクション確立要求の TCP パケット を落す
add pass tcp from any to any setup 上記以外のコネクション確立要求の TCP パケットを通す
add pass udp from any 53 to ${oip} 自マシン(${oip})宛の DNS の問い合わせと返事を通す
add pass udp from ${oip} to any 53
add pass udp from any 123 to ${oip} 自マシン(${oip})宛の NTP の問い合わせと返事を通す
add pass udp from ${oip} to any 123

7. 注意!

ipfw でルールの追加・削除を行う時は、必ずコンソール上で行いましょう。 X やリモートでやるのは自殺行為です。 特に flush すると今までの TCP コネクションはすべて切断されます。
それと、ここをつつかれるといやだというところは明示的にルールに記述し、 log をつけておきましょう。

Powered by Apache PostgreSQL Usupi Logo Kuri Logo
[Home] [Kuri] [Sysad] [Internet?] [Blog] [Java] [Windows] [Download] [Profile] [Flash] [-]
usu@usupi.org Last modified : Wed Jun 6 14:39:00 2001