EN JA
PF.CONF(5)
PF.CONF(5) FreeBSD File Formats Manual PF.CONF(5)

名称

pf.confパケットフィルタ設定ファイル

解説

pf(4) パケットフィルタは、 pf.conf で指定された規則か定義に従って、パケットを変更するか、落とすか、または通過させます。

文の順序

pf.conf には、7 つのタイプの文があります:
Macros
ユーザ定義変数は、設定ファイルを簡素化して、後で定義されて使用されます。マクロは、それらが pf.conf で参照される前に定義されなければなりません。
Tables
テーブルは、多くの発信元 (始点) または宛先 (終点) アドレスで規則の性能と柔軟性を増強するためのメカニズムを提供します。
Options
オプションは、パケットフィルタエンジンの振る舞いを調整します。
Traffic Normalization (例えば、 scrub)
トラフィックの正常化は、インターネットプロトコルと実装における矛盾に対して内部のマシンを保護します。
Queueing
キューは、規則ベースの帯域幅制御を提供します。
Translation (様々な形式の NAT)
変換規則は、アドレスがどのように他のアドレスにマップされるか、またはリダイレクト (出力先変更) されるかを指定します。
Packet Filtering
パケットフィルタリングは、パケットの規則ベースの遮断 (ブロック) または通過 (パス) を提供します。

macrostables を除いて、文のタイプは、基本的なパケットフィルタエンジンの操作に適合するように、上記に示したような順序で pf.conf に分類されて、現れるべきです。デフォルトで、 pfctl(8) は、この順序で実行します (下記の set require-order 参照)。

ハッシュマーク (‘#’) を使用して現在の行の終りまでファイル中のどこでもコメントを置くことができます。

include キーワードで追加の設定ファイルを含むことができます、例えば:

include "/etc/pf/sub.filter.conf"

マクロ

マクロは、後でコンテキストで拡張されるように定義することができます。マクロ名は、文字から始まらなければならず、文字、数字、下線を含むことができます。マクロ名は、予約語であってはいけません (例えば、 pass, in, out)。マクロは、引用文の中で展開されません。

例えば、

ext_if = "kue0" 
all_ifs = "{" $ext_if lo0 "}" 
pass out on $ext_if from any to any 
pass in  on $ext_if proto tcp from any to any port 25

テーブル

テーブルは、アドレスとネットワークの収集を保持することができる指定された構造体です。 (規則の拡張によって明示的か自動的に作成される) IP アドレスだけにおいて異なる多くの規則より、プロセッサの用法とメモリ消費に関して、テーブルがはるかに効率的であるただ一つの規則を作って、 pf(4) のテーブルに対する検索は、比較的速いです。

テーブルは、フィルタ規則、 scrub 規則または natrdr のような変換規則 (様々な規則タイプに関する詳細に関して以下を参照) の発信元 (始点) または宛先 (終点) として使用することができます。また、テーブルは、 natrdr 規則のリダイレクトアドレスのためと、フィルタ規則の経路制御 (ルーティング) オプションで使用することができますが、 ラウンドロビン プールのためだけです。

テーブルは、次の pfctl(8) メカニズムのいずれでも定義することができます。マクロと同様に、予約語は、テーブル名として使用することはできません。

manually
永続的なテーブルは、ルールセット (ruleset) がロードされる前か後に、 pfctl(8)add または replace オプションで、手動で作成することができます。
pf.conf
テーブル定義は、直接このファイルに置くことができ、他の規則がロードされるのと同時に不可分にロードすることができます。 pf.conf 中のテーブル定義は、 table 文を使用して、永続的でないテーブルを定義するために特に役に立ちます。それを初期化するためにアドレスのリストなしで定義された前もって存在するテーブルの内容は、 pf.conf がロードされるとき、変更されません。空のリストで初期化されたテーブル { } は、ロード時にクリアされます。

テーブルは、次の属性で定義されます:

persist
persist (持続) フラグによって、どんな規則もそれを参照しないときでさえ、カーネルは、強制的にテーブルを保存します。それにを参照する最後の規則がフラッシュされるとき、フラグが設定されないなら、カーネルは、自動的にテーブルを削除します。
const
const (不変) フラグは、それがいったん作成されるとユーザがテーブルの内容を変更することを防ぎます。そのフラグがなければ、 pfctl(8) は、 securelevel(7) = 2 で実行するときでさえ、いつでもテーブルにアドレスを追加するか、または削除するために使用することができます。
counters
counters フラグは、 pfctl(8) で表示することができる、アドレス毎のパケットとバイトカウンタを有効にします。

例えば、

table <private> const { 10/8, 172.16/12, 192.168/16 } 
table <badhosts> persist 
block on fxp0 from { <private>, <badhosts> } to any

RFC 1918 プライベートネットワークブロックを保持するために private と呼ばれるテーブルと初めに空である badhosts と呼ばれるテーブルを作成します。フィルタ規則は、どちらのテーブルにもリストされたアドレスから来るすべてのトラフィックをブロックするるために設定されます。 private テーブルは、内容を変更することができません、そして、アクティブフィルタ規則がそれに参照をしないときでさえ、 badhosts テーブルは、存在します。アドレスは、次を使用することによって、これらのホストからのトラフィックをブロックすることができるように、後で badhosts テーブルに追加できます。

# pfctl -t badhosts -Tadd 204.92.77.111

また、テーブルは、次の構文を使用して、1 つ以上の外部のファイルで指定されたアドレスリストで初期化することができます:

table <spam> persist file "/etc/spammers" file "/etc/openrelays" 
block on fxp0 from <spam> to any

ファイル /etc/spammers/etc/openrelays は、1 行に 1 つの IP アドレスをリストします。 # で始まるどんな行も、コメントとして扱われて、無視されます。さらに、IP アドレスによって指定されることよって、ホストは、また、それらのホスト名によって指定されます。リゾルバがテーブルにホスト名を追加するために呼び出されるとき、 すべての 結果の IPv4 と IPv6 アドレスは、テーブルに置かれます。また、有効なインタフェース名、有効なインタフェースグループまたは 自己 キーワードを指定することによって、テーブルに IP アドレスを入れることができます、その場合、(複数の) インタフェースに割り当てられたすべてのアドレスがテーブルに追加されます。

オプション

pf(4) は、 set コマンドを使用して様々な状況のために調整されます。
set timeout

interval
期限が切れた状態と断片を消去する間隔。
frag
組み立てられていない断片の期限が切れる前の秒数。
src.track
最後の状態の期限が切れた後にソースの追跡エントリを持ち続ける時間の長さ。

パケットがステートフル (stateful) 接続に適合するとき、接続が存続する秒は、接続状態に対応する proto.modifier の内容に更新されます。この状態に適合する各パケットは、TTL (生存時間) をリセットします。これらの値を調整することは、有効なアイドル接続を落とすというリスクでファイアウォールの性能は、向上します。

tcp.first
最初のパケットの後の状態。
tcp.opening
かってパケットを送信した宛先 (終点) ホストの前の状態。
tcp.established
完全に確立された状態。
tcp.closing
最初の FIN が送信された後の状態。
tcp.finwait
FIN が交換されて、接続が閉じられた後の状態。いくつかのホスト (とりわけ Solaris 上の web サーバ) は、かって接続を閉じた後に TCP パケットを送信します。 tcp.finwait (と、ことによると tcp.closing) を増加させることは、そのようなパケットのブロックを防ぐことができます。
tcp.closed
1 つの終点が RST を送信した後の状態。

ICMP と UDP は、TCP と同様のやり方で取り扱われますが、はるかに限られた状態のセットで取り扱われます:

udp.first
最初のパケットの後の状態。
udp.single
発信元 (始点) ホストが 1 つ以上のパケットを送信しますが、宛先 (終点) ホストが決して返送しない場合の状態。
udp.multiple
両方のホストがパケットを送信した場合の状態。
icmp.first
最初のパケットの後の状態。
icmp.error
ICMP パケットに応答して ICMP エラーが復帰した後の状態。

他のプロトコルは、UDP と同様に取り扱われます:

other.first
other.single
other.multiple

タイムアウト値は、ステート (状態) テーブルエントリの数が大きくなるのに適応して減少することができます。

adaptive.start
状態エントリの数がこの値を超えるとき、適応できるスケーリング (拡大縮小) は、始まります。すべてのタイムアウト値は、因数 (adaptive.end - 状態の数) / (adaptive.end - adaptive.start) で直線的にスケーリング (拡大縮小) されます。
adaptive.end
この状態エントリの数に達するとき、効果的に直ちにすべての状態エントリを消去してすべてのタイムアウト値は、0 になります。スケール因数を定義するために、この値は、使用され、実際にそれに到達するべきではありません (下位の状態の制限の設定してください、下記参照)。

適応するタイムアウトは、状態の制限の 60% と等しい adaptive.start 値と状態の制限の 120% と等しい adaptive.end 値で、デフォルトで有効にされます。 adaptive.start と adaptive.end の両方を 0 に設定することによって、それらを無効にすることができます。

適応するタイムアウト値は、グローバルと各規則のための両方を定義することができます。 1 つの規則ベース毎に使用されるとき、値は、規則によって作成された状態の数に関連し、そうでなければ、状態の合計数に関連します。

例えば、

set timeout tcp.first 120 
set timeout tcp.established 86400 
set timeout { adaptive.start 6000, adaptive.end 12000 } 
set limit states 10000

9000 の状態テーブルエントリで、タイムアウト値は、 (tcp.first 60, tcp.established 43200) 50% に調整されます。

set loginterface
与えられたインタフェースまたはインタフェースグループのためのパケットとバイトカウント統計の収集を有効にします。これらの統計は、次を使用して見ることができます。

# pfctl -s info

この例では、 pf(4) は、dc0 と名前が付けられたインタフェースで統計を収集します:

set loginterface dc0

次を使用して loginterface を無効にすることができます:

set loginterface none
set limit
パケットフィルタによって使用されるメモリプールでの強固な制限を設定します。メモリプールの説明に関しては、 zone(9) を参照してください。

例えば、

set limit states 20000

これは、 ( no state を指定しない pass 規則によって生成される) 状態テーブルエントリによって使用されるメモリプール中のエントリの最大数を 20000 に設定します。次を使用して

set limit frags 20000

( scrub 規則によって生成される) 断片再構築のために使用されるメモリプール中のエントリの最大数を 20000 に設定します。次を使用して

set limit src-nodes 2000

sticky-addresssrc.track オプションによって生成される) トレース (追跡) ソース IP アドレスのために使用されるメモリプール中のエントリの最大数を 20000 に設定します。次を使用して、

set limit tables 1000 
set limit table-entries 100000

テーブルによって使用されるメモリプールの制限を設定します。 1 番目は、存在することができるテーブルの数を 1000 に制限します。 2 番目は、テーブルに格納することができるアドレスの全体的な数を 100000 に制限します。

次のように、単一の行で様々な制限を結合することができます:

set limit { states 20000, frags 20000, src-nodes 2000 }
set ruleset-optimization
none
ルールセットオプティマイザを無効にします。
basic
基本的なルールセットの最適化を有効にします。これは、デフォルトの振る舞いです。基本的なルールセットの最適化は、ルールセット評価の性能を向上させるために次の 4 つのことを行います:

  1. 重複する規則を削除します
  2. 別の規則の部分集合である規則を削除します
  3. 有利なときに、複数の規則をテーブルに結合します
  4. 評価性能を改良するために規則に再順序付けします

profile
実際のネットワークトラフィックへの迅速な規則の順序付けを調整するためにフィードバックプロフィールとして現在ロードされたルールセットを使用します。

ルールセットオプティマイザが性能を向上させるためにルールセットを変更することに注意することは重要です。ルールセット変更の副作用は、規則毎のアカウント統計には、以前と異なった意味があるということです。請求目的のようなもののために規則毎のアカウントが重要であるなら、ルールセットオプティマイザを使用するべきではありません、または最適化バリアとして機能するアカウント規則のすべてにラベルフィールドを追加するべきです。

また、 pf.conf の設定を上書きして、コマンドライン引数として pfctl(8) に最適化を設定することができます。

set optimization
次のネットワーク環境の 1 つのために状態タイムアウトを最適化します:

normal
正常なネットワーク環境。ほとんどすべてのネットワークで適切です。
high-latency
高度なレイテンシ環境 (衛星接続などの)。
satellite
高度なレイテンシ のための別名。
aggressive
接続を積極的に終了します。これは、早く無駄な接続を落とすことを犠牲にして、ファイアウォールのメモリ使用量を大幅に減少させることができます。
conservative
非常に保守的な設定。 (ビジーネットワークでことによるとはるかに大きい) より大きいメモリ使用量とわずかに増強されたプロセッサ使用量を犠牲にして正当な接続を落とすことを避けます。

例えば、

set optimization aggressive
set block-policy
block-policy オプションは、パケット block 動作のためのデフォルトの振る舞いを設定します:

drop
パケットは、静かに落とされます。
return
ブロックされた TCP パケットのために TCP RST を返し、ブロックされた UDP パケットのために ICMP UNREACHABLE を返し、そして、静かに他のすべてのパケットを落とします。

例えば、

set block-policy return
set state-policy
state-policy オプションは、状態のためのデフォルトの振る舞いを設定します:

if-bound
状態は、インタフェースにバインドされます。
floating
状態は、どんなインタフェースのパケットにも適合することができます (デフォルト)。

例えば:

set state-policy if-bound
set state-defaults
state-defaults オプションは、明白な keep state なしで規則から作成された状態のための状態オプションを設定します。例えば:

set state-defaults pflow, no-sync
set hostid
32 ビットの hostid は、このファイアウォールのステートテーブルエントリと pfsync(4) フェイルオーバクラスタの他のファイアウォールを識別します。デフォルトで、hostid は、擬似ランダム値に設定されますが、例えば、より容易にステートテーブルエントリのソースを識別するために、手動でそれを設定することは望ましいかもしれません。

set hostid 1

hostid は、10 進数または 16 進数のいずれかで指定されます。

set require-order
デフォルトでは、 pfctl(8) は、次のルールセットで文のタイプの順序で実行します: options, normalization, queueing, translation, filtering。このオプションを no に設定すれば、この実行を無効にします。順序通りでないルールセットへの重要で明白でない意味があるかもしれません。実行順序を無効にする前に、熟考してください。
set fingerprints
与えられたファイル名から知られているオペレーティングシステムの指紋をロードします。デフォルトで、知られているオペレーティングシステムの指紋は、 /etcpf.os(5) から自動的にロードされますが、このオプションで無効にすることができます。このオプションを設定することは、現在アクティブなルールセットによって参照された指紋が、新しいルールセットのロードが終了するまで、一貫性のないところで、短な期間にそのままとなるかもしれません。

例えば:

set fingerprints "/etc/pf.os.devel"
set skip on < ifspec>
パケットがフィルタされるべきでないインタフェースをリストします。まるで pf が無効にされるかのように渡されたインタフェースで内と外に渡されるパケットです、すなわち、pf は、決してそれらを処理しません。これは、パケットフィルタリングが望まれていなくて、予期されない効果があるかもしれないとき、ループバックと他の仮想のインタフェースで役に立つちます。例えば:

set skip on lo0
set debug
次の 1 にデバッグ level (レベル) を設定します:

none
デバッグがメッセージを生成しません。
urgent
重大なエラーの場合だけデバッグメッセージを生成します。
misc
様々なエラーのデバッグメッセージを生成します。
loud
一般的な状態のデバッグメッセージを生成します。

トラフィックの正常化

トラフィック正常化は、受信側でパケットの解釈であいまいさがないような方法でパケットの内容をクリアするために使用されます。正常化機能は、IP フラグメントを重ね合わせながら送信することによって侵入検出システムを混乱させる攻撃を防ぐために IP フラグメント再構築します。パケット正常化は、 scrub 指令で呼び出されます。

scrub には、次のオプションがあります:

no-df
適合している IP パケットから dont-fragment ビットをクリアします。いくつかのオペレーティングシステムは、 dont-fragment ビットの設定でフラグメント化されたパケットを生成することが知られています。これは、NFS で特に当てはまります。 scrub は、 no-df が指定されないなら、そのようなフラグメント化された dont-fragment パケットを落とします。

また、残念ながらいくつかのオペレーティングシステムは、 0 の IP 識別フィールドで、それらの dont-fragment パケットを生成します。 0 の IP ID があるパケットで dont-fragment ビットをクリアすると、アップストリーム (上流) のルータが後でパケットをフラグメント化するなら、有害な結果となるかもしれません。 random-id 修飾子 (下記参照) を使用すると、ユニークな IP 識別子を確実にするために no-df 修飾子と組み合わせることが勧められます。

min-ttl < number>
適合している IP パケットのために最小の TTL を強制します。
max-mss < number>
適合している IP パケットのために最大の MSSL を強制します。
set-tos < string> | < number>
マッチする IP パケットのための TOS を強制します。 TOS は、 lowdelay, throughput, reliability, の 1 つとして、または 16 進数または 10 進数として、与えられます。
random-id
多くのホストによって生成された予測できる値を補正するために IP 識別フィールドをランダムな値に置き換えます。このオプションは、省略可能なフラグメントの再構築の後にフラグメント化されないパケットだけに適用されます。
fragment reassemble
scrub 規則を使用して、フラグメントは、正常化によって再構築することができます。この場合、完成したパケットを形成するまで、フラグメントは、バッファリングされ、完成したパケットだけがフィルタに渡されます。利点は、フィルタ規則が完成したパケットだけに対処しなければならなくて、フラグメントを無視することができるということです。キャッシュフラグメントの欠点は、追加メモリコストです。しかし、完全な再構築方法は、現在 NAT で動作する唯一の方法です。フラグメント化修飾子を供給しないなら、これは、 scrub 規則のデフォルトの振る舞いです。
fragment crop
デフォルトのフラグメント再構築方法が高価であるので、切り取るオプションが提供されています。この場合、 pf(4) は、フラグメントを追跡してて、小さい範囲記述子をキャッシュします。重複したフラグメントは、落とされ、オーバラップは、切り取られます。したがって、データは、最初に発生する分解のあいまいな接続上に一度だけ発生します。 fragment reassemble (フラグメント再構築) 修飾子と異なって、フラグメントは、バッファリングされないで、受信されるとすぐに、それらは、渡されます。 fragment crop (フラグメント切り取り) 再構築メカニズムは、まだ NAT で動作していません。
fragment drop-ovl
このオプションは、すべてのオーバラップまたは重複したフラグメントが落とされて、さらなるすべての対応するフラグメントが落とされることを除いて、 fragment crop 修飾子と同様です。
reassemble tcp
ステートフル (処理状態を把握する) 正常化 TCP 接続。 scrub reassemble tcp (再構築 tcp) 規則は、指定された (in/out) 指令はありません。 reassemble tcp (再構築 tcp) は、次の正常化を実行します:

ttl
接続のどちら側もそれらの IP TTL を減少させることができます。攻撃者は、ファイアウォールに到達して、ファイアウォール状態に影響して、宛先 (終点) ホストに到達する前に期限が切れるように、パケットを送るかもしれません。 reassemble tcp は、接続に見られる最も高い値まですべてのパケットの TTL を引き上げます。
timestamp modulation
最新の TCP スタックは、あらゆる TCP パケットでタイムスタンプを送信し、他の終点のタイムスタンプをそれらにエコーします。多くのオペレーティングシステムは、最初にブートされるとき、0 でタイムスタンプを単に始め、何度か 1 秒それを増加します。ホストの動作可能時間は、タイムスタンプを読み込んで、一定で増加することを推定することができます。また、いくつかの異なったタイムスタンプを観測することは、 NAT デバイスの後ろのホストを数えるために使用することができます。そして、接続へのなりすまし TCP パケットは、有効なタイムスタンプを知っているか、または推測することを必要とします。タイムスタンプは、単に単調に増加して、推測可能な基本時間から導けない必要があります。 reassemble tcp は、 scrub をランダムな数で TCP タイムスタンプを変化させます。
extended PAWS checks
パケットが 32 ビットのシケーンスの空間を折り返すために接続を試みるより長い間遅れるかもしれないので、長くて太いパイプ上の TCP で問題があります。そのようなことが起これは、古いパケットは、新しいパケットと区別できないでしょう、そういうものとして受け付けるでしょう。この解決策は、PAWS と呼ばれます: Protection Against Wrapped Sequence (折り返されたシーケンスに対する保護) 番号。各パケットに関するタイムスタンプが後方に行かないことを確実にすることによって、それから保護します。また、 reassemble tcp は、パケットに関するタイムスタンプが RFC で許されているものより進んでいないことを確実にします。そうすれば、 pf(4) は、盲目的な攻撃者も同様に、タイムスタンプを推測しなければならないので、ホストが適切にランダマイズされたタイムスタンプを使用するとき、 10 から 18 ビットまでに、人為的に TCP シーケンス番号のセキュリティを拡張します。

例えば、

scrub in on $ext_if all fragment reassemble

scrub 規則の前に no オプションを付けることによって、パケットフィルタの drop quick 動作と同じ方法で、一致するパケットは、scrub されずに残ります (下記参照)。このメカニズムは、広範囲の scrub 規則から特定のパケットを排除する必要があるとき、使用されるべきです。

キューイング

現在、ALTQ システムは、GENERIC カーネルもロード可能モジュールとしても利用可能ではありません。キューイングオプションの一つが呼び出された後の時点で使用するために、カスタム構築カーネルを使用しなければなりません。関連するカーネルオプションに関して知るためには、 altq(4) を参照してください。

パケットは、帯域幅制御の目的のためのキューに割り当てることができます。キューを設定するためには、少なくとも 2 つの宣言を必要とし、後のどんなパケットフィルタリング規則は、名前で定義されたキューを参照することができます。 pf.conf の構成要素のフィルタリングの間に、最後に参照された queue の名前は、 pass 規則からのどんなパケットもキューに入れられるところです、一方、 block 規則の場合は、何か結果として起こる ICMP または TCP RST パケットがどこのキューに入れられるべきであるかを指定しますが。 scheduler (スケジューラ) は、どのパケットが遅れるか、落とされるか、または直ちに送出されるか、を決定するために使用されるアルゴリズムを定義します。現在サポートされている 3 つの scheduler (スケジューラ) があります。

cbq
クラスベースのキューイング (Class Based Queueing)。 queue は、ツリーを構築するインタフェースにアタッチします、したがって、各 queue は、さらなる子供の queue を持つことができます。各キューは、 priority (優先順序) と bandwidth (帯域幅) を割り当てることができます。 priority は、主として送出させるためにかかる時間パケットを制御しますが、一方 bandwidth は、主としてスループットに影響を与えます。 cbq は、階層的に構造化されたクラスによってリンク帯域幅のパーティショニングと共有の両方を達成します。各クラスは、それ自体の queue (キュー) があり、 bandwidth (帯域幅) の共有が割り当てられます。子供のクラスは、余分な帯域幅が利用可能である限り、 (下記のオプション borrow 参照) 親のクラスから帯域幅を借りることができます。
priq
優先順序キューイング (Priority Queueing)。 queue は、インタフェースにフラットにアタッチされ、したがって、 queue さらなる子供の queue を持つことができません。各 queue は、0 から 15 までの範囲で、ユニークな priority を割り当てられます。最も高い priority がある queue におけるパケットは、最初に処理されます。
hfsc
階層的なフェアサービスカーブ (Hierarchical Fair Service Curve)。 queue は、ツリーを構築するインタフェースにアタッチします、したがって、各 queue は、さらなる子供の queue を持つことができます。各キューは、 priority (優先順序) と bandwidth (帯域幅) を割り当てることができます。 priority は、主として送出させるためにかかる時間パケットを制御しますが、一方 bandwidth は、主としてスループットに影響を与えます。 hfsc は、リンクの共有と保証されたリアルタイムサービスの両方をサポートします。それは、サービスカーブベースの QoS モデルを使用し、そのユニーク機能は、 delaybandwidth (帯域幅) 割り付けを分離する能力です。

キューが活性化されるべきであるインタフェースは、 altq on 宣言を使用して宣言されます。 altq on には、次のキーワードがあります:

< interface>
キューは、指定されたインタフェースで有効にされます。
< scheduler>
使用するキュースケジューラを指定します。現在サポートされた値は、クラスベースのキューイングのための cbq と、優先順序キューイングのための priq と階層的なフェアサービスカーブスケジューラのための hfsc です。
bandwidth < bw>
インタフェースでのすべてのキューのための最大のビットレートは、 bandwidth キーワードを使用して指定できます。絶対値として、または、インタフェース帯域幅の割合として値を指定することができます。絶対値を使用するとき、接尾辞 b, Kb, MbGb は、それぞれ、1 秒毎のビット、キロビット、メガビットとギガビットを表すのために使用されます。値は、インタフェース帯域幅を超えてはいけません。 bandwidth (帯域幅) が指定されないなら、インタフェース帯域幅は、使用されます (が、いくつかのインタフェースがそれらの帯域幅を知らないか、またはそれらの帯域幅レートを適合できることに注意してください)。
qlimit < limit>
パケットの最大数は、キューに保持されます。デフォルトは、50 です。
tbrsize < size>
トークンバケツ調節装置のバイト単位のサイズを調整します。指定されないなら、サイズを決定するためにインタフェース帯域幅に基づく発見的手法が使用されます。
queue < list>
インタフェースで作成するサブキューのリストを定義します。

次の例では、インタフェース dc0 は、クラスベースのキューイングを使用して 4 つの第 2 レベルのキューおける最大 5Mbps でキューを作るべきです。それらの 4 つのキューは、後の例で示されます。

altq on dc0 cbq bandwidth 5Mb queue { std, http, mail, ssh }

インタフェースが altq 指令を使用してキューのためにいったんアクティブにされると、 queue 指令のシーケンスが定義されます。 queue に関連している名前は、 altq 指令 (例えば、メール) で定義されたキューに適合しなければなりません、または、親の queue 宣言の priq scheduler を除いて、キューに適合しなければなりません。次のキーワードを使用することができます:

on < interface>
キューの操作をオンにするインタフェースを指定します。与えられないなら、すべての適合するインタフェースを動作させます。
bandwidth < bw>
キューによって処理され最大のビットレートを指定します。この値は、親の queue の値を超えてはいけなくて、親のキューの帯域幅の絶対値または割合として指定することができます。指定されなければ、デフォルトは、親のキューの帯域幅の 100% です。 priq スケジューラは、帯域幅指定をサポートしません。
priority < level>
キューの間で、優先順序レベルを設定することができます。 cbqhfsc に関して、範囲は、0 から 7 であり、 priq に関しては、範囲は、0 から 15 です。すべてのデフォルトは、1 です。より高い優先順序がある priq キューは、常に最初に処理されます。より高い優先順序がある cbqhfsc キューは、オーバロードの場合が選ばれます。
qlimit < limit>
パケットの最大数は、キューに保持されます。デフォルトは、50 です。

scheduler は、< scheduler> (< parameters>) で追加パラメータを取得することができます。パラメータは、次の通りです:

default
別のキューによって適合されなかったパケットは、これに割り当てられます。きっちり 1 つのデフォルトキューが必要です。
red
このキューで RED (ランダムな早期発見 (Random Early Detection)) を有効にします。 RED は、平均したキューの長さに比例している確率でパケットを落とします。
rio
このキューで RIO を有効にします。 RIO は、IN/OUT がある RED であり、したがって、RIO が同じ効果を達成するより 2 倍も多くの RED を実行します。 RIO は、現在、GENERIC カーネルでサポートされていません。
ecn
このキューで ECN (明白な混雑状態通知 (Explicit Congestion Notification)) を有効にします。 ECN は、RED を含意します。

cbq scheduler は、次の追加オプションをサポートします:

borrow
キューは、親から帯域幅を取り入れることができます。

hfsc scheduler は、次のいくつかの追加オプションをサポートします:

realtime < sc>
キューに必要とする最小限の帯域幅。
upperlimit < sc>
キューに許された最大の帯域幅。
linkshare < sc>
バックログされたキューの共有された帯域幅。

< sc>は、 service curve (サービスカーブ) の頭文字語です。

サービスカーブ仕様のための形式は、 ( m1, d, m2) です。 m2 は、キューに割り当てられた帯域幅を制御します。 m1d は、省略可能であり、初期の帯域幅割り当てを制御するために使用することができます。最初の d ミリセカンドに対して、キューは、 m1 として与えられた帯域幅、その後 m2 で与えられた値を取得します。

さらに、 cbqhfsc において、子供のキューは、 altq 宣言のように指定することができ、その結果、それらの親の帯域幅の一部を使用してキューのツリーを構築します。

パケットは、 queue キーワードを使用することによってフィルタ規則に基づくキューに割り当てることができます。通常、1 つの queue だけが指定されます。 2 番目のものが指定されるとき、それは、 lowdelayTOS を持っているパケットとデータペイロードがない TCP ACK に代わりに使用されます。

前の例を続けるために、以下の例は、4 つの参照されたキューといくつかの子供のキューを指定します。対話的な ssh(1) セッションは、 scp(1)sftp(1) のようなバルク転送より優先されます。そして、キューは、フィルタリング規則によって参照されます (下記の パケットフィルタリング 参照)。

queue std bandwidth 10% cbq(default) 
queue http bandwidth 60% priority 2 cbq(borrow red) \ 
      { employees, developers } 
queue  developers bandwidth 75% cbq(borrow) 
queue  employees bandwidth 15% 
queue mail bandwidth 10% priority 0 cbq(borrow ecn) 
queue ssh bandwidth 20% cbq(borrow) { ssh_interactive, ssh_bulk } 
queue  ssh_interactive bandwidth 50% priority 7 cbq(borrow) 
queue  ssh_bulk bandwidth 50% priority 0 cbq(borrow) 
 
block return out on dc0 inet all queue std 
pass out on dc0 inet proto tcp from $developerhosts to any port 80 \ 
      queue developers 
pass out on dc0 inet proto tcp from $employeehosts to any port 80 \ 
      queue employees 
pass out on dc0 inet proto tcp from any to any port 22 \ 
      queue(ssh_bulk, ssh_interactive) 
pass out on dc0 inet proto tcp from any to any port 25 \ 
      queue mail

変換

変換規則は、ステートフル接続に関連しているパケットのソース (始点) または宛先 (終点)アドレスのいずれかを変更します。ステートフル接続は、それらが pf.conf のフィルタリングセクションによってブロックされない限り、そのような規則に適合するパケットを追跡するために自動的に作成されます。変換エンジンは、パケット中の指定されたアドレス、と/または、ポートを変更して、必要に応じて IP、TCP と UDP チェックサムを再計算し、そして評価のためにパケットフィルタにそれを渡します。

変換は、フィルタリングの前に生じるので、フィルタエンジンは、任意のアドレスとポートが変換された後で見るようなパケットを見ます。したがって、フィルタ規則は、変換されたアドレスとポート番号に基づいてフィルタリングしなければなりません。変換規則に適合するパケットは、 pass 修飾子が与えられる場合にだけ、自動的に渡されます、そうでなければ、それらは、まだ blockpass 規則に従います。

作成された状態エントリは、 pf(4) がその状態に関連しているトラフィックのためのオリジナルのアドレスの経過を追い、その接続のためのトラフィックを正しく直接返すことを可能にします。

変換の様々なタイプは、次の pf で可能です:

binat
binat 規則は、外部の IP netblock と内部の IP netblock の間の双方向のマッピングを指定します。
nat
nat 規則は、IP アドレスがパケットが与えられたインタフェースを横断するときに変更されることを指定します。この技術で、変換しているホストに関する 1 つ以上の IP アドレスが、 "内部 (inside)"のネットワークでより大きい範囲のマシンのためにネットワークトラフィックをサポートできます。理論的には、任意の IP アドレスが内部で使用することができますが、 RFC 1918 によって定義されたアドレスの範囲の 1 つが使用されることが強く勧められます。これらの netblocks は、次の通りです:

10.0.0.0 - 10.255.255.255 (all of net 10, i.e., 10/8) 
172.16.0.0 - 172.31.255.255 (i.e., 172.16/12) 
192.168.0.0 - 192.168.255.255 (i.e., 192.168/16)
rdr
パケットは、別の宛先 (終点) とことによると異なったポートにリダイレクト (向け直し) されます。 rdr 規則は、単一のポートの代わりにオプションのポート範囲を指定することができます。 rdr ... port 2000:2999 -> ... port 4000 は、2000 から 2999 (包括的) のポートをポート 4000 にリダイレクト (向け直し) します。 rdr ... port 2000:2999 -> ... port 4000:* は、2000 から 4000, 2001 から 4001, ..., 2999 のポートを 4999 にリダイレクト (向け直し) します。

アドレスを変更することに加えて、いくつかの変換規則は、 tcp(4) または udp(4) 接続のためにソース (始点) または宛先 (終点) を変更します。 nat 規則の場合は、暗黙のうちに、 rdr 規則の場合は、明示的に、変更します。ポート番号は、 binat 規則で決して変換されません。

翻訳規則の評価順序は、変換規則とパケットの方向のタイプに依存しています。 binat 規則は、常に最初に評価されます。次に、 rdr 規則は、内向きのパケットで評価されるか、または nat 規則は、外向きのパケットで評価されます。同じタイプの規則は、それらがルールセットに現れる同じ順序で評価されます。最初の適合規則は、どんなアクションが取られるかを決定します。

変換規則へ前に置かれた no オプションは、パケットフィルタでの drop quick 動作とまったく同じように (下記参照)、パケットを変換されないままで残すようにします。どんな規則もパケットに適合しないなら、変更されていなでフィルタエンジンに渡されます。

変換規則は、指定されたインタフェースを通過するパケットだけに適用されます、インタフェースが指定されないなら、変換は、すべてのインタフェースでパケットに適用されます。例えば、内部の web サーバに外部のインタフェースでポート 80 をリダイレクトする (向け直す) ことは外部から発する接続のためだけに動作します。ローカルホストからの外部インタフェースのアドレスとの接続は、そのようなパケットが実際に外部のインタフェースを通過しなしので、リダイレクトされません。リダイレクションは、それらが到着するインタフェースを通してパケットを反映することができないで、異なったインタフェースに接されたホスト、または、ファイアウォール自体にそれらは、リダイレクトする (向け直す) ことができるだけです。

事実上、次のように、

rdr on ne3 inet proto tcp to port smtp -> 127.0.0.1 port spamd

ループバックアドレスに外部の着信接続をリダイレクトすることは、本当のインタフェースにおけるそのような接続の伝統的なブロッキングを回避して、外部のホストが唯一ループバックアドレスへのバインドするデーモンに接続することを可能とします。この効果が望まれていない場合、ローカルの非ループバックアドレスのどれも、代わりに、このアドレスにバインドするか、またはどんなアドレスにもバインドしないデーモンだけに外部の接続を許す、リダイレクションターゲットとして使用されるべきです。

下記の 変換の例 を参照してください。

パケットフィルタリング

pf(4) には、それらのレイヤ (層) 3 ( ip(4)ip6(4) 参照) とレイヤ (層) 4 ( icmp(4), icmp6(4), tcp(4), udp(4) 参照) ヘッダの属性に基づくパケットを block (ブロック) して、 pass (通過) する能力があります。さらに、また、パケットは、帯域幅制御の目的のためのキューに割り当てられるかもしれません。

パケットフィルタによって処理された各パケットに関しては、フィルタ規則は、最初から最後まで連続した順序で評価されます。最後に適合する規則は、どんなアクションが取られるかを決定します。規則がパケットにマッチしないなら、デフォルトの動作は、パケットを通過することです。

次のアクションは、次のフィルタで使用することができます:

block
パケットは、ブロックされます。パケットをブロックするとき block (ブロック) 規則が振る舞うことができる多くの方法があります。デフォルトの振る舞いは、静かにパケットを drop (落とす) ことですが、しかしながら、 block-policy オプションを設定するか、または、次のオプションの 1 つに基づく規則毎に、上書きするか、明白にいずれかをグローバルにすることができます。

drop
パケットは、静かに落とされます。
return-rst
これは、 tcp(4) パケットのみ適用し、接続をクローズする TCP RST を発行します。
return-icmp
return-icmp6
これは、ICMP メッセージを規則に適合するパケットのために返させます。デフォルトで、これは、ICMP UNREACHABLE メッセージですが、しかしながら、コードまたは数としてメッセージを指定することによって、これを無効にすることができます。
return
これは、 tcp(4) パケットのために TCP RST を返えさせ、 UDP と他のパケットのためには、ICMP UNREACHABLE です。

pf(4)if_bridge(4) で操作されるなら、ICMP パケットを返すオプションは、現在効果がありません。この機能をサポートするコードは、まだ実装されていません。

デフォルトですべてをブロックし、明白な規則にマッチするパケットだけを通過する最も簡単なメカニズムは、次の最初のフィルタ規則を指定することです:

block all
pass
パケットは、通過されます。状態は、 no state がオプションが指定されないなら、作成されます。

デフォルトで、 pf(4) は、パケットをステートフルに (処理状態を把握する) フィルタします。最初のパケットは、 pass (通過) 規則にマッチし、状態エントリが作成されます。その後のパケットに関して、フィルタは、パケットが任意の状態にマッチするどうかチェックします。そうするなら、パケットは、任意の規則の評価なしでも通過されます。接続がクローズされるか、タイムアウトの後に、状態エントリは、自動的に削除されます。

これには、いくつかの利点があります。 TCP 接続のために、パケットを状態と比較することは、 scrub reassemble tcp 規則が接続に適用されるなら、TCP タイムスタンプと同様にシーケンス番号をチェックすることを必要とします。これらの値が期待された値の狭いウィンドウの外であるなら、パケットは、落とされます。これは、攻撃者がにせのソースアドレス/ポートでパケットを送信するが、接続のシーケンス番号を知らないときのような、なりすまし攻撃を防ぎます。同様に、 pf(4) は、どのように ICMP 応答を状態にマッチするかを知っています。例えば、

pass out inet proto icmp all icmp-type echoreq

によって、 ( ping(8) によって作成されたもののように) エコー要求は、ステートフルに出力でき、着信エコー応答が正しく状態にマッチします。

また、通常、状態の検索は、規則を評価するより速くなります。 50 の規則があるなら、それらのすべては、O(n) で連続して評価されます。 50000 の状態があっても、状態が O(log2n) で検索できる二分検索木に格納されるので、16 の比較だけが状態とマッチするために必要です。

さらに、ICMP エラーメッセージの正しい取り扱いは、多くのプロトコル、特に TCP でクリティカル (重要) です。 pf(4) は、ICMP エラーメッセージを正しい接続に合わせて、接続パラメータに対してそれらをチェックして、適切であるなら、それらを渡します。例えば、ステートフル TCP 接続を参照する ICMP ソース quench (クエンチ, 焼き入れ) メッセージが到着すると、それは、状態にマッチされて、通過されます。

最終的に、状態の追跡は、返って来るパケットでアドレスを追跡して、ポートを変換し、変換を逆にするために、 nat, binatrdr 規則を必要とします。

また、 pf(4) は、本来、事実上ステートレス (状態なし) である他のプロトコルのための状態を作成します。 UDP パケットは、ホストアドレスとポートだけを使用して状態とマッチされ、他のプロトコルは、ホストアドレスだけを使用して状態とマッチされます。

個々のパケットのステートレス (状態なし) フィルタリングが要求されているなら、これが最後の規則のマッチであるなら、状態が作成されないことを指定するために no state キーワードを使用することができます。また、 pf(4) が状態の追跡をどのように扱うかに影響するように多くのパラメータを設定することができます。さらに詳しい詳細については、下記の ステートフルトラッキングオプション を参照してください。

パラメータ

規則パラメータは、規則が適用されるパケットを指定します。パケットは、常に、1 つのインタフェースを通して入って来るか、または外に出ます。ほとんどのパラメータは、オプションです。パラメータが指定されるなら、規則は、適合する属性があるパケットのみに適用されます。特定のパラメータは、リストとして表すことができます、その場合、 pfctl(8) は、すべての必要な規則の組み合わせを生成します。
in または out
この規則は、着信または発信パケットに適用されます。 inout も指定されないなら、規則は、両方の方向にパケットに適合します。
log
指定されたアクションに加えて、ログメッセージが生成されます。 no state オプションが指定されないなら、状態を確立するパケットだけがログ記録されます。ログ記録されたパケットは、デフォルトで pflog0 である、 pflog(4) インタフェースに送信されます。このインタフェースは、 pcap(3) バイナリ形式でファイル /var/log/pflog にログ記録されたパケットをダンプする、 pflogd(8) ログ記録デーモンによって、モニタされます。
log (all)
接続のためにすべてのパケットのログ記録を強制するために使用されます。 no state が明白に指定されるとき、これは、必要ではありません。 log のように、パケットは、 pflog(4) にログ記録されます。
log (user)
パケットが、(どのソケットがローカルであるかにより) どこが発信元であるか、または、どこが宛先であるかで、オープンされたソケットがある、ソケットとプロセスの PID を所有しているユーザの UNIX ユーザ ID をログ記録します。これは、ログ記録された通常の情報に追加されます。

log (all, user) を通してログ記録された最初のパケットのみ、ステートフルマッチング (stateful matching) を使用するとき、ログ記録されたユーザ資格証明があります。

log (to < interface>)
ログを pflog0 の代わりに指定された pflog(4) インタフェースに送信します。
quick
パケットが quick オプション設定がある規則に適合するなら、この規則は、最後に適合する規則であると見なされ、その後の規則の評価は、スキップされます。
on < interface>
この規則は、この特定のインタフェースまたはインタフェースグループを通して着信するか発信するパケットだけに適用されます。インタフェースグループの詳しい情報に関しては、 ifconfig(8)group キーワードを参照してください。
< af>
この規則は、このアドレスファミリのパケットだけに適用されます。サポートされた値は、 inetinet6 です。
proto < protocol>
この規則は、このプロトコルのパケットだけに適用されます。一般的なプロトコルは、 icmp(4), icmp6(4), tcp(4)udp(4) です。 pfctl(8) によって使用された数のマッピングへのすべてのプロトコル名のリストに関しては、ファイル /etc/protocols を参照してください。
from < source> port < source> os < source> to < dest> port < dest>
この規則は、指定されたソース(始点)、宛先 (終点) アドレス、とポートでパケットだけに適用されます。

アドレスは、シンボリックなホスト名、インタフェース名またはインタフェースグループ名として、または、次のキーワードのいずれかとして、 CIDR 記法 (netblocks に適合する) で指定することができます:

any
任意のアドレス。
no-route
現在経路制御可能でない任意のアドレス。
urpf-failed
unicast reverse path forwarding (ユニキャスト逆パス転送) (URPF) チェックに失敗する任意のソースアドレス、すなわち、パケットのソースアドレスへ戻るルートを保持する以外のインタフェースで着信するパケットです。
< table>
与えられたテーブルに適合する任意のアドレス。

アドレスの範囲は、‘-’演算子を使用することによって指定されます。例えば: “10.1.1.10 - 10.1.1.12”は、10.1.1.10 から 10.1.1.12 までのすべてのアドレスを意味し、したがって、アドレス 10.1.1.10、10.1.1.11 と 10.1.1.12 です。

インタフェース名とインタフェースグループ名は、次の修飾子を追加することができます:

:network
インタフェースにアタッチされた (複数の) ネットワークに変換します。
:broadcast
インタフェースの (複数の) ブロードキャスト (同報通信) アドレスに変換します。
:peer
(複数の) ポイントツーポイントのインタフェースのピア (相手) アドレスに変換します。
:0
インタフェース別名を含めません。

また、ホスト名は、それぞれの v4 と v6 アドレスを見つけるために名前解決を制限するために :0 オプションを追加するかもしれません。

ホスト名解決とアドレス変換へのインタフェースは、ルールセットロード時に行われます。インタフェース (または、ホスト名) のアドレスが変化するとき (例えば DHCP か PPP の下で)、ルールセットは、変更をカーネルに反映されるために再びロードされなければなりません。括弧中のインタフェース名 (と、オプションの修飾子) を囲むことは、この振る舞いを変更します。インタフェース名が括弧で囲まれるとき、規則は、インタフェースがアドレスを変更するときはいつも自動的に更新されます。ルールセットは、再びロードされる必要はありません。これは、 nat で特に役に立ちます。

ポートは、数か名前のいずれかによって指定することができます。例えば、ポート 80 は、 www として指定することができます。 pfctl(8) によって使用された数のマッピングへのすべてのポート名のリストに関しては、ファイル /etc/services を参照してください。

ポートのポートと範囲は、これらのオペレータを使用することによって指定されます:

= (等しい) 
!= (不等) 
< (未満) 
≤ (以下) 
> (越える) 
≥ (以上) 
: (境界を含む範囲) 
>< (境界を含まない範囲) 
<> (範囲を除く)

‘><’, ‘<>’と‘:’は、(2 つの引数を取る) 2 項演算子です。例えば:

port 2000:2004
‘すべてのポート≥ 2000 と≤ 2004’したがって、ポート 2000、2001、2002、2003、と 2004 を意味します。
port 2000 >< 2004
‘すべてのポート > 2000 と < 2004’したがって、ポート 2001、2002、と 2003 を意味します。
port 2000 <> 2004
‘すべてのポート < 2000 または > 2004’したがって、ポート 1-1999 と 2005-65535 を意味します。

ソースホストのオペレーティングシステムは、 OS 修飾子がある TCP 規則の場合に指定することができます。詳しい情報については、 オペレーティングシステム指紋法 セクションを参照してください。

ホスト、ポート、と OS 仕様は、次の例のようにオプションです:

pass in all 
pass in from any to any 
pass in proto tcp from any port ≤ 1024 to any 
pass in proto tcp from any to any port 25 
pass in proto tcp from 10.0.0.0/8 port > 1024 \ 
      to ! 10.1.2.3 port != ssh 
pass in proto tcp from any os "OpenBSD"
all
これは、"from any to any"と同等です。
group < group>
user と同様に、この規則は、指定されたグループによって所有されているソケットのパケットのみに適用します。
user < user>
この規則は、指定されたユーザによって所有されているソケットのパケットのみに適用します。ファイアウォールから開始された発信接続において、これは、接続をオープンしたユーザです。ファイアウォール自体への着信接続のために、これは、宛先 (終点) ポートで listen する (接続を受け付ける) ユーザです。転送された接続において、ファイアウォールが接続された終点でないところで、ユーザとグループは、 unknown (未知) です。

1 つの接続の発信と着信のすべてのパケットは、同じユーザとグループに関連付けられます。 TCP と UDP パケットしかユーザに関連付けることはできません。他のプロトコルにおいて、これらのパラメータは、無視されます。

ユーザとグループは、ソケットが setuid/setgid プロセスによって作成されるときに備えて、有効な (実際とは対照的に) ID を参照します。ユーザとグループ ID は、ソケットが作成されるとき、保存されます。プロセスがルート (例えば、特権があるポートにバインドすることによって) として listen (接続を受け付け) ソケットを作成し、その次に別のユーザ ID (特権を下げる) を変更するとき、資格証明は、ルートのままで残ります。

ユーザとグループ ID は、数か名前のどちらかで指定することができます。構文は、ポートのものと同様です。 unknown (未知の) 値は、転送された接続のパケットに適合します。 unknown は、オペレータ =!= でのみ使用することができます。 user ≥ unknown のような他の構文は、無効です。 unknown (未知の) ユーザとグループ ID で転送されたパケットは、オペレータ = または != と反対の明白な比較である規則のみに適合します。例えば、 user ≥ 0 は、転送されたパケットに適合しません。次の例は、選択されたユーザだけが発信接続をオープンできます:

block out proto { tcp, udp } all 
pass  out proto { tcp, udp } all user { < 1000, dhartmei }
flags < a> /< b> | /< b> | any
この規則は、flags < a>が設定され< b>が設定されない、TCP パケットだけに適用されます。< b>で指定されなかった flags は、無視されます。ステートフル接続において、デフォルトは、 flags S/SA です。フラグが、すべてチェックされるべきでないことを示すためには、 flags any を指定します。 flags は、次の通りです: (F)IN, (S)YN, (R)ST, (P)USH, (A)CK, (U)RG, (E)CE と C(W)R です。
flags S/S
フラグ SYN が設定されます。他のフラグは、無視されます。
flags S/SA
これは、ステートフル接続のためのデフォルトの設定です。 SYN と ACK 以外、正確に SYN が設定されます。 SYN, SYN+PSH と SYN+RST は、適合しますが、SYN+ACK, ACK と ACK+RST は、適合しません。これは、前の例より制限されています。
flags /SFRA
最初の設定が指定されないなら、それは、なにもをデフォルトとしません。すべての SYN, FIN, RST と ACK は、設定してはいけません。

( no state が指定されないなら) flags S/SA がデフォルトで適用されるので、TCP ハンドシェイクの初期の SYN パケットだけが TCP 接続のために状態を作成します。それを制限することはでき、 flags any を指定することによって中間的な (non-SYN) パケットからの状態の作成することは可能です。例えば、ステートテーブルをフラッシュするなら、これによって、 pf(4) は、既存の接続に同期します。しかしながら、そのような中間的パケットから作成された状態は、TCP ウィンドウのスケールファクタのような詳細な接続を失うかもしれません。それらが nat, binat または rdr 規則、 modulate または synproxy state オプション、または reassemble tcp で無効にされるかによって影響されるようなパケットフローを変更する状態も、中間的パケットから復旧可能ではありません。そのような接続は、ストール (行き詰まり) しタイムアウトします。

icmp-type < type> code < code>
icmp6-type < type> code < code>
この規則は、指定されたタイプとコードがある ICMP か ICMPv6 パケットだけに適用されます。 ICMP タイプとコードのためのテキスト名は、 icmp(4)icmp6(4) にリストされています。このパラメータは、プロトコル ICMP か ICMP6 をカバーする規則だけに有効です。プロトコルと ICMP タイプ指示子 ( icmp-type または icmp6-type) は、適合しなければなりません。
tos < string> | < number>
この規則は、指定された TOS ビットの設定でパケットに適用されます。 TOS は、 lowdelay, throughput, reliability, の 1 つ、または、16 進数または 10 進数のいずれかとして与えられます。

例えば、次の規則は、同じです:

pass all tos lowdelay 
pass all tos 0x10 
pass all tos 16
allow-opts
デフォルトで、IP オプションがある IPv4 パケットまたはルーティング拡張ヘッダがある IPv6 パケットは、ブロックされます。 allow-optspass 規則のために指定されるとき、その規則 (最後のマッチング) に基づいてフィルタに渡すパケットは、たとえ、それらが、IP オプションか、またはルーティング (経路制御) 拡張ヘッダを含んでも、そうします。状態に適合するパケットに関しては、初めに状態を作成した規則が使用されます。パケットがどんな規則にも適合しないとき使用される暗黙の pass 規則は、IP オプションを許可しません。
label < string>
規則を識別するために使用することができる、ラベル (名) を規則に追加します。例えば、 pfctl -s labels は、ラベルを持っている規則のために規則ごとの統計を表示します。

次のマクロは、ラベルで使用することができます:

$if
インタフェース。
$srcaddr
ソース (始点) IP アドレス。
$dstaddr
宛先 (終点) IP アドレス。
$srcport
ソース (始点) ポート指定。
$dstport
宛先 (終点) ポート指定。
$proto
プロトコル名。
$nr
規則番号。

例えば:

ips = "{ 1.2.3.4, 1.2.3.5 }" 
pass in proto tcp from any to $ips \ 
      port > 1023 label "$dstaddr:$dstport"

は、次のように拡張されます。

pass in inet proto tcp from any to 1.2.3.4 \ 
      port > 1023 label "1.2.3.4:>1023" 
pass in inet proto tcp from any to 1.2.3.5 \ 
      port > 1023 label "1.2.3.5:>1023"

==================================--- label 指示のためのマクロ展開は、設定ファイルの解析時のみに起こり、実行時ではありません。

queue < queue> | (< queue>, < queue>)
この規則に適合するパケットは、指定されたキューに割り当てられます。 2 つのキューが与えられるなら、データのペイロードなしで lowdelayTOS と TCP ACK を持っているパケットは、2 番目のものに割り当てられます。訳注: ペイロードは、転送されるパケットのヘッダ部を除いたデータの本体。セットアップの詳細については、 キューイング 参照してください。

例えば:

pass in proto tcp to port 25 queue mail 
pass in proto tcp to port 22 queue(ssh_bulk, ssh_prio)
tag < string>
この規則に適合するパケットは、指定された文字列でタグ付けされます。タグは、後でこれらのパケットを特定するために使用することができる内部のマーカとして作用します。例えば、インタフェースの間の信任を提供するためと、パケットが変換規則で処理されたかどうか決定するためにこれを使用することができます。規則が最後の適合する規則でなくても、パケットがタグ付けをされることを意味して、タグは、“sticky” (ねばねば) です。さらに、適合している規則は、新しいものでタグを置き換えることができますが、以前に適用されたタグは、取り除かれません。パケットは、一度に 1 個のタグしか割り当てられません。パケットは、フィルタ規則に加えて nat, rdr または binat 規則の間にタグ付けすることができます。タグは、ラベルと同じマクロを取ります (上記参照)。
tagged < string>
パケットが規則にマッチするために与えられたタグで既にタグ付けをしなければならないと指定するためにフィルタ、変換または scrub 規則で使用されます。また、反対のタグの適合は、 tagged (タグ付け) されたキーワードの前に ! オペレータを指定することによって行うことができます。
rtable < number>
ルーティング (経路制御) 検索のために代替ルーティングテーブルを選択するために使用します。ルート (経路) 検索が起こるまえだけ有効となります、すなわち、内向きフィルタリングのとき。
divert-to < host> port < port>
パケットを hostport をバインドするローカルソケットにリダイレクトするために使用します。パケットは、変更されないので、ソケット上の getsockname(2) は、パケットのオリジナルの宛先アドレスを返します。
divert-reply
マシンにローカルでないアドレスにバインドされるソケットのための応答を受信するために使用します。どのようにこれらのソケットをバインドするかの情報については、 setsockopt(2) を参照してください。
probability < number>
確率属性は、領域は、含まず、0 と 1 の間で設定された値で規則にアタッチすることができます。その場合には、規則は、与えられた確率値だけを使用することで尊敬されます。例えば、次の規則は、20% の着信 ICMP パケットを落します:

block in proto icmp probability 20%

(ルーティング) 経路制御

パケットがルート (経路) オプション設定で規則に適合するなら、パケットフィルタは、ルートオプションのタイプに従ってパケットを (ルーティング) 経路制御します。そのような規則が状態を作成するとき、ルートオプションは、また、同じ接続に適合するすべてのパケットに適用されます。
fastroute
fastroute オプションは、パケットのために次の中継点 (ホップ) を見つけるために正常な経路 (ルート) の検索を行います。
route-to
route-to オプションは、パケットを次の中継点のための省略可能なアドレスで指定されたインタフェースへ経路制御します。 route-to 規則が状態を作成するとき、フィルタ規則指定と同じ方向に通過するパケットだけが、この方法で経路制御されます。逆方向 (応答) に通過するパケットは、影響を受けないで、正常に経路制御されます。
reply-to
reply-to オプションは、 route-to オプションと同様ですが、指定されたインタフェースへの逆方向 (応答) に通過するパケットを経路制御します。逆方向は、状態エントリのコンテキストでのみ定義され、 reply-to は、状態を作成する規則でのみ、役に立ちます。 (左右対称の経路制御施行) を通して到着した着信接続のインタフェースを通して接続のすべての発信パケットを経路制御するために複数の外部の接続と共にシステムで使用することができます。
dup-to
dup-to オプションは、パケットの複製を作成して、それを route-to のように経路制御します。オリジナルのパケットは、普通に経路制御されるように経路制御されます。

プールオプション

(1 つ以上の IP アドレス) IPv4 のための 32 または IPv6 のための 128 より小さなサブネットマスクがある単一のリダイレクションアドレスがある ( route-to, reply-todup-to 規則オプションと同様に) natrdr 規則のために、このアドレスを割り当てるためのさまざまな異なった方法は、次のように使用することができます:
bitmask
bitmask オプションは、リダイレクションアドレスのネットワーク部分を ( nat があるソース (始点)、 rdr がある宛先 (終点)) で変更されるためのアドレスに適用します。
random
random オプションは、アドレスの定義されたブロック中でランダムにアドレスを選択します。
source-hash
source-hash オプションは、リダイレクションアドレスが与えられたソース (始点) と常に同じであることを確実にするために、リダイレクションアドレスを決定するのにソース (始点) アドレスのハッシュを使用します。オプションキーは、16 進数か文字列として、このキーワードの後に指定することができます。デフォルトで、 pfctl(8) は、ルールセットが再ロードされるときはいつも、source-hash のためにキーをランダムに生成します。
round-robin
round-robin オプションは、(複数の) リダイレクションアドレスを通してループします。

1 つ以上のリダイレクションアドレスが指定されるとき、 round-robin は、唯一の許可されたプールタイプです。

static-port
nat 規則で、 static-port オプションは、 pf(4) が TCP と UDP パケットでソース (始点) ポートを変更するのを防ぎます。

さらに、 sticky-address オプションは、同じソースからの複数の接続が同じリダイレクションアドレスにマップされることを確実にすることを助けるために指定することができます。このオプションは、 randomround-robin プールオプションで使用することができます。それらを参照する状態がもはやないなら、すぐに、デフォルトで、これらの関連性が破壊されることに注意してください。状態の存続期間を越えて最後にマッピングを作成するためには、 set timeout src.track でグローバルなオプションを増加させます。ソース追跡を制御するより多くの方法については、 ステートフル (処理状態の把握) トラッキング (追跡) オプション を参照してください。

状態調節

TCP に由来するセキュリティの多くは、初期のシーケンス番号 (ISN) がどれくらいよく選ばれているかに起因します。いくつかのよく知られているスタックの実装は、 非常に 貧しい ISN を選んで、その結果、通常、ISN 予測エクスプロイト (セキュリティ上の弱点を突く手段) を受け入れる余地があります。 TCP 接続への modulate state を適用することによって、 pf(4) は、それぞれの接続終点のための高品質のランダムシーケンス番号を作成します。

modulate state 指示は、暗黙のうちに規則で状態を保持して、TCP 接続のみに適用できます。

例えば:

block all 
pass out proto tcp from any to any modulate state 
pass in  proto tcp from any to any port 25 flags S/SFRA modulate state

変調された接続は、状態テーブルが失われるとき (ファイアウォールリブート、状態テーブルのフラッシュ、など) 復旧しないことに注意してください。 pf(4) は、状態テーブルが接続の調節子をフラッシュした後に再び接続を推論することができません。状態が失われるとき、接続は、個別の終点の接続タイムアウトまでぶら下げたままになるかもしれません。調節子の損失の後に再同期しようとしている間に ACK 攻撃を開始する終点のための速いローカルネットワークで可能です。デフォルト flags 設定 (または、より厳密な同等物) は、ACK 攻撃を防ぐために modulate state 規則で使用されるべきです。

代替のメソッドは、状態テーブルの損失を防いで、ファイアウォールフェイルオーバを可能とするために利用可能であることに注意してください。さらなる詳細については、 carp(4)pfsync(4) を参照してください。

SYN プロキシ

デフォルトで、 pf(4) は、終点の間で tcp(4) ハンドシェイクの不可欠な要素であるパケットを通過させます。 synproxy state オプションは、 pf(4) 自体がアクティブな終点でハンドシェイクを終了させるために、受動的な終点でハンドシェイクを実行して、次に、終点の間でパケットを転送するために、使用することができます。

アクティブな終点がハンドシェイクを終了する前には、パケットを受動的な終点に送信しません、したがって、なりすましたソース (始点) アドレスでのいわゆる SYN 送り付け攻撃は、送信者がハンドシェイクを終了することができないとき、受動的な終点に到達しません。

プロキシは、両方の終点に透明であり、それらは、それぞれ終点からの単一の接続/終点への単一の接続に見えます。 pf(4) は、両方のハンドシェイクのためのランダム初期シーケンス番号を選びます。ハンドシェイクがいったん終了されると、シーケンス番号調節子 (前のセクションを参照) は、接続のさらなるパケットを変換するために使用されます。 synproxy state は、 modulate state を含んでいます。

synproxy がある規則は、 pf(4)bridge(4) で動作するなら、動作しません。

例えば:

pass in proto tcp from any to any port www synproxy state

ステートフル (処理状態の把握) トラッキング (追跡) オプション

ステートフル追跡に関連する多くのオプションは、規則毎をベースにして適用することができます。 keep state, modulate statesynproxy state は、それらのオプションをサポートし、 keep state は、オプションを規則に適用するために明白に指定しなければなりません。

max < number>
同時に規則を作成する状態の数の制限。この制限に到達するとき、状態を作成するさらなるパケットは、存在する状態のタイムアウトまで、この規則にマッチしません。
no-sync
pfsync(4) インタフェースで現れるのを、この規則によって作成された状態への状態の変更を防ぎます。
< timeout>< seconds>
この規則によって作成された状態のために使用されるタイムアウトを変更します。すべての有効なタイムアウト名のリストに関しては、上記の オプション を参照してください。
sloppy
挿入と ICMP 分解攻撃 (teardown attack) をより簡単にする、シーケンス番号を全くチェックしないずさんな (sloppy) TCP 接続トラッカ (tracker) を使用します。これは、誰も接続のすべてのパケットを見ない状況で、例えば、非対称のルーティング状況で、使用されることを目的としています。 modulate または synproxy state で使用することはできません。
pflow
この規則によって作成された状態は、 pflow(4) インタフェースでエクスポートされます。

複数のオプションは、コンマによって分離して指定することができます:

pass in proto tcp from any to any \ 
      port www keep state \ 
      (max 100, source-track rule, max-src-nodes 75, \ 
      max-src-states 3, tcp.established 60, tcp.closing 5)

source-track キーワードが指定されるとき、ソース IP 毎の状態の数は、追跡されます。次の制限を設定することができます:

source-track rule
この規則で作成された状態の最大数は、規則の max-src-nodesmax-src-states オプションによって制限されます。この特定の規則によって作成された状態のエントリだけが規則の制限方向にカウントされます。
source-track global
このオプションを使用するすべての規則によって作成された状態の数は、制限されます。各規則は、異なった max-src-nodesmax-src-states オプションを指定することができますが、任意の参加規則によって作成された状態のエントリは、それぞれの個別の規則の制限方向にカウントされます。

次の制限は、設定することができます:

max-src-nodes < number>
同時に状態テーブルエントリを持つことができる発信元アドレスの最大数の制限。
max-src-states < number>
単一の発信元アドレスがこの規則で作成することができる同時に存在する状態エントリの最大数の制限。

また、ステートフル TCP 接続において、(TCP 3-way ハンドシェイクが終了した接続) を確立した接続での制限は、発信元 IP ごとに強制することができます。

max-src-conn < number>
単一のホストで行うことができる 3-way ハンドシェイクを終了した同時に存在する TCP 接続の最大数の制限。
max-src-conn-rate < number> / < seconds>
時間間隔での、新しい接続の速度の制限。接続速度は、移動平均として計算された近似値です。

3-way ハンドシェイクは、発信元アドレスがなりすましされていないことを確実にするので、これらの制限に基づいて、より攻撃的な行動を取ることができます。 overload < table>状態のオプションで、確立された接続における制限のいずれかにヒットする発信元 IP アドレスは、名前付けされたテーブルに追加されます。このテーブルは、それを tarpit プロセスにリダイレクトするか、またはその帯域幅を制限する、問題となるホストからさらなる活動をブロックするためのルールセットで使用することができます。

オプションの flush キーワードは、これらの制限を超えるホストから発するマッチング規則によって作成されたすべて状態を kill します。 flush コマンドへの global 修飾子は、どの規則が状態を作成したかにかかわらず、問題となっているホストから発するすべての状態を kill します。

例えば、次の規則は、10 秒で 100 個以上の接続を行うホストに対して WEB サーバを保護します。この速度より早い接続のすべてのホストは、そのアドレスを<bad_hosts>テーブルに追加し、フラッシュされたホストから発するすべての状態を持ちます。このホストから到着するすべての新しいパケットは、ブロック規則によって無条件に落とされます。

block quick from <bad_hosts> 
pass in on $ext_if proto tcp to $webserver port www keep state \ 
 (max-src-conn-rate 100/10, overload <bad_hosts> flush global)

オペレーティングシステム指紋法

受動的な OS 指紋法は、TCP 接続の初期の SYN パケットのニュアンス (微妙な差異) を検査して、ホストのオペレーティングシステムを推測するメカニズムです。残念ながら、これらのニュアンスは、攻撃者によって容易に偽造されるので、指紋は、セキュリティを決定にする際に役に立ちません。しかし、通常、指紋は、ポリシ決定を行うために十分正確です。

指紋は、オペレーティングシステムのクラス、バージョン、またはサブタイプ/パッチレベルによって指定されます。オペレーティングシステムのクラスは、通常ベンダかジャンルであり、 pf(4) ファイアウォール自体への OpenBSD となるでしょう。主な FTP サイトで最も古い利用可能な OpenBSD リリースのバージョンが 2.6 となり、指紋は、次のように書かれるでしょう。

"OpenBSD 2.6"

オペレーティングシステムのサブタイプは、そのパッチが TCP スタックの振る舞いでの変更となるなら、通常、パッチレベルについて説明するために使用されます。 OpenBSD の場合には、唯一のサブタイプは、 no-df 無効オプションによって正常化にされた指紋のためであり、次のように指定されるでしょう。

"OpenBSD 3.3 no-df"

ほとんどの一般的なオペレーティングシステムのための指紋は、 pf.os(5) によって提供されます。いったん pf(4) が実行さると、知られているオペレーティングシステム指紋のすべてのリストは、次のように実行することによってリストされます:

# pfctl -so

フィルタ規則は、指紋が存在していると仮定する任意のレベルのオペレーティングシステム仕様においてポリシを実行することができます。ポリシは、承認されたオペレーティングシステムへのトラフィックか、または最も遅いサービスパックを攻撃しないホストからの接続を禁止するトラフィックさえ、制限するかもしれません。

また、 unknown クラスは、オペレーティングシステム指紋が知られていないパケットに適合する指紋として使用することができます。

例えば:

pass  out proto tcp from any os OpenBSD 
block out proto tcp from any os Doors 
block out proto tcp from any os "Doors PT" 
block out proto tcp from any os "Doors PT SP3" 
block out from any os "unknown" 
pass on lo0 proto tcp from any os "OpenBSD 3.3 lo0"

オペレーティングシステム指紋は、TCP SYN パケットだけに制限されます。これは、他のプロトコルで動作しないで、現在確立した接続に適合しないことを意味します。

警告: オペレーティングシステム指紋は、時々間違っています。 3 つの問題があります: 攻撃者は、彼が選ぶどんなオペレーティングシステムとしても現れるようにパケットを巧妙に作ることができます。オペレーティングシステムパッチは、スタックの振る舞いを変更するかもしれません、そして、どんな指紋もデータベースを更新するまでそれに適合しないでしょう。そして、複数のオペレーティングシステムには、同じ指紋があるかもしれません。

なりすましトラフィックのブロック

"なりすまし"は、通常、悪意がある目的のための IP アドレスを偽造することです。 antispoof 指示は、その他のインタフェースを通してシステムに入ってくる、直接接続された (複数の) ネットワークから指定された (複数の) インタフェースまでソース IP ですべてのトラフィックをブロックする 1 組のフィルタ規則を拡張します。

例えば、次の行

antispoof for lo0

は、次のように拡張します。

block drop in on ! lo0 inet from 127.0.0.1/8 to any 
block drop in on ! lo0 inet6 from ::1 to any

非ループバックインタフェースには、インタフェースの IP と同じソース IP アドレスで着信パケットをブロックするための追加規則があります。例えば、インタフェース wi0 が 10.0.0.1 の IP アドレスで 255.255.255.0 のネットマスク (netmask) があると仮定すれば、次の行

antispoof for wi0 inet

は、次のように拡張します。

block drop in on ! wi0 inet from 10.0.0.0/24 to any 
block drop in inet from 10.0.0.1 to any

警告: antispoof 指示で作成された規則は、ローカルのアドレスへのループバックインタフェースに送信されたパケットを妨ぎます。明らかにこれらを通過するべきです。

フラグメント操作

IP データグラム (パケット) のサイズは、ネットワークの最大の転送単位 (MTU) よりかなり大きくなる場合があります。そのような大きいパケットを送信するために、必要であるか、またはより効率的である場合では、大きなパケットは、接続でそれぞれに適合する多くのより小さいパケットに断片化されます。残念ながら、ファイアウォールを行うデバイスに関して、最初の論理的な断片だけが pf(4) が TCP ポートのようなものでフィルタにかけるか、または NAT を実行できるようにする、サブプロトコルのために必要なヘッダ情報を含みます。

上記の トラフィックの正常化 で説明されている scrub 規則の使用のほかに、パケットフィルタでフラグメントを操作するための 3 つのオプションがあります。

1 つの代替手段は、フィルタ規則で個々の断片をフィルタにかけることです。 scrub 規則が断片に適用されないなら、それは、フィルタを通過します。適合している IP ヘッダパラメータがあるフィルタ規則は、完全なパケットがフィルタされるのと同じ方法で、断片が通過されるがブロックされるかどうかを決定します。再構築なしに、断片は、サブプロトコルヘッダフィールドが利用可能でないので (TCP/UDP ポート番号、ICMP コード/タイプ)、 IP ヘッダフィールド (ソース/宛先アドレス、プロトコル) に基づいてのみフィルタにかけることができます。 fragment オプションは、完全なパケットではなく、断片だけに適用するフィルタ規則を制限するために使用することができます。 fragment オプションのないフィルタ規則は、IP ヘッダフィールドを指定するだけであるなら、それでも断片に適用されています。例えば、規則

pass in proto tcp from any to any port 80

は、再構築なしでこの情報が各断片で利用可能でないので、断片が宛先のポート 80 で TCP パケットの部分であっても、決して断片に適用しません。また、これは、断片が新しいか、または適合する既存の状態テーブルエントリを作成することができないことを意味します。状態テーブルエントリは、断片のためのステートフルのフィルタリングとアドレス変換 (NAT、リダイレクション) を不可能にします。

scrub 規則によるパラメータとしてソース、宛先アドレスまたはプロトコルを指定することによって、特定の断片だけを再構築することも可能です。

多くの場合、再構築は、追加メモリ費用を越える利益があり、そして fragment reassemble 修飾子を通してすべての断片を再構築する scrub 規則を使用することが勧められます。

断片キャッシュのために割り付けられたメモリは、 pfctl(8) を使用して制限することができます。いったんこの制限に到達するなら、キャッシュされなければならない断片は、他のエントリがタイムアウトするまで落とされます。また、タイムアウト値を調整することもできます。

現在、IPv4 断片だけがサポートされ、IPv6 断片は、無条件にブロックされます。

アンカ

主なルールセットのほかに、 pfctl(8) は、ルールセットを anchor 取り付けポイントにロードすることができます。 anchor は、規則を保持することができるコンテナ (入れ物)、アドレステーブルと、他のアンカです。

anchor には、 pfctl(8) が、子供のアンカかローディング規則をアタッチするような、操作を実行するためにアンカにアクセスするために使用することができるパスを指定する名前があります。アンカは、ファイルシステム階層構造がどのようにレイアウトされているかと同様に、コンポーネントが‘/’文字よって分離されて入れ子にされています。主なルールセットは、実際にデフォルトのアンカであるので、例えば、フィルタと変換規則は、任意のアンカにも含まれるかもしれません。

アンカは、次の種類の規則を使用して別の anchor アタッチメントポイントを参照することができます:

nat-anchor < name>
指定された anchornat 規則を評価します。
rdr-anchor < name>
指定された anchorrdr 規則を評価します。
binat-anchor < name>
指定された anchorbinat 規則を評価します。
anchor < name>
指定された anchor でフィルタ規則を評価します。
load anchor < name> from < file>
指定されたファイル (file) からルールをアンカ name にロードします。

主なルールセットの評価が anchor 規則に到達するとき、 pf(4) は、そのアンカで指定されたすべての規則を評価し続けます。

quick オプションでマークされるフィルタのマッチングと変換規則は、最終であり、他のアンカと主なルールセットの規則の評価を中止します。 anchor 自体が quick オプションでマークされるなら、ルールセットの評価は、パケットがアンカ内の任意の規則にマッチされるなら、アンカが終了されるとき、終了します。

anchor 規則は、それらが含まれているアンカに相対的に評価されます。例えば、主なルールセットで指定されたすべての anchor 規則は、主なルールセットの下部のアンカアタッチメントポイントを参照し、 load anchor 規則からロードされたファイルで指定された anchor 規則は、そのアンカポイントの下にアタッチされます。

規則は、主なルールセットがロードされるとき、どんな規則も含まない anchor アタッチメントポイントに含まれるかもしれません、そして、後で、そのようなアンカは、主なルールセットか他のアンカを再ロードしないで pfctl(8) を通して操作することができます。例えば、

ext_if = "kue0" 
block on $ext_if all 
anchor spam 
pass out on $ext_if all 
pass in on $ext_if proto tcp from any \ 
      to $ext_if port smtp

は、デフォルトで外部のインタフェースでのすべてのパケットをブロックして、次に、"spam"と名前が付けられた anchor ですべての規則を評価して、最後にポート 25 へのすべての発信接続と着信接続を通過します。

# echo "block in quick from 1.2.3.4 to any" | \ 
      pfctl -a spam -f -

これは、単一の規則を特定のアドレスからすべてのパケットをブロックする、 anchor にロードします。

また、アンカは、 anchor 規則の後に load anchor 規則を加えることによって、投入することができます:

anchor spam 
load anchor spam from "/etc/pf-spam.conf"

また、 pfctl(8)pf.conf をロードするとき、すべての規則をファイル /etc/pf-spam.conf からアンカにロードします。

オプションで、 anchor 規則は、フィルタ規則と同じ構文を使用してパケットフィルタリングパラメータを指定することができます。パラメータが使用されるとき、 anchor 規則は、適合するパケットのためだけに評価されます。これは、次のようなアンカの条件付きの評価を可能とします:

block on $ext_if all 
anchor spam proto tcp from any to any port smtp 
pass out on $ext_if all 
pass in on $ext_if proto tcp from any to $ext_if port smtp

anchor spam 中の規則は、宛先のポート 25 で tcp パケットのためにだけに評価されます。したがって、

# echo "block in quick from 1.2.3.4 to any" | \ 
      pfctl -a spam -f -

は、1.2.3.4 からポート 25 までの接続だけをブロックします。

アンカは、それらのアンカ名のアルファベット順で評価されるべきであるそのポイントにアタッチされたすべてのアンカをを意味する、アスタリスク (‘*’) 文字で終わるかもしれません。例えば、

anchor "spam/*"

は、 spam アンカにアタッチされている各アンカの各規則を評価します。それは、 spam アンカに直接アタッチされているアンカを評価するだけであって、アンカを再帰的に評価するために降りて行かないことに注意してください。

アンカがそれらが含まれているアンカに相対的に評価されるので、与えられたアンカの親と先祖のアンカにアクセスするためのメカニズムがあります。ファイルシステムパス名解決と同様に、シーケンス“..”は、アンカパスコンポーネントとして現れ、そのポイントでのパスの評価の現在のアンカの親のアンカは、新しい現在のアンカになります。例として、次を熟考してください:

# echo ' anchor "spam/allowed" ' | pfctl -f - 
# echo -e ' anchor "../banned"\n pass' | \ 
      pfctl -a spam/allowed -f -

主なルールセットの評価は、 spam/allowed アンカに導きます。そのアンカは、もしあれば、最終的に pass 規則を評価する前に、 spam/banned アンカで規則を評価します。

大括弧 ('{' '}') で区切られたブロック内のルールセットのインラインでフィルタ規則 anchors をロードすることができます。大括弧で区切られたブロックは、規則または他の大括弧で区切られたブロックを含むことができます。アンカがこの方法でロードされるとき、アンカ名は、省略可能となります。

anchor "external" on egress { 
 block 
 anchor out { 
  pass proto tcp from any to port { 25, 80, 443 } 
 } 
 pass in proto tcp to any port 22 
}

‘/’文字を含むアンカ名のどんな参照も、アンカ名のためのパーサ仕様が文字列であるので、アンカ名の周りに二重引用符 (‘"’) 文字を必要とします。

変換の例

この例は、(例えば、root として実行されないので、したがって、ポート 80 をバインドするパーミッションが不足するので) デーモンが実行される、ポート 80 からポート 8080 で着信要求をマップします。

# 容易に変更できるように、インタフェース名のためのマクロを使用します 
ext_if = "ne3" 
 
# 80 にあるように見えるように 8080 でデーモンをマップします 
rdr on $ext_if proto tcp from any to any port 80 -> 127.0.0.1 port 8080

pass 修飾子が与えられるなら、変換規則に適合するパケットは、次のフィルタ規則を検査しないで、通過されます:

rdr pass on $ext_if proto tcp from any to any port 80 -> 127.0.0.1 \ 
      port 8080

以下の例では、vlan12 は、192.168.168.1 として設定されます。マシンは、それらが vlan12 を除いて、任意のインタフェースで外に出ていくとき、 192.168.168.0/24 から 204.92.77.111 に来るすべてのパケットを変換します。これは、192.168.168.0/24 ネットワークからのトラフィックをまるで、 vlan12 上のノードを除いて、ルータでの任意のインタフェースの後ろのノードにインターネットの経路制御 (ルート) 可能なアドレス 204.92.77.111 であるかのように、見えさせるというネットの効果があります。 (したがって、192.168.168.1 は、192.168.168.0/24 ノードと通信することができます。)

nat on ! vlan12 from 192.168.168.0/24 to any -> 204.92.77.111

以下の例で、マシンは、にせの内部の 144.19.74.* ネットワークと 204.92.77.100 の経路制御可能な外部の IP の間にあります。 no nat 規則は、プロトコル AH を変換されることから除外します。

# NO NAT 
no nat on $ext_if proto ah from 144.19.74.0/24 to any 
nat on $ext_if from 144.19.74.0/24 to any -> 204.92.77.100

以下の例では、パケットは、sysadmin によって生成されたものがプロキシされないのと同様に、ある特定のサーバのためにバインドします。他のすべての接続は、つぎの通りです。

# NO RDR 
no rdr on $int_if proto { tcp, udp } from any to $server port 80 
no rdr on $int_if proto { tcp, udp } from $sysadmins to any port 80 
rdr on $int_if proto { tcp, udp } from any to any port 80 -> 127.0.0.1 \ 
      port 80

このより長い例は、NAT とリダイレクションの両方を使用します。外部のインタフェースには、アドレス 157.161.48.183 があります。 localhost では、我々は、FTP セッションがそれにリダイレクトされるのをウェート (待つ) し、 ftp-proxy(8) を実行します。 ftp-proxy(8) のための 3 つの強制的なアンカは、この例から省略されます。 ftp-proxy(8) マニュアルページを参照してください。

# NAT 
# 発信パケットのソースアドレス (のどんなプロトコルも) を変換します. 
# この場合、ゲートウェイの外部アドレスを除いて、すべてのアドレスが 
# マップされます. 
nat on $ext_if inet from ! ($ext_if) to any -> ($ext_if) 
 
# NAT PROXYING 
# 発信パケットのソースポートを任意のポートの代わりに割り当てられた 
# プロキシポートにマップします. 
# この場合、ゲートウェイ上のポート 500 で発信 isakmp をプロキシします. 
nat on $ext_if inet proto udp from any port = isakmp to any -> ($ext_if) \ 
      port 500 
 
# BINAT 
# 発信パケットのソースアドレス (のどんなプロトコルも) を変換します. 
# 着信パケットの宛先アドレスを (双方向の) 内部のマシンに変換します. 
binat on $ext_if from 10.1.2.150 to any -> $ext_if 
 
# RDR 
# 着信パケットの宛先アドレスを変換します. 
例として、TCP と UDP ポートを内部のマシンにリダイレクトします。 
rdr on $ext_if inet proto tcp from any to ($ext_if) port 8080 \ 
      -> 10.1.2.151 port 22 
rdr on $ext_if inet proto udp from any to ($ext_if) port 8080 \ 
      -> 10.1.2.151 port 53 
 
# RDR 
# 発信 ftp 制御接続をポート 8021 で ftp-proxy(8) が実行するように 
# プロキシするために localhost にそれらを送信するために変換します. 
rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 port 8021

この例では、NAT ゲートウェイは、パブリックアドレス (192.0.2.16/28) のプールを使用して内部のアドレスを変換するために、そして、内部のネットワークで web サーバのグループに着信 web サーバ接続をリダイレクトするために、セットアップされます。

# NAT LOAD BALANCE (ロードバランス) 
# アドレスプールを使用して発信パケットのソースアドレスを変換します. 
# 与えられたソースアドレスは、常にソースハッシュキーワードを使用して、 
# 同じプールアドレスに変換されます. 
nat on $ext_if inet from any to any -> 192.0.2.16/28 source-hash 
 
# RDR ROUND ROBIN (ラウンドロビン) 
# 着信 web サーバ接続を内部のネットワークで web サーバのグループに 
# 変換します. 
rdr on $ext_if proto tcp from any to any port 80 \ 
      -> { 10.1.2.155, 10.1.2.160, 10.1.2.161 } round-robin

フィルタの例

# 外部のインタフェースは、kue0 です 
# (157.161.48.183, 経路制御可能なアドレスのみ) 
# と、NAT を行うための、プライベートネットワークは、10.0.0.0/8 です. 
 
# 容易にそれを変更できるようにインタフェース名のためのマクロを使用します 
ext_if = "kue0" 
 
# すべての着信トラフィックを正常化 
scrub in on $ext_if all fragment reassemble 
 
# デフォルトですべてをブロックして、ログを記録する 
block return log on $ext_if all 
 
# 逆の経路制御がないソース (始点) から来るすべてをブロック 
block in from no-route to any 
 
# ingress インタフェースがルートバックのものと、それらのソースアドレスと 
# マッチしないパケットをブロックします 
block in from urpf-failed to any 
 
# ソース (始点) としてアドレスがない発信パケットをブロックしログを記録し 
# ます、良くしたく、ゴミを送信しないように、それらはなりすましされている 
# か何か誤設定 (例えば、NAT を無効にした) されているかのいずれかです 
block out log quick on $ext_if from ! 157.161.48.183 to any 
 
# ブロードキャスト (同報通信) (ケーブルモデム雑音) を静かに落とします 
block in quick on $ext_if from any to 255.255.255.255 
 
# 予約されたアドレス空間と無効のアドレスからの着信パケットをブロックして 
# ログに記録し、とにかくそれらを応答することができない 
# (したがって、rst を返さない)、それらはなりすましされているか何か 
# 誤設定されているかのいずれかです 
block in log quick on $ext_if from { 10.0.0.0/8, 172.16.0.0/12, \ 
      192.168.0.0/16, 255.255.255.255/32 } to any 
 
# ICMP 
 
# 特定の ICMP 問い合わせを out/in に通過させ、ホストアドレスと 
# ICMP ID (タイプ/コードでない) で行われる状態 (ping) 状態を維持し、 
# したがって、応答 (8/0 のための 0/0 のような) は、TCP/UDP 状態に 
# よって操作される (常に TCP/UDP パケットを参照する) ICMP 
# エラーメッセージ要求に一致します 
pass on $ext_if inet proto icmp all icmp-type 8 code 0 
 
# UDP 
 
# すべての UDP 接続を外に通過し、状態を維持します 
pass out on $ext_if proto udp all 
 
# 特定の UDP 接続を内に通過し、状態を維持します (DNS) 
pass in on $ext_if proto udp from any to any port domain 
 
# TCP 
 
# すべての TCP 接続を外に通過し、状態を調節します 
pass out on $ext_if proto tcp all modulate state 
 
# 特定の TCP 接続を内に通過し、状態を維持します (SSH, SMTP, DNS, IDENT) 
pass in on $ext_if proto tcp from any to any port { ssh, smtp, domain, \ 
      auth } 
 
# それらは、通常ウイルスのワームであるので、Windows 9x SMTP 接続を許可 
# しません. 代わりに、これらの OS をそれぞれ 1 つの接続に制限することも 
# あり得ます. 
block in on $ext_if proto tcp from any os {"Windows 95", "Windows 98"} \ 
      to any port smtp 
 
# IPv6 
# すべての IPv6 トラフィックを in/out に通過します: 物理インタフェースと 
# トンネルの両方で、2 つの異なった方法で、これを有効にしなければならない 
# ことに注意してください 
pass quick on gif0 inet6 
pass quick on $ext_if proto ipv6 
 
# パケットのタグ付け 
 
# 3 つのインタフェースは: $int_if, $ext_if と $wifi_if (無線) です. 
# NAT は、すべての発信パケットのために $ext_if で行われています. 
# $int_if で内のパケットにタグ付けをし、$ext_if でそれらのタグ付け 
# されたパケットを外に通過します. 他のすべての発信パケット (すなわち、 
# 無線ネットワークからのパケット) がポート 80 にアクセスすることだけが 
# 許可されます. 
 
pass in on $int_if from any to any tag INTNET 
pass in on $wifi_if from any to any 
 
block out on $ext_if from any to any 
pass out quick on $ext_if tagged INTNET 
pass out on $ext_if proto tcp from any to any port 80 
 
# それらが spamd(8) にリダイレクトされるとき、着信パケットにタグ付けし 
# ます. パケットフィルタを通してそれらのパケットを通過するためにタグを 
# 使用します. 
 
rdr on $ext_if inet proto tcp from <spammers> to port smtp \ 
 tag SPAMD -> 127.0.0.1 port spamd 
 
block in on $ext_if 
pass in on $ext_if inet proto tcp tagged SPAMD

文法

BNF 形式の pf.conf の構文は、次の通りです:

line           = ( option | pf-rule | nat-rule | binat-rule | rdr-rule | 
                 antispoof-rule | altq-rule | queue-rule | trans-anchors | 
                 anchor-rule | anchor-close | load-anchor | table-rule | 
                 include ) 
 
option         = "set" ( [ "timeout" ( timeout | "{" timeout-list "}" ) ] | 
                 [ "ruleset-optimization" [ "none" | "basic" | "profile" ]] | 
                 [ "optimization" [ "default" | "normal" | 
                 "high-latency" | "satellite" | 
                 "aggressive" | "conservative" ] ] 
                 [ "limit" ( limit-item | "{" limit-list "}" ) ] | 
                 [ "loginterface" ( interface-name | "none" ) ] | 
                 [ "block-policy" ( "drop" | "return" ) ] | 
                 [ "state-policy" ( "if-bound" | "floating" ) ] 
                 [ "state-defaults" state-opts ] 
                 [ "require-order" ( "yes" | "no" ) ] 
                 [ "fingerprints" filename ] | 
                 [ "skip on" ifspec ] | 
                 [ "debug" ( "none" | "urgent" | "misc" | "loud" ) ] ) 
 
pf-rule        = action [ ( "in" | "out" ) ] 
                 [ "log" [ "(" logopts ")"] ] [ "quick" ] 
                 [ "on" ifspec ] [ "fastroute" | route ] [ af ] [ protospec ] 
                 hosts [ filteropt-list ] 
 
logopts        = logopt [ "," logopts ] 
logopt         = "all" | "user" | "to" interface-name 
 
filteropt-list = filteropt-list filteropt | filteropt 
filteropt      = user | group | flags | icmp-type | icmp6-type | "tos" tos | 
                 ( "no" | "keep" | "modulate" | "synproxy" ) "state" 
                 [ "(" state-opts ")" ] | 
                 "fragment" | "no-df" | "min-ttl" number | "set-tos" tos | 
                 "max-mss" number | "random-id" | "reassemble tcp" | 
                 fragmentation | "allow-opts" | 
                 "label" string | "tag" string | [ ! ] "tagged" string | 
                 "queue" ( string | "(" string [ [ "," ] string ] ")" ) | 
                 "rtable" number | "probability" number"%" 
 
nat-rule       = [ "no" ] "nat" [ "pass" [ "log" [ "(" logopts ")" ] ] ] 
                 [ "on" ifspec ] [ af ] 
                 [ protospec ] hosts [ "tag" string ] [ "tagged" string ] 
                 [ "->" ( redirhost | "{" redirhost-list "}" ) 
                 [ portspec ] [ pooltype ] [ "static-port" ] ] 
 
binat-rule     = [ "no" ] "binat" [ "pass" [ "log" [ "(" logopts ")" ] ] ] 
                 [ "on" interface-name ] [ af ] 
                 [ "proto" ( proto-name | proto-number ) ] 
                 "from" address [ "/" mask-bits ] "to" ipspec 
                 [ "tag" string ] [ "tagged" string ] 
                 [ "->" address [ "/" mask-bits ] ] 
 
rdr-rule       = [ "no" ] "rdr" [ "pass" [ "log" [ "(" logopts ")" ] ] ] 
                 [ "on" ifspec ] [ af ] 
                 [ protospec ] hosts [ "tag" string ] [ "tagged" string ] 
                 [ "->" ( redirhost | "{" redirhost-list "}" ) 
                 [ portspec ] [ pooltype ] ] 
 
antispoof-rule = "antispoof" [ "log" ] [ "quick" ] 
                 "for" ifspec [ af ] [ "label" string ] 
 
table-rule     = "table" "<" string ">" [ tableopts-list ] 
tableopts-list = tableopts-list tableopts | tableopts 
tableopts      = "persist" | "const" | "counters" | "file" string | 
                 "{" [ tableaddr-list ] "}" 
tableaddr-list = tableaddr-list [ "," ] tableaddr-spec | tableaddr-spec 
tableaddr-spec = [ "!" ] tableaddr [ "/" mask-bits ] 
tableaddr      = hostname | ifspec | "self" | 
                 ipv4-dotted-quad | ipv6-coloned-hex 
 
altq-rule      = "altq on" interface-name queueopts-list 
                 "queue" subqueue 
queue-rule     = "queue" string [ "on" interface-name ] queueopts-list 
                 subqueue 
 
anchor-rule    = "anchor" [ string ] [ ( "in" | "out" ) ] [ "on" ifspec ] 
                 [ af ] [ protospec ] [ hosts ] [ filteropt-list ] [ "{" ] 
 
anchor-close   = "}" 
 
trans-anchors  = ( "nat-anchor" | "rdr-anchor" | "binat-anchor" ) string 
                 [ "on" ifspec ] [ af ] [ "proto" ] [ protospec ] [ hosts ] 
 
load-anchor    = "load anchor" string "from" filename 
 
queueopts-list = queueopts-list queueopts | queueopts 
queueopts      = [ "bandwidth" bandwidth-spec ] | 
                 [ "qlimit" number ] | [ "tbrsize" number ] | 
                 [ "priority" number ] | [ schedulers ] 
schedulers     = ( cbq-def | priq-def | hfsc-def ) 
bandwidth-spec = "number" ( "b" | "Kb" | "Mb" | "Gb" | "%" ) 
 
action         = "pass" | "block" [ return ] | [ "no" ] "scrub" 
return         = "drop" | "return" | "return-rst" [ "( ttl" number ")" ] | 
                 "return-icmp" [ "(" icmpcode [ [ "," ] icmp6code ] ")" ] | 
                 "return-icmp6" [ "(" icmp6code ")" ] 
icmpcode       = ( icmp-code-name | icmp-code-number ) 
icmp6code      = ( icmp6-code-name | icmp6-code-number ) 
 
ifspec         = ( [ "!" ] ( interface-name | interface-group ) ) | 
                 "{" interface-list "}" 
interface-list = [ "!" ] ( interface-name | interface-group ) 
                 [ [ "," ] interface-list ] 
route          = ( "route-to" | "reply-to" | "dup-to" ) 
                 ( routehost | "{" routehost-list "}" ) 
                 [ pooltype ] 
af             = "inet" | "inet6" 
 
protospec      = "proto" ( proto-name | proto-number | 
                 "{" proto-list "}" ) 
proto-list     = ( proto-name | proto-number ) [ [ "," ] proto-list ] 
 
hosts          = "all" | 
                 "from" ( "any" | "no-route" | "urpf-failed" | "self" | host | 
                 "{" host-list "}" ) [ port ] [ os ] 
                 "to"   ( "any" | "no-route" | "self" | host | 
                 "{" host-list "}" ) [ port ] 
 
ipspec         = "any" | host | "{" host-list "}" 
host           = [ "!" ] ( address [ "/" mask-bits ] | "<" string ">" ) 
redirhost      = address [ "/" mask-bits ] 
routehost      = "(" interface-name [ address [ "/" mask-bits ] ] ")" 
address        = ( interface-name | interface-group | 
                 "(" ( interface-name | interface-group ) ")" | 
                 hostname | ipv4-dotted-quad | ipv6-coloned-hex ) 
host-list      = host [ [ "," ] host-list ] 
redirhost-list = redirhost [ [ "," ] redirhost-list ] 
routehost-list = routehost [ [ "," ] routehost-list ] 
 
port           = "port" ( unary-op | binary-op | "{" op-list "}" ) 
portspec       = "port" ( number | name ) [ ":" ( "*" | number | name ) ] 
os             = "os"  ( os-name | "{" os-list "}" ) 
user           = "user" ( unary-op | binary-op | "{" op-list "}" ) 
group          = "group" ( unary-op | binary-op | "{" op-list "}" ) 
 
unary-op       = [ "=" | "!=" | "<" | "≤" | ">" | "≥" ] 
                 ( name | number ) 
binary-op      = number ( "<>" | "><" | ":" ) number 
op-list        = ( unary-op | binary-op ) [ [ "," ] op-list ] 
 
os-name        = operating-system-name 
os-list        = os-name [ [ "," ] os-list ] 
 
flags          = "flags" ( [ flag-set ] "/"  flag-set | "any" ) 
flag-set       = [ "F" ] [ "S" ] [ "R" ] [ "P" ] [ "A" ] [ "U" ] [ "E" ] 
                 [ "W" ] 
 
icmp-type      = "icmp-type" ( icmp-type-code | "{" icmp-list "}" ) 
icmp6-type     = "icmp6-type" ( icmp-type-code | "{" icmp-list "}" ) 
icmp-type-code = ( icmp-type-name | icmp-type-number ) 
                 [ "code" ( icmp-code-name | icmp-code-number ) ] 
icmp-list      = icmp-type-code [ [ "," ] icmp-list ] 
 
tos            = ( "lowdelay" | "throughput" | "reliability" | 
                 [ "0x" ] number ) 
 
state-opts     = state-opt [ [ "," ] state-opts ] 
state-opt      = ( "max" number | "no-sync" | timeout | "sloppy" | "pflow" | 
                 "source-track" [ ( "rule" | "global" ) ] | 
                 "max-src-nodes" number | "max-src-states" number | 
                 "max-src-conn" number | 
                 "max-src-conn-rate" number "/" number | 
                 "overload" "<" string ">" [ "flush" ] | 
                 "if-bound" | "floating" ) 
 
fragmentation  = [ "fragment reassemble" | "fragment crop" | 
                 "fragment drop-ovl" ] 
 
timeout-list   = timeout [ [ "," ] timeout-list ] 
timeout        = ( "tcp.first" | "tcp.opening" | "tcp.established" | 
                 "tcp.closing" | "tcp.finwait" | "tcp.closed" | 
                 "udp.first" | "udp.single" | "udp.multiple" | 
                 "icmp.first" | "icmp.error" | 
                 "other.first" | "other.single" | "other.multiple" | 
                 "frag" | "interval" | "src.track" | 
                 "adaptive.start" | "adaptive.end" ) number 
 
limit-list     = limit-item [ [ "," ] limit-list ] 
limit-item     = ( "states" | "frags" | "src-nodes" ) number 
 
pooltype       = ( "bitmask" | "random" | 
                 "source-hash" [ ( hex-key | string-key ) ] | 
                 "round-robin" ) [ sticky-address ] 
 
subqueue       = string | "{" queue-list "}" 
queue-list     = string [ [ "," ] string ] 
cbq-def        = "cbq" [ "(" cbq-opt [ [ "," ] cbq-opt ] ")" ] 
priq-def       = "priq" [ "(" priq-opt [ [ "," ] priq-opt ] ")" ] 
hfsc-def       = "hfsc" [ "(" hfsc-opt [ [ "," ] hfsc-opt ] ")" ] 
cbq-opt        = ( "default" | "borrow" | "red" | "ecn" | "rio" ) 
priq-opt       = ( "default" | "red" | "ecn" | "rio" ) 
hfsc-opt       = ( "default" | "red" | "ecn" | "rio" | 
                 linkshare-sc | realtime-sc | upperlimit-sc ) 
linkshare-sc   = "linkshare" sc-spec 
realtime-sc    = "realtime" sc-spec 
upperlimit-sc  = "upperlimit" sc-spec 
sc-spec        = ( bandwidth-spec | 
                 "(" bandwidth-spec number bandwidth-spec ")" ) 
include        = "include" filename

関連ファイル

/etc/hosts
ホスト名データベース。
/etc/pf.conf
ルールセットファイルのデフォルトの位置。
/etc/pf.os
OS 指紋のデフォルトの位置。
/etc/protocols
プロトコル名データベース。
/etc/services
サービス名データベース。

歴史

pf.conf ファイル形式は、 OpenBSD 3.0 ではじめて登場しました。
June 29, 2012 FreeBSD