LoginSignup
19

More than 5 years have passed since last update.

FreeBSDでpfを使う(1/2)

Posted at

OS Xを含むBSD系OSで使われている Firewall の pf の設定メモ.普段は Linux の iptables しか書いていない人なので間違っているところもあるかも.できるだけ iptables と対比させながら書いて見る.pfのテスト環境は10.0-RELEASE-p12.iptablesの方は検証せずに書いているので参考程度に.

参考資料

原則

pf はルールが上から順番に評価されるが,マッチするルールがあってもそこで評価は停止しない.最後にマッチしたルールが適用される.ただし,quickをつけた場合にはそこで評価が終了し,そのルールが適用される.

Rule Syntax

フィルタの文法は以下の通り.詳しくはOpenBSDのドキュメントを参照のこと

action [direction] [log] [quick] [on interface] [af] [proto protocol] \
   [from src_addr [port src_port]] [to dst_addr [port dst_port]] \
   [flags tcp_flags] [state]

FreeBSDでのpfの有効化方法

/etc/rc.confに以下の行を追加する.

pf_enable="YES"
pf_flags=""
pflog_enable="YES"
gateway_enable="YES"

とりあえず有効化するだけであればservice pf startでできる.ログは別のサービスで取るのでservice pflog startも必要.gateway_enableはNATを使いたければ必要.

基本形

ローカルループバックは許可し,入ってくるパケットはログを取った上ですべて拒否する.ただし,出て行くパケットに関連付けられていたパケットは許可する.

# Allow Local Loop back
set skip on lo0

# packet is silently dropped
set block-policy drop

# Block and log add packets from outside
block in log all

# Allow all packets to go out, and keep state of them
pass out all keep state

pass out all keep stateで出て行くパケットの状態を記録し,これに関連する内向き通信を許可することを示している.関連すると判定された場合にはそもそもフィルタのチェック対象にはならない.iptablesの-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPTに相当するが,in/outが逆なので一瞬戸惑う.

相当するiptables

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT 
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -j LOG --log-prefix "iptables-INPUT-drop:" --log-level 5

ログを確認する

ログは標準では/var/log/pflogに出力されている.ただ,このログはバイナリなので直接は読めない.そこでtcpdumpを使う.

$ tcpdump -n -e -ttt -r /var/log/pflog

iptablesのようにログにヘッダーはつけられないけど,何番目のルールにマッチし,結果としてblockされたのかpassされたのかも一緒に記録されるのでそれほど問題にはならないはず.

参考

もし,ログをリアルタイムに確認したければtcpdump -n -e -ttt -i pflog0でできる.

特定のサービスのIncomingを許可

SSHを許可してみる.サービスの名前は/etc/servicesにあるものが使える.数字でも良い.

set skip on lo0
set block-policy drop

block in log all
pass in proto tcp to any port ssh
pass out all keep state

相当するiptables

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT 
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -j LOG --log-prefix "iptables-INPUT-drop:" --log-level 5

特定のアクセス元のみIncomingを許可

IPアドレスを指定して接続を許可する.この例では192.168.67.0/24からのSSHアクセスを許可している.

set skip on lo0
set block-policy drop

block in log all
pass in proto tcp from 192.168.67.0/24 to any port ssh
pass out all keep state

相当するiptables

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT 
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -m state --state NEW -m tcp --dport 22 -s 192.168.67.0/24 -j ACCEPT
-A INPUT -j LOG --log-prefix "iptables-INPUT-drop:" --log-level 5

複数のポート,IPをまとめて指定する.

{}で囲うことで複数のサービス/IPをまとめて指定できる.

set skip on lo0
set block-policy drop

block in quick proto udp to any port 17500
block in log all
pass in log proto tcp from {192.168.67.0/24, 192.168.68.0/24} to any port {ssh, http}
pass out all keep state

変数を使う

変数のようなものが使える.

set skip on lo0

tcp_services="{ ssh, http }"
acceptables_ip="{ 172.16.0.0/12, 192.168.0.0/16 }"

block in quick proto udp to any port 17500
block in log all
pass in log proto tcp from $acceptables_ip to any port $tcp_services
pass out all keep state

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19