| トップ | Solaris | FreeBSD | Gentoo | CentOS | Fedora | Windows | Tips | 自宅サーバの動作確認 | サイト内検索(Namazu) | サイト内検索(HE) |
「Packet Filter」を利用してパケットフィルタリングを行う。
ここでは通信のみの制御で、ルータとしての機能は行わない事とする。
当然の事ながら、ここでの設定はあくまで一例なので、この通りに行えば良い、という訳ではなく各自の環境に合わせて設定する。
なお、「Swatch」を利用してログを監視し、アクセス制限を行う場合はこちらを参照。
FreeBSDのバージョンが古い場合や「Packet Filter」をカーネルに組み込む場合、カーネルを再構築する。
FreeBSD5.3以降であればloadable moduleとして組み込まれているので、無理にこの作業を行う必要は無い。
なお、ここでは最低限必要なもののみ設定している。
「Packet Filter」用の設定
ALTQを有効にする場合の記述もあるが、当サイトではALTQは利用しない。
ALTQについてはこちらを参照。
FreeBSD# cd /usr/src/sys/i386/conf FreeBSD# cp GENERIC MYKERNEL <= カーネル設定ファイルのコピー FreeBSD# vi MYKERNEL <= 設定ファイルの編集 使用しているCPU以外の部分はコメントアウトする cpu I486_CPU cpu I586_CPU cpu I686_CPU ↓ #cpu I486_CPU <= コメントアウト #cpu I586_CPU <= コメントアウト cpu I686_CPU ident GENERIC ↓ ident MYKERNEL <= 新しいカーネルの名前(変更したファイル名) 以下を追加(Packet Filter用) device pf device pflog device pfsync ALTQを利用する場合、以下も追加 options ALTQ options ALTQ_CBQ # Class Bases Queuing (CBQ) options ALTQ_RED # Random Early Detection (RED) options ALTQ_RIO # RED In/Out options ALTQ_HFSC # Hierarchical Packet Scheduler (HFSC) options ALTQ_PRIQ # Priority Queuing (PRIQ) options ALTQ_NOPCC # Required for SMP build |
カーネルの再構築
上記の設定後、以下のようにしてカーネルを再構築し、インストールする。
FreeBSD# config MYKERNEL FreeBSD# cd ../../compile/MYKERNEL FreeBSD# make depend FreeBSD# make FreeBSD# make install |
新しいカーネルで起動しない場合
カーネル再構築後、リブートして新しいカーネルで起動するが、起動に失敗する場合、以下のように対処する。
まず、Boot時の起動レベルの選択中にEnterキー以外のキーを押下し
unload boot kernel.old |
と入力すれば古いカーネルで起動する。
その後、設定ファイルを修正し、再度カーネルの構築を行う。
設定ファイルを編集し、必要な設定を記述する。
FreeBSD# vi /etc/rc.conf <= 設定ファイルの編集 以下を追加 pf_enable="YES" # Enable PF (load module if required) pf_rules="/etc/pf.conf" # rules definition file for pf pf_flags="" # additional flags for pfctl startup pflog_enable="YES" # start pflogd(8) pflog_logfile="/var/log/pflog" # where pflogd should store the logfile pflog_flags="" # additional flags for pflogd startup |
セクション
「Packet Filter」の以下の7つのセクションから構成されている。
| セクション | 説明 |
|---|---|
| Macros | IPアドレスやインタフェース名等、ユーザ定義の変数。 |
| Tables | IPアドレスのリストの構造体。 |
| Options | オプション。 |
| Normalization | パケットの通常化およびデフラグメントするための再処理行程。 |
| Queueing | 帯域制御とパケットの優先付け。 |
| Translation | NATとパケットリダイレクションの制御。 |
| Filtering | フィルタリングルール。 |
Macros
IPアドレスやインタフェース名等のユーザ定義の変数を設定する。
例えばインタフェース名とLAN内のマシンを指定する場合。
ext_if = "fxp0"
lan_machine = "{ 192.168.0.2, 192.168.0.3 }"
|
Tables
IPアドレスのグループを保持する。
上記のMacrosのlan_machineで設定しているようなリストに比べて非常に高速に実行される。
よって、大規模なアドレスのグループを保持するのに利用する。
Tablesの書式は以下の通り。
table <テーブル名> 属性 { IPアドレス }
|
属性には以下を指定出来る。
| 属性 | 説明 |
|---|---|
| const | テーブルが生成された後にテーブルの内容を変更することは出来ない。 |
| persist | テーブルが生成された後も動的にテーブルの内容を変更出来る。 |
IPアドレスの前に ! あるいは not を指定すると否定になり、例えば以下のように設定する。
table <private> const { 192.168.0.0/24, \
192.168.1.0/24, !192.168.1.1 }
table <blacklist> persist
|
上記の persist を指定した場合、後からテーブルにルールの追加・削除を行う場合、以下のように pfctlコマンドを使う。
FreeBSD# pfctl -t blacklist -Tadd 192.168.2.0/24 <= 追加 FreeBSD# pfctl -t blacklist -Tdelete 192.168.2.0/24 <= 削除 FreeBSD# pfctl -t blacklist -Tshow <= 参照 |
Options
Optionsで指定出来る主なものは以下の通り。
| Options | 説明 |
|---|---|
| set block-policy | blockの動作でのデフォルトの挙動を設定。 ・drop:送信元に通知しない。 ・return:TCPパケットには TCP RST パケットを返し、他のパケットには ICMP UNREACHABLE パケットを返す。 |
| set debug | デバッグレベル ・none:無効 ・urgent:重大なエラーのみ(デフォルト) ・misc:一般的なエラーを含む ・loud:全てのメッセージ |
| set limit | セッションを保持する為のタイムアウトや保持数を設定する。 ・frags:scrubルールを行う為に使用されるメモリプール中のエントリの最大の数。 デフォルトは5000 ・states:keep state が指定されたルールに使用されるメモリプール中のエントリの最大の数。 デフォルトは10000 |
| set loginterface | 統計情報を収集するインタフェースを指定。 |
| set optimization | 以下のいずれかのネットワーク環境のに応じて最適化する。 ・normal:ほとんどのネットワークに適合する(デフォルト)。 ・high-latency:遅延の大きなネットワーク。 ・aggressive:強制的に状態テーブルから接続を除去する。 ビジー状態のファイアウォールのメモリ要求量を減少させる必要がある場合。 ただし、早期にアイドル状態の接続を切断してしまう可能性がある。 ・conservative:アイドル状態の接続を切断しないようにする。 ただし、より多くのメモリ消費量と若干のCPU使用量が増加する。 |
| set timeout | タイムアウトの設定。 ・interval:失効した状態の排除からパケットのフラグメント化までの間の秒数。 ・frag:再構成されていないフラグメントが失効するまでの秒数。 |
| set skip on | 処理を行わないインタフェースを指定。 ループバックインタフェース等で利用。 |
Normalization
パケットの通常化や再構成を行い、正しくないフラグの組み合わせを持つTCPパケットを廃棄する。
すべてのインタフェース上の受信パケットに対してスクラブを行う場合、以下のように指定する。
scrub in all |
指定出来るオプションは以下の通り。
| オプション | 説明 |
|---|---|
| no-df | フラグメント禁止ビットをパケットのヘッダから除去する。 |
| random-id | 送信パケットの識別フィールドの値をランダムな値で書き換える。 |
| min-ttl | TTLの最小値に強制的に適用する。 |
| max-mss | MSS最大値に強制的に適用する。 |
| fragment reassemble | フラグメント化された受信パケットをバッファリングし、完全なパケットに再構成してからフィルタエンジンに渡す。 |
| fragment crop | 重複部分を廃棄する。 |
| fragment drop-ovl | fragment crop に加え、その後に着信する関連フラグメントも含めて廃棄される。 |
| reassemble tcp | IPのTTLを減少させることは禁止し、TCPのパケットヘッダのRFC1323のタイムスタンプを乱数を使用して変調する。 |
Queueing
キューイングの設定を行う。
ALTQを組み込まないと動作しない。
当サイトでは利用しない為、ここでは割愛。
Translation
NATの設定を行う。
当サイトではNATの設定は行わない為、ここでは割愛。
Filtering
「Packet Filter」のメインの設定であるフィルタリングルール。
次から説明。
フィルタリングルール
フィルタリングルールの基本的な構文は以下の通り。
action [in|out] option keyword |
ここでは、上記のそれぞれについて主要なものだけ記述する。
action
actionでは許可するものは pass、破棄するものは block を指定する。
[in|out]
[in|out]は入力の場合、in を、出力の場合は out を指定する。
option
optionで指定出来る主なものは以下の通り。
なお、複数のoptionを指定する場合、上に記述しているものから指定する。
| option | 説明 |
|---|---|
| log | ログに残す |
| quick | 該当する場合、以降のルールをチェックせず適用 |
| on interface | インタフェース |
keyword
keywordで指定出来る主なものは以下の通り。
なお、複数のkeywordを指定する場合、上に記述しているものから指定する。
| keyword | 説明 |
|---|---|
| inet/inet6 | パケットのアドレスファミリ。 ICMPではIPv4とIPv6の実装が異なるのでtypeを指定した場合、必須。 inet:IPv4 inet6:IPv6 |
| proto プロトコル | プロトコル(tcp,udp,icmp等) |
| from,to/all/ IPアドレス | from:発信元IPアドレス to:宛先IPアドレス IPアドレスにanyを指定すると全てに一致する。 なお、allを指定するとfrom any to anyになる。 |
| port ポート番号 | ポート番号。 この設定はprot tcpにした場合のみ指定出来る。 |
| flags flags | TCPのフラグを指定。 以下の左のように指定する。右はフラグの内容。 F:FIN(終了:送信終了) S:SYN(同期:接続要求) R:RST(リセット:強制切断要求) P:PSH(プッシュ:バッファリングせず、すぐアプリケーションに届けるよう要求) A:ACK(肯定:パケットを受け付けた) U:URG(緊急:緊急で扱うべきデータであることを示す) E:ECE(明示的輻輳通知のエコー) W:CWR(輻輳ウィンドウの減少通知) フラグは、flags フラグ/フラグマスク と記述する。 フラグマスクは常に指定する。 例:flags S/SA 拒否:SYN+ACK 許可:SYN+RST、SYN+FIN、SYN+URG、SYN+PSH |
| state | 保存しておくパケットの情報を決定する。 keep state:TCP、UDP、ICMPパケットで保存する。 modulate state:TCPに対してのみ保存する。 パケットがルールにマッチする為に強力な初期シーケンス番号(ISN)を生成する。 synproxy state:詐称された TCP SYN flood からサーバを防護するため、着信するTCP接続のプロキシを行う。 このオプションは、keep state および modulate state の機能を含んでいる。 |
「Packet Filter」の設定
デフォルトの設定ファイルは全てコメントアウトされており、有効な設定が一つもない。
その為、必要な設定の部分をコメント解除するか追記する。
ここでは基本的な部分のみ記述している。
FreeBSD# vi /etc/pf.conf <= 設定ファイルの編集
###################################
# Macros #
###################################
lo_if = "lo0"
ext_if = "fxp0"
lo_addr = "127.0.0.0/8"
lo_net = "192.168.0.0/24"
###################################
# Tables #
###################################
table <fakeaddr> const { 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 169.254.0.0/16 }
table <blacklist> persist
###################################
# Options #
###################################
set block-policy drop
set loginterface fxp0
###################################
# Normalization #
###################################
scrub in all
scrub out all random-id max-mss 1414
###################################
# Queueing #
###################################
###################################
# Translation #
###################################
###################################
# Filtering #
###################################
### INPUT ###
# 基本破棄
block in all
# ループバックの許可
pass in quick on $lo_if from $lo_addr to $lo_addr
pass out quick on $lo_if from $lo_addr to $lo_addr
# 送信元のおかしなもの、拒否しているIPアドレスはログを取って破棄
block in log quick on $ext_if from { <fakeaddr> <blacklist> } to any
# ping(内部ネットワークのみ許可)
pass in quick on $ext_if inet proto icmp from $lo_net to any icmp-type 0
pass in quick on $ext_if inet proto icmp from $lo_net to any icmp-type 8
# SSH
pass in quick on $ext_if proto tcp from any to any port 22 flags S/SA modulate state
# DNS
pass in quick on $ext_if proto {tcp, udp} from $lo_net to any port 53 keep state
# IDENT
block return-rst in quick on $ext_if proto tcp from any to any port 113
### OUTPUT ###
# 基本許可
pass out all
# Samba
pass out quick on $ext_if proto {tcp, udp} from any to $lo_net port 136 >< 140 keep state
block out quick on $ext_if proto {tcp, udp} from any to any port 136 >< 140
pass out quick on $ext_if proto {tcp, udp} from any to $lo_net port 445 keep state
block out quick on $ext_if proto {tcp, udp} from any to any port 445
# ping(内部ネットワークのみ許可)
pass out quick on $ext_if inet proto icmp from any to $lo_net icmp-type 0
pass out quick on $ext_if inet proto icmp from any to $lo_net icmp-type 8
block out quick on $ext_if proto icmp all
|
「Packet Filter」の起動
FreeBSD# /etc/rc.d/pf start FreeBSD# /etc/rc.d/pflog start |
ルールの確認
FreeBSD# pfctl -vv -s rules -v:詳細な情報を表示 |
ルール更新後の反映
FreeBSD# pfctl -f /etc/pf.conf |
ログの確認
ログファイルは /var/log/pflog であるが、テキストファイルではないので以下のようにして確認する。
なお、リアルタイムに監視する場合のfxp0はデバイス名
FreeBSD# tcpdump -n -e -ttt -r /var/log/pflog <= ログファイルを確認 FreeBSD# tcpdump -n -e -ttt -i fxp0 <= ログファイルをリアルタイムに監視 |
国別IPアドレスリスト破棄の設定
拒否したい国がある場合、以下のようなスクリプトを作成してアクセス拒否の設定をする。
FreeBSD# vi drop_country.sh <= 拒否スクリプトファイル作成
#!/bin/sh
PFCTL="/sbin/pfctl"
WGET="/usr/local/bin/wget"
RM="/bin/rm"
# 国別IPアドレスリスト取得
$WGET -q http://ftp.apnic.net/stats/apnic/delegated-apnic-latest # APNIC
$WGET -q ftp://ftp.arin.net/pub/stats/arin/delegated-arin-latest # ARIN
# 指定した国からのアクセスを破棄
DROP_COUNTRY(){
for IP in `cat $1 | grep "$2|$3|ipv4|"`
do
ADDR=`echo $IP |cut -d "|" -f 4`
TEMP=`echo $IP |cut -d "|" -f 5`
CIDR=32
while [ $TEMP -ne 1 ];
do
TEMP=`expr "$TEMP" / 2`
CIDR=`expr "$CIDR" - 1`
done
$PFCTL -t blacklist -Tadd $ADDR/$CIDR
done
}
# 中国
DROP_COUNTRY delegated-apnic-latest apnic CN
DROP_COUNTRY delegated-arin-latest arin CN
# 韓国
DROP_COUNTRY delegated-apnic-latest apnic KR
DROP_COUNTRY delegated-arin-latest arin KR
# 北朝鮮
DROP_COUNTRY delegated-apnic-latest apnic KP
DROP_COUNTRY delegated-arin-latest arin KP
# 台湾
DROP_COUNTRY delegated-apnic-latest apnic TW
DROP_COUNTRY delegated-arin-latest arin TW
# 国別IPアドレスリスト削除
$RM delegated-apnic-latest
$RM delegated-arin-latest
FreeBSD# chmod 700 drop_country.sh <= 作成したスクリプトに実行権限付加
|