FreeBSD 12.2 RELEASE - 基本設定 - ファイアウォール IP Firewall

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

1. 概要

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

2. カーネルの再構築

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

options IPFIREWALL
options IPFIREWALL_VERBOSE
options IPFIREWALL_VERBOSE_LIMIT=10
options IPFIREWALL_DEFAULT_TO_ACCEPT
 「IPFIREWALL」のオプションは必須、これを定義ことで初めて IPFW が有効になります。  「IPFIREWALL_VERBOSE」のオプションを定義することでログを取ることができます。  「IPFIREWALL_DEFAULT_TO_ACCEPT」は、「IPFW」のデフォルトの動作では、すべてのパケットを「deny」するそうで、これを定義するとデフォルトの動作が「allow」になるそうです。  これは気をつける必要があるようで、下記の定義を有効にするか、後で示す、もう一つの方法で、パケットを通過させるようにしておかないと、ファイアウォールを有効にして起動したら、自分自身のパケットもふさいでしまって何もできない状態に陥ることになります。  他に

options IPFIREWALL_VERBOSE_LIMIT=10	←	値は変えられます。
 というオプションがあって、ログを有効にしたとき、ログが大量に出力されることを防ぐためにあるそうです。  ここで定義した(単位がわかりませんが)量にログが達した場合、ログの出力が停止するとのこと。  出力が停止したら、コマンドで、ログの量をリセットしてやる必要があるそうです。  よって、この定義は有効にしない方がよさそうです。  オプションを設定したら、カーネルをコンパイルしてインストールします。  コンパイル・インストールの手順は「基本設定 - カーネルの再構築」を参照してください。

3. /etc/rc.conf 設定

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

service ipfw enable
 前項で「options IPFIREWALL_DEFAULT_TO_ACCEPT」を定義していない場合

cat << 'EOF' >> /etc/rc.conf
firewall_type="open"
'EOF'
 これを定義することで、デフォルトの動作を「allow」にすることができます。  デフォルトを「allow」にしているならば、この時点で、いったん起動してみます。

$ service ipfw start
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 icmp6types 1
01000 allow ipv6-icmp from any to any icmp6types 2,135,136
Firewall rules loaded.

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」はフィルタの番号です。  デフォルトの設定と重ならないようにするので「10001~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
ハイスピードプラン