IP Firewall でパケットフィルタリング


FreeBSD は IP Firewall (以下 IPFW) というカーネルレベルでのパケットフィルタリング機能を持っています。 ここでは IPFW を利用してのパケットフィルタリングの方法を簡単に説明します。

なお、IPFW の詳細についてはハンドブックの『10.7. ファイアウォール』、 または IPFW(8) のオンラインマニュアルを参照してください。

1. IPFW を使うための準備

標準の GENERIC kernel では IPFW が利用できるようになっていません。 このため、IPFW を有効にした kernel を再構築する必要があります。

IPFW を有効にするには kernel コンフィギュレーションファイルに


  options IPFIREWALL
  options IPFIREWALL_VERBOSE

を追加して、kernel を再構築してください。kernel の再構築の手順については、 『kernel の再構築』を参照してください。

kernel で IPFW を有効にしたら、/etc/rc.conf に以下の記述を追加しておきます。


  firewall_enable="YES"

これで、リブート後は IPFW が利用可能な状態になっています。 ただし、これだけだと、一切の通信ができない状況になっているので注意してください。

2. フィルタの状態を確認する

IPFW の設定は ipfw(8) によって行います。

root 権限で ipfw -a list を叩くと現在のフィルタリングの設定を確認できます。 何も設定していない状況では、以下のようになると思います。


  # ipfw -a list
  65535      0        0 deny ip from any to any

1 フィールド目がそのフィルタの番号になります。 この番号は 0 〜 65535 までで、若い番号のフィルタから有効になります。 先述のフィルタの状態であった場合、受信パケットは、 65535 番のフィルタによって評価されます。 65535 番のフィルタは deny ip from any to any なので、全ての IP パケットを拒否します。 このため、一切の通信ができません。

フィルタルールが複数ある場合は、番号の若いフィルタから評価され、 フィルタルールにマッチした時点で評価は終わります。 つまり、65535 番より若い番号のフィルタにて、 パケットの通過を許可するように設定されていれば、65535 番にマッチして、 拒否されることはありません。

この状態では何も出来ないので、まずは


  # ipfw add 65000 allow all from any to any

を実行しておきます。 これで 65000 番のフィルタとして allow ip from any to any が設定されましたので、 全てのパケットを受け入れるということになります。 つまり、このフィルタを通ることで、全てのパケットが受信されるので、 続く 65535 番の deny ip from any to any まで進むことはありません。

以降、(受信パケットを拒否するような)フィルタを追加するには 65000 番より若い番号のフィルタとして追加する必要があります。

3. フィルタを追加する

では、実際にフィルタを追加してみましょう。 リモートホストから自ホストへの X サーバへのパケットを拒否するようなフィルタリングを考えてみます。 X サーバへの通信は TCP の 6000 番ポートを通じて行われますから、 リモートホストから自ホストの TCP の 6000 番ポートへのパケットを拒否すれば良いことになります。 この場合のフィルタリングルールは


  deny tcp from any to me 6000

になります。これを 65000 番より前のフィルタとして登録します。 ここでは 60001 番として登録してみましょう。 この場合、以下のようなコマンドラインになります。


  # ipfw add 60001 deny tcp from any to me 6000
  60001 deny tcp from any to me 6000

from any は『全てのホストからのパケット』という意味になります。 特定のホストからのパケットに絞りたい場合は from 192.168.0.1 というような指定や、ホスト名の指定も可能です。 また、from 192.168.0.0/24 というように、 ネットワークアドレスを指定することも可能です。

ただし、any は自分自信も含みます。 自分自身を示す me という名前を使って、 自分自信からのパケットは許可するように設定します。 me はループバックインターフェースを含む、 自分自信に割り当てられた IP アドレス全てを示すキーワードになりますので、 便利です。

先程追加した 60001 番のフィルタでは TCP の 6000 番ポートに対する全てのパケットが拒否されてしまうので、 特定の IP アドレスからのパケットのみ許可するには、60001 番より前にフィルタを設定する必要があります。 ここでは 60000 番として追加してみましょう。この場合のフィルタリングルールは


  allow tcp from me to me 6000

となりますから、コマンドラインは以下のようになります。


  # ipfw add 60000 allow tcp from me to me 6000
  60000 allow tcp from me to me 6000

では、現時点のフィルタの状況を確認してみましょう。


  # ipfw -a list
  60000 allow tcp from me to me 6000
  60001 deny tcp from any to me 6000
  65000 354796 84007947 allow ip from any to any
  65535      0        0 deny ip from any to any

このようになっているはずです。 設定したフィルタを解除したい場合は


  # ipfw delete <フィルタ番号>

とします。

4. 起動時にフィルタが設定されるようにする

いちいち、こんなのを手打ちで設定していては面倒なので、 設定ファイルを用意して、起動時にフィルタルールが登録されるようにします。

まず、設定ファイルを用意します。 この例では /etc/my_firewall とします。

/etc/my_firewall に以下のように ipfw コマンドの引数を記述していきます。


  add 60000 allow tcp from me to me 6000
  add 60001 deny tcp from any to me 6000
  add 65000 allow all from any to any

/etc/my_firewall の記述が完了したら、/etc/rc.conf に以下の記述を追加します。


  firewall_type="/etc/my_firewall"

これで、次回起動時から /etc/my_firewall に記述したフィルタが自動で設定されます。


tetSTREAMS > FreeBSD > IP Firewall でパケットフィルタリング