FreeBSD 11.2 RELEASE - OS 起動後の基本的な設定 - ファイアウォール IP Firewall

 
1. 概要
2. カーネルの再構築
3. /etc/rc.conf 設定
4. デフォルトの設定を見てみる
5. 拒否のフィルタを追加
6. コンフィグレーションファイルの作成
7. フィルタ設定のオプション
8. リスト表示のオプション

1. 概要

 危険な考えかもしれませんが、優秀なルータを使用して、ルータのファイアウォールが細かく設定されていれば、サーバ側でファイアウォールを使用する必要はないと思っています。  しかし、ルータが非力な場合は、サーバ側にファイアウォールを設定しなければなりません。  FreeBSD にデフォルトで用意されているファイアウォールを使用することで十分対応できると思っています。  デフォルトで用意されているファイアウォールは IP Firewall、通称 IPFW というそうです。 以下「IP Firewall でパケットフィルタリング」の記事を参考にさせていただきました。

2. カーネルの再構築

 IPFW を有効にするには、カーネルの再構築が必要になります。  カーネルの設定の詳細に関しては「OS 起動後の基本的な設定 - カーネルの再構築」をご参照ください。  4つのオプションを追加します。

options IPFIREWALL
options IPFIREWALL_VERBOSE
options IPFIREWALL_VERBOSE_LIMIT=10
options IPFIREWALL_DEFAULT_TO_ACCEPT
 366行目のオプションは必須、これを定義ことで初めて IPFW が有効になります。  367行目のオプションを定義することでログを取ることができます。  368行目は、ログを有効にしたとき、ログが大量に出力されることを防ぐためにあるそうです。  ここで定義した(単位がわかりませんが)量にログが達した場合、ログの出力が停止するとのこと。  出力が停止したら、コマンドで、ログの量をリセットしてやる必要があるそうです。  よって、この定義は有効にしない方がよさそうです。  369行目は IPFW のデフォルトの動作では、すべてのパケットを deny するそうで、これを定義するとデフォルトの動作が allow になるそうです。  これは気をつける必要があるようで、下記の定義を有効にするか、後で示す、もう一つの方法で、パケットを通過させるようにしておかないと、ファイアウォールを有効にして起動したら、自分自身のパケットもふさいでしまって何もできない状態に陥ることになります。  オプションを設定したら、カーネルをコンパイルしてインストールします。  コンパイル・インストールの手順は「OS 起動後の基本的な設定 - カーネルの再構築」を参照してください。

3. /etc/rc.conf 設定

 カーネルの構築までできたら、/etc/rc.conf を編集してファイアウォールを有効にします。

firewall_enable="YES"
 もう一点、前項で「options IPFIREWALL_DEFAULT_TO_ACCEPT」を定義していない場合は

firewall_type="open"
 を指定することで、デフォルトの動作を allow にすることができます。  どのタイミングで reboot するか迷うところですが、allow の設定を行っていれば、ここらで一度 reboot してもいいかと思います。

4. デフォルトの設定を見てみる

 ここから先は ipfw というコマンドを使用します。  前項までの設定を終えて、再起動後にファイアウォールのルールがどうなっているのかを見てみます。

> ipfw -a list
00100  64 22370 allow ip from any to any via lo0
00200   0     0 deny ip from any to 127.0.0.0/8
00300   0     0 deny ip from 127.0.0.0/8 to any
00400   0     0 deny ip from any to ::1
00500   0     0 deny ip from ::1 to any
00600   0     0 allow ipv6-icmp from :: to ff02::/16
00700   0     0 allow ipv6-icmp from fe80::/10 to fe80::/10
00800   0     0 allow ipv6-icmp from fe80::/10 to ff02::/16
00900   0     0 allow ipv6-icmp from any to any ip6 icmp6types 1
01000   0     0 allow ipv6-icmp from any to any ip6 icmp6types 2,135,136
65535 395 44855 allow ip from any to any
 list はリスティング。-a オプションがすべてということのようです。  1フィールド目がフィルタの番号で 0~65535 が設定できるそうです。  フィルタのチェックは若い順にチェックするとのことで、この場合、200~500 までしか deny がないので 100~500 をすり抜けてきたものは最後の 65535 で allow ip from any to any ですべての ip が any から any へ届くことを許可しているので、通信可能となるわけです。  200~500 の deny はループバックアドレスの通信を語る外部のものや、自分のループバックアドレスから外部へ出るものを遮断しているようです。

5. 拒否のフィルタを追加

 やりたいのは、ssh で侵入しようとする外部からの通信を遮断することです。  実現するには例えば以下のように設定します。  123.0.0.0 のネットワークからの ssh の侵入を防ぐには

> ipfw add 10000 deny tcp from 123.0.0.0/8 to me 22
 ここで「10000」はフィルタの番号です。デフォルトの設定と重ならないようにするので 1001~65534 の番号にします。  「tcp」 はプロトコルです。  「123.0.0.0/8 to me」 は 123.0.0.0 ~ 123.255.255.255 の自分に向かってくるアドレスです。  「22」は ssh のポート番号です。  ここのアドレス部を試験的にクライアントマシンのアドレスにすれば試験できますが、手元にサーバマシンのコンソールがないと何もできなくなりますのでご注意を。

6. コンフィグレーションファイルの作成

 前項の設定を拒否したいプロトコル・アドレス・方向・ポートを組み合わせて追加していけば、やりたいことは実現できるわけですが。  コマンドで設定したものは、マシンを再起動するとリセットされてしまいます。  設定を記述したコンフィグレーションファイルを作成してロードするようにします。  例えば、/etc/firewall.conf というファイルを作成して、以下のように記述します。

add 10000 deny tcp from 123.0.0.0/8 to me 22
 前項のコマンドから ipfw というモジュール名をはずしたものです。  作成したら /etc/rc.conf に以下を追加します。

firewall_type="/etc/firewall.conf"
 これで、マシンの再起動もしくは

> service ipfw restart
Flushed all rules.
00100 allow ip from any to any via lo0
00200 deny ip from any to 127.0.0.0/8
00300 deny ip from 127.0.0.0/8 to any
00400 deny ip from any to ::1
00500 deny ip from ::1 to any
00600 allow ipv6-icmp from :: to ff02::/16
00700 allow ipv6-icmp from fe80::/10 to fe80::/10
00800 allow ipv6-icmp from fe80::/10 to ff02::/16
00900 allow ipv6-icmp from any to any ip6 icmp6types 1
01000 allow ipv6-icmp from any to any ip6 icmp6types 2,135,136
Firewall rules loaded.
 でコンフィグレーションファイルの設定が反映されるようになります。

7. フィルタ設定のオプション

 フィルタを設定する際の主なパラメータ・オプションを提示しておきます。

> ipfw [-N] command [index] action [log] protocol from アドレス [port] \
	to アドレス [port] [via interface] [option]
パラメータ意味
-N アドレスやサービス名を 文字列に変換して表示します。
command add ルールを追加します。
delete ルールを削除します。
index ルールの番号を指定します。
log カーネルを IPFIREWALL_VERBOSE つきでコンパイルしていれば、マッチしたルールをログに出力します。
action reject パケットを捨て、ICMP ホスト / ポート到達不能パケットの適切な方を発信元へ送ります。
allow パケットを通過させます。
deny パケットを捨てます。reject と違うのは ICMP を返さないので、相手には何が起こっているかわかりません。
付き合いたくない相手にはこちらの方が有効かと思います。
count パケットカウンタを更新するのみです。
ログと組み合わせると分析に便利なのかしら?
protocol all 任意のプロトコル。
icmp icmp 。ping に使われるプロトコルですね。
tcp tcp
udp udp
アドレス アドレスの直接表記とアドレス/ビットマスクでの指定が可能です。
ポート番号 ポート番号-ポート番号と範囲指定することもできるし、ポート番号をカンマで区切って複数記述することができます。両方を記述することもできますが、両方指定する場合は範囲指定を先に記述しなければなりません。
また ssh のように文字列で指定することもできます。
文字列の方が意図的に何を指定しているかがわかって良いように思います。
文字列は /etc/services に定義してあります。
interface 複数の NIC を使用してルーティングしているときに便利ですね。
option in 入力パケット。
out 出力パケット。
establishedパケットが既に確立されている TCP コネクションの一部であれば (RST または ACK ビットがセットされていれば) マッチします。
このをチェーンの最初の方に置くと通過させたいパケットのチェックでファイアウォールの負担をかけないようにできます。

8. リスト表示のオプション

 リストを表示する際の主なオプションを提示しておきます。

> ipfw [-a] [-c] [-d] [-e] [-t] [-N] [-S] list
オプション意味
-aリスト表示の際にカウンタの値も表示します。
-cコンパクトな形式でルールの一覧を表示します。
-d静的ルールに加え動的ルールも表示します。
-e-d が指定されているときには、 期限が切れた動的ルールも表示します。
-t各チェーンエントリが最後に マッチした時刻を表示します。
-Nアドレスやサービス名を文字列に変換して表示します。
-S各ルールが所属しているセットを表示します。 このフラグが設定されていない場合には、 無効にされているルールは一覧に表示されません。

 わたしがよく使用するのは、以下の使い方です。


> ipfw -aN list