本記事は、FreeBSD の設定手順を解説するシリーズの一部です。
ここでは、ipfw によるファイアウォールの基本設定を記録します。
検証環境は FreeBSD 14.3-RELEASE(ConoHa VPS)を使用しています。
前回の初期設定・セキュリティ設定は以下の記事を参照してください。
→ 【FreeBSD】初期設定とセキュリティ設定(ConoHa VPS/14.3-RELEASE)
本記事で扱う範囲は以下のとおりです。
- ipfw の有効化と基本的なルール設定
- SSH(変更後ポート)の許可、ICMP の制御
- アウトバウンド通信のホワイトリスト制御
- NetBIOS / SMB の明示的な拒否
- 拒否パケットのログ設定
Web やmail 関連のルールは、各サービスの導入時に追加するため含めていません。
設定内容は筆者の環境と運用方針に基づく一例です。あくまで参考としてご覧ください。
ipfw の概要
ipfw は FreeBSD 標準のパケットフィルタです。カーネルレベルで動作し、通過するパケットをルールに従って許可・拒否します。
ルールには番号が割り当てられ、番号が小さい順に評価されます。
最初にマッチしたルールが適用され、どのルールにもマッチしなかったパケットは 65535 番(デフォルト deny)で拒否されます。
また、keep-state と check-state によるステートフルなフィルタリングが可能です。keep-state を付けたルールは通信の状態を記録し、check-state で戻りの通信を自動的に許可します。
これにより、応答パケット用のルールを個別に書く必要がなくなります。
ipfw の有効化
ipfw を有効にする前に、重要な注意点があります。
⚠ ipfw を有効化した時点で、デフォルトではすべての通信が拒否されます。
SSH 接続中に有効化すると、即座にロックアウトされる可能性があります。
必ず VNC コンソールからアクセスできる状態で作業してください。
まず、安全に進めるため /etc/rc.conf に以下を追記します。
# sysrc firewall_enable="YES"
# sysrc firewall_type="open"
# sysrc firewall_logging="YES"
firewall_type="open" はすべての通信を許可する一時的な設定です。
この状態で ipfw を起動し、ルールスクリプトの作成・テストが済んでから本番の設定に切り替えます。
ipfw を起動します。
# service ipfw start
起動後、現在のルールを確認します。
# ipfw list
open の場合、以下のように全許可のルールが表示されます。
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
65000 allow ip from any to any
65535 deny ip from any to any
この状態が確認できたら、次のセクションでルールスクリプトを作成していきます。
ルールスクリプトの作成
ipfw のルールはシェルスクリプトとして記述し、起動時に読み込ませます。
本記事では /usr/local/etc/ipfw.rules にルールスクリプトを作成します。
まず、/etc/rc.conf の firewall_type を open からスクリプトのパスに変更します。
# sysrc firewall_type="/usr/local/etc/ipfw.rules"
※ この時点ではまだ反映しません。スクリプトの作成とテストが完了してから適用します。
ルール番号の設計方針:
ルールは番号順に評価されるため、用途ごとに番号帯を分けておくと管理しやすくなります。
本記事では以下の番号体系を使用します。
| 番号帯 | 用途 |
|---|---|
| 00100〜00199 | ループバック・ステートフル |
| 00200〜00299 | 明示的な拒否(NetBIOS 等) |
| 00300〜00399 | アウトバウンド許可 |
| 00400〜00499 | インバウンド許可 |
| 00500〜 | ログ・デフォルト deny |
番号の間隔に余裕を持たせているため、今後 HTTP/HTTPS やメール関連のルールを追加する際にも対応できます。
スクリプトの雛形:
# vi /usr/local/etc/ipfw.rules
#!/bin/sh
fwcmd="/sbin/ipfw"
# ルール初期化
${fwcmd} -q flush
# --- 00100: ループバック・ステートフル ---
# (次セクションで記述)
# --- 00200: 明示的な拒否 ---
# (次セクションで記述)
# --- 00300: アウトバウンド許可 ---
# (次セクションで記述)
# --- 00400: インバウンド許可 ---
# (次セクションで記述)
# --- 00500: ログ・デフォルト deny ---
# (次セクションで記述)
以降のセクションで、各ブロックのルールを順に記述していきます。
ループバックとステートフルの基本ルール
ループバック(lo0)はサーバ内部の通信に使用されます。
これを許可しないと、localhost を使うサービスが正常に動作しません。
また、check-state を早い段階に配置することで、確立済みの通信を効率よく処理できます。
# --- 00100: ループバック・ステートフル ---
${fwcmd} -q add 00100 allow ip from any to any via lo0
${fwcmd} -q add 00101 deny ip from any to 127.0.0.0/8
${fwcmd} -q add 00102 deny ip from 127.0.0.0/8 to any
${fwcmd} -q add 00110 check-state
| ルール | 内容 |
|---|---|
| 00100 | ループバックインターフェース経由の通信をすべて許可 |
| 00101〜00102 | lo0 以外での 127.0.0.0/8 通信を拒否 |
| 00110 | 確立済みセッションに属するパケットを許可 |
明示的な拒否
不要なことが明らかな通信を早い段階で拒否しておきます。
プライベート IP アドレスは、インターネット側から届くことはないため、なりすまし防止として拒否します。
NetBIOS / SMB 関連のポートはインターネット上から狙われやすく、VPS 環境で使うことはまずありません。
# --- 00200: 明示的な拒否 ---
# プライベート IP アドレス
${fwcmd} -q add 00200 deny ip from 10.0.0.0/8 to any
${fwcmd} -q add 00201 deny ip from any to 10.0.0.0/8
${fwcmd} -q add 00202 deny ip from 172.16.0.0/12 to any
${fwcmd} -q add 00203 deny ip from any to 172.16.0.0/12
${fwcmd} -q add 00204 deny ip from 192.168.0.0/16 to any
${fwcmd} -q add 00205 deny ip from any to 192.168.0.0/16
# NetBIOS / SMB
${fwcmd} -q add 00210 deny tcp from any to any 135
${fwcmd} -q add 00211 deny tcp from any to any 137-139
${fwcmd} -q add 00212 deny udp from any to any 137-139
${fwcmd} -q add 00213 deny tcp from any to any 445
${fwcmd} -q add 00214 deny udp from any to any 445
| ルール | 内容 |
|---|---|
| 00200〜00205 | プライベート IP アドレス(10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)の送受信を拒否 |
| 00210 | RPC(135/TCP)を拒否 |
| 00211〜00212 | NetBIOS(137-139/TCP, UDP)を拒否 |
| 00213〜00214 | SMB(445/TCP, UDP)を拒否 |
※ VPS 環境では内部ネットワークにプライベート IP を使用しているケースがあります。ConoHa VPS でプライベートネットワーク機能を利用している場合は、該当するアドレス帯を拒否ルールから除外してください。
アウトバウンドルール
ホワイトリスト方式のため、サーバから外部への通信も必要なものだけを明示的に許可します。keep-state を付けることで、応答パケットは check-state(00110)で自動的に許可されます。
# --- 00300: アウトバウンド許可 ---
# DNS
${fwcmd} -q add 00300 allow tcp from me to any 53 out setup keep-state
${fwcmd} -q add 00301 allow udp from me to any 53 out keep-state
# NTP
${fwcmd} -q add 00310 allow udp from me to any 123 out keep-state
# HTTP/HTTPS(pkg, freebsd-update 等)
${fwcmd} -q add 00320 allow tcp from me to any 80 out setup keep-state
${fwcmd} -q add 00321 allow tcp from me to any 443 out setup keep-state
| ルール | 内容 |
|---|---|
| 00300〜00301 | DNS の名前解決(53/TCP, UDP)を許可 |
| 00310 | NTP の時刻同期(123/UDP)を許可 |
| 00320〜00321 | HTTP/HTTPS(80, 443/TCP)を許可。pkg update や freebsd-update で必要 |
アウトバウンドの HTTP/HTTPS は、Web サーバとしてのインバウンド許可とは別です。
ここではサーバ自身がパッケージの取得やアップデートを行うために必要な通信を許可しています。
今後、メールサーバを導入する際には、SMTP の送信(25/TCP)などをこの番号帯に追加します。
インバウンドルール
現時点では ICMP と SSH のみ許可します。
# --- 00400: インバウンド許可 ---
# ICMP
${fwcmd} -q add 00400 allow icmp from any to me in icmptypes 0,3,8,11
# SSH
${fwcmd} -q add 00410 allow tcp from any to me 10022 in setup keep-state
| ルール | 内容 |
|---|---|
| 00400 | ICMP の必要な型を許可 |
| 00410 | SSH(変更後ポート 10022)への接続を許可 |
ICMP で許可している型の内訳は以下のとおりです。
| 型番号 | 名称 | 用途 |
|---|---|---|
| 0 | Echo Reply | ping の応答 |
| 3 | Destination Unreachable | 到達不能通知(経路やポートの問題把握に必要) |
| 8 | Echo Request | ping の受信(死活監視に使用) |
| 11 | Time Exceeded | traceroute の応答やTTL超過通知 |
外部からの死活監視を行わない場合は、型番号 8(Echo Request)を除外しても構いません。
※ SSH のポート番号は sshd_config で設定した値に合わせてください。
HTTP/HTTPS(80, 443)やメール関連(25, 587, 993 等)のインバウンドルールは、各サービスの導入時にこの番号帯に追加していきます。
ログとデフォルト deny
ここまでのルールにマッチしなかったパケットを、ログに記録したうえで拒否します。
# --- 00500: ログ・デフォルト deny ---
${fwcmd} -q add 00500 deny log ip from any to any
log を付けることで、拒否されたパケットの情報が syslog に出力されます。
不正アクセスの兆候や設定漏れの発見に役立ちます。
ログ出力先の設定:
デフォルトでは ipfw のログは /var/log/security に出力されます。
専用のログファイルに分離したい場合は、/etc/syslog.conf に以下を追記します。
# vi /etc/syslog.conf
security.* /var/log/ipfw.log
ログファイルを作成し、syslogd を再起動します。
# touch /var/log/ipfw.log
# service syslogd restart
ログローテーションの設定:
ログが肥大化しないよう、/etc/newsyslog.conf にローテーション設定を追加しておきます。
# vi /etc/newsyslog.conf
以下の行を追加します。
/var/log/ipfw.log 600 7 1000 * JC
| 項目 | 内容 |
|---|---|
| 600 | ファイルのパーミッション(root のみ読み書き) |
| 7 | 保持する世代数 |
| 1000 | ローテーションするサイズ(KB) |
| * | 時間指定なし(サイズのみで判定) |
| JC | bzip2 圧縮、存在しなければ作成 |
なお、/etc/rc.conf の firewall_logging="YES" は ipfw の有効化のセクションで設定済みです。
ルールの適用と動作確認
ルールスクリプトが完成したら、まずスクリプトに実行権限を付与します。
# chmod 700 /usr/local/etc/ipfw.rules
⚠ 重要:適用前に VNC コンソールからアクセスできることを確認してください。
ルールに問題があると SSH 接続が即座に切断され、復旧は VNC 経由でしか行えません。
ルールの適用:
# service ipfw restart
現在のルールを確認:
# ipfw list
スクリプトに記述したルールが番号順に表示されることを確認します。
通信カウンタの確認:
# ipfw show
各ルールにマッチしたパケット数とバイト数が表示されます。
しばらく運用した後に確認すると、どのルールが実際に使われているか把握できます。
接続テスト:
適用後、以下の順で確認します。
- 新しい Tera Term ウィンドウを開き、変更後のポートで SSH 接続できることを確認
- 外部から
pingを実行し、応答があることを確認 - サーバ側から
freebsd-update fetchやpkg updateを実行し、アウトバウンド通信が正常に動作することを確認
すべて問題なければ、ファイアウォールの設定は完了です。
万が一接続できなくなった場合は、VNC コンソールからログインし、一時的にルールを全許可に戻して原因を調査します。
# ipfw -q flush
# ipfw -q add 65000 allow ip from any to any
この時点での状態まとめ
ここまでの設定で、ipfw によるファイアウォールが有効になっています。
現在のルール構成:
| 番号帯 | 内容 |
|---|---|
| 00100〜00110 | ループバック許可、偽装拒否、ステートフル検査 |
| 00200〜00214 | プライベート IP アドレスの拒否、NetBIOS / SMB の拒否 |
| 00300〜00321 | アウトバウンド許可(DNS, NTP, HTTP/HTTPS) |
| 00400〜00410 | インバウンド許可(ICMP, SSH) |
| 00500 | ログ記録+デフォルト deny |
通信ポリシー:
| 方向 | 方針 |
|---|---|
| インバウンド | SSH と ICMP のみ許可、それ以外はすべて拒否 |
| アウトバウンド | DNS, NTP, HTTP/HTTPS のみ許可(ホワイトリスト方式) |
今後、各サービスの導入に合わせて以下のルールを追加していく想定です。
| サービス | 追加するルール |
|---|---|
| Web サーバ | インバウンド 80, 443/TCP の許可 |
| メールサーバ(Postfix) | インバウンド 25, 587/TCP の許可、アウトバウンド 25/TCP の許可 |
| メールサーバ(Dovecot) | インバウンド 110, 143, 993, 995/TCP の許可 |
次回以降は、以下の内容を予定しています。
- pkg / ports の導入と使い方:ソフトウェアのインストール方法を整理します
- Postfix 設定編:メール送信側の構築に進みます
これらが完了すれば、Postfix や Dovecot などのアプリケーション導入に進む準備が整います。
