PF メモ
投稿日: | |
---|---|
編集日: | |
タグ: |
本稿はBSD系OSのパケットフィルタリングツールPFのメモ。参考にしたのはmanと以下のページである。
実行環境
OS | FreeBSD |
---|---|
バージョン | 10.0 |
アーキテクチャ | i386 |
はじめに
PFを利用するには以下の4つの要素がある。
- カーネルの設定
- PFやPFのログ機能などを利用するにはカーネルの設定が必要である。私の実行環境では標準でPFやログ機能は利用可能だが、ALTQといわれるキューイング制御のためのフレームワークは利用不能であった。
- 設定ファイル
- PF関連の起動スクリプトの設定(/etc/rc.conf)
pf_enable="YES" # pfを実行可能に pflog_enable="YES" # PF用のログインタフェース pflog_logfile="/var/log/pflog" # PF用のログファイルのパスを指定 pf_rules="/etc/pf.conf" # pfの設定ファイルを指定
- /etc/sysctl.conf
-
PFでパケット転送機能を使用するには前述の設定が必要である。OS起動後にこの値を変更するには、次のような処理を行えば良い。net.inet.ip.forwarding=1
user% sysctl net.inet.ip.forwarding=1
また、現在の値については以下のようにして取得できる。user% sysctl net.inet.ip.forwarding
- PFの設定(/etc/pf.conf)
-
以下に例を示す。
# Tables table <private> const { 127.0.0.1 192.168/16 } table <hosts1> persist # Options set block-policy drop # Filtering block in all pass in from any to <private>
- 起動スクリプトの実行
-
PF関連のスクリプトにはpfやpflog、pfsyncなどがある。
user% /etc/rc.d/pf start
- /dev/pf制御用コマンド(pfctl)
-
PFはpfctlコマンドを利用して制御できる。以下にいくつか例を示す。
- ルールテキストのロード
user% pfctl -f /etc/pf.conf
- テーブル操作
user% pfctl -t hosts1 -T add 192.168.1.3
- ルールの確認
user% pfctl -s rules
カーネルの設定
PFやログ機能を利用するには、カーネルがそれに対応していなければならない。
- pf
device pf
- pflog
device pflog
- ALTQ
- ALTQ(ALTernate Queueing of network packets)というBSD系OSのネットワークインタフェースでのキューイング制御のためのフレームワークのこと。ALTQには以下に記すようないくつかのオプションがあるが、その全てが必要な訳ではない。各オプションの機能はmanを参照されたし。
options ALTQ options ALTQ_CBQ options ALTQ_RED options ALTQ_RIO options ALTQ_HFSC options ALTQ_CDNR options ALTQ_PRIQ options ALTQ_NOPCC options ALTQ_DEBUG
pf.conf
PFの設定はpf_rulesで設定したファイル、または/etc/pf.confに記述する。pf.confはいくつかの種類の文からなり、それらは次の2種類に分類できる。
- 変数やアドレスリストの定義
- Macros
- Tables
- ルール行
- Options
- Normalization
- Queueing
- Translation
- Filtering
pf.confのサンプルを以下に示す。
#Comments #から文末までコメント
#Macros 変数の定義
net_if="alc0"
#Tables アドレスリストの定義
table <default> const { 10/8, 172.16/12, 192.168/16 }
table <goodhost> persist # pfctlで追加するリスト
#Options パラメータの設定
set block-policy drop
set timeout { icmp.first 20 }
#Normalization パケットの正規化(分断化されたパケットを再構築すること)の制御
scrub in all
scrub out all random-id max-mss 1414
#Queueing 帯域幅の制御
queue http on parent std bandwidth 100M default
#Translation NATや他のアドレスへのリダイレクトの制御
# nat|rdr|binat on 〜
rdr on $net_if proto tcp from 192.168.1.4 to 192.168.1.2 port 10080 -> 192.168.1.3 port 80
#Filtering ブロックや通過の設定
#block|pass in|out 〜
block in on $net_if all # ファイアウォールから入るのを防ぐ
pass in on $net_if from <default> # default内のアドレスの通過を許可
pass in on $net_if from <goodhost> # goodhost内のアドレスの通過を許可
pf.confの作成や修正が終わったならば、起動スクリプトの再実行("/etc/rc.d/pf restart")や設定ファイルの再読み込み("/etc/rc.d/pf reload")を行えば、ルールが適応される。
変数やアドレスリストの定義
- Macros
-
PFではマクロが利用可能である。
- 代入
var="string"
- 評価
$var
また、マクロの機能という訳ではないがインタフェースを()で囲うことでそれに割り当てられたIPアドレスを指定できる。myaddr="192.168.1.2" nif="alc0" mport="{ 25, 110 }"
($nif)
- Tables
-
PFではいくつかのアドレスの集合を表す仕組みにテーブルがある。テーブルはアドレスのリストで、これによっていくつかのアドレスに対してまとめてブロックや通過などを指定できる。アドレスはIPアドレスやネットワークアドレスを指定できる。また、テーブルには、タイプがいくつかある。以下にいくつか例を紹介する。
- const
-
不変なアドレスリスト。以下のように設定ファイルに記述できる。
table <private> const { 10/8, 172.16/12, 192.168/16 } table <local> const { 127.0.0.1, 192.168.1.15 }
- persist
-
可変なアドレスリスト。以下のように設定ファイルに記述し、
pfctlによって次のように制御できる。table <badhost> persist
- 追加
user% pfctl -t badhost -T add 192.168.1.3
- 削除
user% pfctl -t badhost -T delete 192.168.1.3
ルール行(1)
ルール行は標準では次のような設定に従う。
- PFはフィルタルールセット(/etc/pf.conf)の先頭から末尾へと順に評価される。
- 最後に一致したルールが採用される。
- quickキーワードが付いたルールと一致する場合、そのルールを最終的に一致するルールとなる。
- デフォルトではパケットは通過するように設定されている。
また、ルール行は次の順番で記述しなければならない。
- Options
- Normalization
- Queueing
- Translation
- Filtering
- Filtering
- Translation
- Options
- (Packet) Filtering
-
ファイアウォールの中や外への通信の遮断(block)や通過(pass)などを制御。組合せは以下の4つである。
in out block block in block out pass pass in pass out
Filteringの行の書き方は以下のような流れである。block in from 183.77.202.242 to 192.168.1.2
指定するIPアドレスは直接記述したりTablesで定義したテーブルを指定したりできる。また、全てのアドレスを指す場合は"any"というキーワードが使用でき、"from any to any"と記述する場合は"all"と書いても良い。block/pass [quick] [on interface] in/out [log] from 〜 to 〜
- block block-policy
-
通信を遮断。blockはblock-policyの設定に基づいて動作が変化する。blockのblock-policyを省略した場合の設定はOptionsで設定できる。block-policyには次のいずれかを設定できる。
- drop
- パケットは黙って破棄。
- return
- ブロックされたTCPパケットに対してTCP RST パケットが返され、 他のすべてのパケットに対しては ICMP UNREACHABLE パケットが返されます。
また、Optionsでデフォルトを設定する場合、次のように記述する。block drop on all
set block-policy drop
- pass
-
パケットを通過。
- route-to
- replay-to
- dup-to
- fastroute
<キーワードの一例>
in ファイアウォールの中への通信か外への通信 out log ログを記録(pflogは通常/var/log/pflogにtcpdumpのバイナリ形式で記録される。ログの保存先はrc.confのpflog_logfileで指定可能) on interface ネットワークインタフェース proto protocol プロトコル名。/etc/protocolsに記述されているプロトコル。 inet IPv4/v6 inet6 from 送信元 to 宛先 any 全てのアドレス all from any to anyのこと port ポート番号(TCPやUDP通信などの場合) quick 一致する場合それを最終的に一致するルールとする -
以下に実際のFilteringルールの例を紹介する。
- re0を通したファイアウォール内の192.168.1.21のTCPの110番(POP3)に対するアクセスをブロック
-
またはblock in on re0 inet proto tcp from any to 192.168.1.21 port 110
ポートの指定には次の記号が利用可能。block in on re0 inet proto tcp from any to 192.168.1.21 port = 110
port = x xと等しい port != x xと等しくない port < x x未満 port <= x x以下 port > x xより大きい port >= x x以上 port x:y x以上y以下 port x >< y x未満でかつyより大きい port x <> y x未満かyより大きい - re0を通したファイアウォール内の192.168.1.21のTCPかUDPの110番(POP3)に対するアクセスをブロック
-
block in on re0 inet proto {tcp, udp} from any to 192.168.1.21 port = 110
- 指定したアドレス(badhost)からファイアウォール内へのアクセスをブロック
-
テーブル<badhost>へのアドレスの追加は次のように行う。table <badhost> persist block in from <badhost>
user% pfctl -t badhost -T add 192.168.1.3
- ファイアウォール内への全てのICMPアクセスをブロック
block in inet proto icmp all
- ログを記録
-
ログはpflogによって制御され、通常/var/log/pflogにtcpdumpのバイナリ形式で記録される。icmpであれば、次のようなコマンドでログを取得できる。block in log inet proto icmp all
また、次のようなpop3をブロックするログがあるとする。user% sudo tcpdump -n -r /var/log/pflog icmp reading from file /var/log/pflog, link-type PFLOG (OpenBSD pflog file) 00:13:43.605085 IP 192.168.1.4 > 192.168.1.2: ICMP echo request, id 7202, seq 1, length 64 00:13:44.612563 IP 192.168.1.4 > 192.168.1.2: ICMP echo request, id 7202, seq 2, length 64 00:13:45.620305 IP 192.168.1.4 > 192.168.1.2: ICMP echo request, id 7202, seq 3, length 64
この時、このログは次のようにして取得できる。block in log on re0 inet proto tcp from any to 192.168.1.21 port 110
user% sudo tcpdump -n -r /var/log/pflog port pop3 reading from file /var/log/pflog, link-type PFLOG (OpenBSD pflog file) 00:25:00.624451 IP 192.168.1.4.51868 > 192.168.1.2.110: Flags [S], seq 1646204942, win 14600, options [mss 1460,sackOK,TS[|tcp]> 00:25:01.622446 IP 192.168.1.4.51868 > 192.168.1.2.110: Flags [S], seq 1646204942, win 14600, options [mss 1460,sackOK,TS[|tcp]> 00:25:03.627292 IP 192.168.1.4.51868 > 192.168.1.2.110: Flags [S], seq 1646204942, win 14600, options [mss 1460,sackOK,TS[|tcp]>
<サンプルルール>
- Translation
-
宛先や送信元のアドレスの変更やポート番号などを制御。
- rdr
- リダイレクトまたはポートフォワーディング。あるパケットを別のIPアドレスや別のポート番号に転送する。例えば"192.168.1.4"から"192.168.1.2"のポート番号10080へのTCP通信を"192.168.1.3"のポート番号80に転送する場合、次のように記述する。
また、直接IPアドレスを指定せずインタフェースを()で囲えば、そのインタフェースに割り当てられたIPアドレスを指定できる。rdr proto tcp from 192.168.1.4 to 192.168.1.2 port 10080 -> 192.168.1.3 port 80
rdr proto tcp from any to ($nif) -> 192.168.1.5
- nat
- NATまたはNAPT。あるパケットのアドレスやポート番号を変更する。例えば"192.168.1.2"からの通信を"192.168.1.100"に変更する場合、次のように記述する。
->の右辺は以下のようにインタフェース名を指定することもできる。nat on alc0 from 192.168.1.2 to any -> 192.168.1.100
rdrとは異なり、->の右辺で指定するのは宛先ではなく送信元である。また、宛先ポート番号は指定できないが、送信元ポート番号を指定できる。NAPTは次のように行う。nat on alc0 from 192.168.1.2 to any -> alc1
natの状態はpfctlで確認可能である。nat on re0 proto tcp from 192.168.1.2 port 80 to any -> 192.168.1.100
なお変更後のアドレスには任意のアドレスを利用できるが、通信が成り立つためには相手が経路を確保できることとこちらのインタフェースがそれを取得できることが必要である。例えばローカルネットワーク"192.168.1.0"内で、"192.168.1.2"と"192.168.1.3"のマシンが通信を行い、"192.168.1.2"を"192.168.1.100"に変更する場合、それぞれのマシンで次のような処理が必要である。user% pfctl -s nat
- 192.168.1.2のマシン
-
pf.confに次の行を追加。
インタフェースに"192.168.1.100"をエイリアスし、受信可能にする。nat on re0 from 192.168.1.2 to any -> 192.168.1.100
user% ifconfig re0 alias 192.168.1.100
- 192.168.1.3のマシン
-
192.168.1.2のMACアドレスが"01:23:45:67:89:ab"の時、192.168.1.100に対応するMACアドレスをそれに対応づける。
user% arp -s 192.168.1.100 01:23:45:67:89:ab -i eth0
- binat
- 双方向マッピング。ある2つのアドレスやポート番号を対応させる。例えば192.168.1.1と192.168.1.5を対応付けるには次のように記述する。
binat on re0 from 192.168.1.1 to any -> 192.168.1.5
なおこのような場合最初に一致したルールが最終的な一致となる。no nat on re0 from 192.168.1.2 to 192.168.1.4 nat on re0 from 192.168.1.2 to any -> 192.168.1.100
- Options
-
PFや通信に関する基本的な情報を設定。以下にサンプルを示す。
詳しくは"man pf.conf"を参照されたし。set block-policy drop set timeout { icmp.first 20 }
timeout loginterface limit パケットフィルタで使用するメモリプールの限界値。 ruleset-optimization optimization block-policy Filterのblockでblock-policyを省略した場合のblock-policy。 state-policy hostid require-order fingerrpints skip on debug
ルール行(2)
編集中
- Traffic Normalization
-
分断化されたパケットを再構築(正規化)する際の制御。詳しくは"man pf.conf"を参照されたし。
scrub in all scrub out all random-id max-mss 1414
- Queueing
pfctl
pfctlの詳細は"man pfctl"で閲覧できる。以下にいくつかpfctlの機能を紹介する。
- ルールテキストのロード
user% pfctl -f /etc/pf.conf
- テーブル操作
user% pfctl -t hosts1 -T add 192.168.1.3
- ルールの確認
user% pfctl -s rules
- PFを有効に
user% pfctl -e
- PFを無効に
user% pfctl -d
メモ
- タグ