[前に戻る: テーブル] [目次] [次に進む: ネットワークアドレス変換 (NAT)]
フィルタルールには、パケットがマッチすべき判断基準、およびパケットがマッチした場合に その結果として取るべき、通過かブロックかのいずれかの動作が指定されます。 フィルタルールは、先頭から末尾の方に向けて、指定されている順序で評価されます。 パケットが、quick キーワードの指定されたルールにマッチしない限りは、 最終的な動作が行われるまでに、パケットはすべてのフィルタルールに対して 評価されることになります。最後にマッチしたルールが「勝者」であり、パケットに対して どのような動作を取るべきかが指示されることになります。フィルタリングルールセット の先頭に、暗黙のうちに pass all が指定されていると見なされるため、 パケットがどのフィルタルールにもマッチしなかった場合には、その結果として取られる 動作は通過となります。
action direction [log] [quick] on interface [af] [proto protocol] \
from src_addr [port src_port] to dst_addr [port dst_port] \
[tcp_flags] [state]
デフォルトで拒否するフィルタのポリシーを作成するには、 最初のふたつのフィルタルールは以下のものでなければなりません。
block in all
block out all
これはすべてのインターフェイス上の、どこからどこへ行くものであっても、 すべてのトラフィックを双方向ともブロックするというものです。
いくつかの例を以下に示します。
# dc0 上に、ローカルネットワーク 192.168.0.0/24 から OpenBSD マシンの
# IP アドレス 192.168.0.1 に着信するパケットだけを通過させます。また、
# dc0 から戻って行くトラフィックも同様に通過させます。
pass in on dc0 from 192.168.0.0/24 to 192.168.0.1
pass out on dc0 from 192.168.0.1 to 192.168.0.0/24
# OpenBSD マシン上で実行される web サーバへの、fxp0 上の TCP の
# 着信トラフィックを通過させます。パケットが OpenBSD マシン宛の
# ものである場合のみこのルールにマッチするよう、インターフェイス名
# fxp0 を送信先アドレスとして使用しています。
pass in on fxp0 proto tcp from any to fxp0 port www
良くない例:
block in on fxp0 proto tcp from any to any port ssh
pass in all
この例では、この block 行は評価されるかも知れませんが、 その次に、何でも通過させてしまう行があるため、 何の効果も持ちません。
良い例:
block in quick on fxp0 proto tcp from any to any port ssh
pass in all
これらのルールの場合、少し異なる評価が行われます。block 行にマッチすると、quick オプションが指定されているため、 パケットはブロックされ、残りのルールセットは無視されます。
状態の保持は、より簡単なルールセットやより良いフィルタリング性能など、 多くの優位性を持っています。PF は状態テーブルのエントリと移動するパケットとを 双方向ともマッチさせることができますが、これは帰りのトラフィックを 通過させるためのフィルタルールを記述する必要がないことを意味しています。 そして、状態を持つ接続にパケットがマッチするとルールセットを評価する 必要がないので、PF がこれらのパケットの処理に要する時間を大幅に 減少させることができます。
ルールが keep state オプションを持つ場合、ルールにマッチする 最初のパケットは、送信者と受信者との間の「状態」を生成することになります。 今、送信者から受信者に送出されるパケットは状態エントリにマッチし、ルールセット の評価をバイパスするだけでなく、受信者側から送信者側に送り返される 応答パケットも同様のことが行われます。これはたとえば、以下の例のような行です。
pass out on fxp0 proto tcp from any to any keep state
これは、fxp0 インターフェイスから送出されるすべての TCP トラフィックを 通過させ、応答のトラフィックがファイアウォールを通過するのを許可しています。 状態の保持はすばらしい機能であり、状態テーブルの参照は、 パケットとフィルタルールを評価していくのに比べて劇的に高速ですので、 この機能を使用することで、ファイアウォールの性能を著しく改善します。
modulate state オプションは、それが TCP にのみ適用可能であることを除いて、 keep state と同様に機能します。 modulate state の場合、送出される接続の初期シーケンス番号 (ISN: Initial Sequence Number) がランダム化されます。これは、ISN を選択する際に、 単純に決定してしまうようなある種のオペレーティングシステムから開始した接続を 保護する上で役に立つ機能です。
送出される TCP、UDP および ICMP パケットの状態の保持、ならびに変調された TCP の ISN を指定するには、以下の例のようにします。
pass out on fxp0 proto tcp from any to any modulate state
pass out on fxp0 proto { udp, icmp } from any to any keep state
状態を保持することのもうひとつの優位性は、関連する ICMP トラフィックが ファイアウォールを通過することができるということです。たとえば、TCP 接続に keep state が指定されている場合、ICMP 始点抑制メッセージが この TCP 接続の到着を参照しますが、これは適切な状態エントリにマッチするので ファイアウォールを通過することができます。
状態を持つ接続は、その接続が生成されたインターフェイス上に制限されるということは、 注意すべき重要事項です。このことは、PF を実行するルータやファイアウォールでは 特に重要なことであり、特に「デフォルトで拒否」のポリシーが上記の概要のとおり 実装されている場合にはなおさらです。もし、ファイアウォールが外部インターフェイス上の すべての送出接続の状態を保持している場合、これらのパケットはやはり明示的に 内部インターフェイスにわたすべきでしょう。
nat、 binat、および rdr ルールは、マッチした接続が フィルタのルールセットにわたされる限り、暗黙のうちにその接続の 状態を生成するということに注意してください。
ルールの評価中に TCP のフラグを PF に検査させるためには、 flags キーワードを以下のシンタクスで使用します。
flags check/mask
mask 部は指定されたフラグのみ検査することを PF に指示し、 check 部に指定されたフラグは、マッチしたパケットの ヘッダ中のフラグが "on" に違いないことをチェックするよう指示します。
pass in on fxp0 proto tcp from any to any port ssh flags S/SA
上記のルールは、SYN ならびに ACK フラグだけに注目しているので、 SYN フラグのセットされた TCP トラフィックを通過させます。また、 SYN と ECE フラグのセットされたパケットは、やはり上記のルールに マッチしますが、SYN と ACK か ACK だけのパケットはマッチしません。
注: 以前のバージョンの OpenBSD では、 以下のシンタクスがサポートされていました。
. . . flags S
現在ではもはやこれは有効ではありません。マスクは常に指定されている必要があります。
状態エントリの生成の制御を行いやすくするために、フラグは keep state ルールと関連してしばしば使用されます。
pass out on fxp0 proto tcp all flags S/SA keep state
これは、SYN、ACK フラグのうちの SYN フラグだけがセットされた すべての送出 TCP パケットのための状態の生成を許可します。
フラグの使用には注意が必要です。なぜ、何をしようとしているのか理解すべきですし、 それは間違っているなどの、人びとのアドバイスにも耳を傾けるべきです。ある人たちは、 「他のものは除いて SYN フラグがセットされたものだけ」の状態を生成するよう 示唆しています。そのようなルールは以下のような最後になっていたりします。
. . . flags S/FSRPAUEW あまり良くない考えです !!
その理屈は、TCP セッションの開始時点のみ状態を生成すべきであり、 セッションは他のフラグのない、SYN フラグで始まるべきである、 ということなのです。問題は、ECN フラグを使用し始めたいくつかのサイトで、 接続を試みてくる ECN の使用サイトはすべてこのようなルールによって 拒絶されるでしょう。より良い指針は以下のようなものです。
. . . flags S/SAFR
これは実戦的で安全なものではありますが、このトラフィックが スクラブ (scrub) 済のものであった場合には、 不要なチェックでもあります。スクラブの処理では、(SYN と FIN や SYN と RST のような) 正しくない TCP フラグの組み合わせを持つすべての着信パケットを PF は廃棄します。これは、以下のような scrub による着信パケットの場合、 常に強く推奨されるものです。
scrub in on fxp0
.
.
.
pass in on fxp0 proto tcp from any to any port ssh flags S/SA \
keep state
通常、クライアントがサーバに対して TCP 接続を行おうとする場合、 PF はこれら 2 点間の ハンドシェイクパケットが到着するよう、通過させます。 しかし、PF には、このハンドシェイクのプロキシを行う能力があります。 このハンドシェイクのプロキシが行われると、PF 自身がクライアントと完全な ハンドシェイクを行い、PF がサーバに対してハンドシェイクを行おうとします。 その上で、これら 2 点間のパケットを通過させます。 このプロセスの利点は、クライアントがハンドシェイクを完了させるまで、 サーバに対して一切のパケットを送信しないことです。 詐称されたクライアントの接続はハンドシェイクを完了することができないので、 これによって、サーバに影響を及ぼす、詐称された TCP SYN flood の脅威を 取り除くことができます。
TCP SYN プロキシは、以下の例のように、フィルタルール中で synproxy state キーワードを使用することによって有効化することができます。
pass in on $ext_if proto tcp from any to $web_server port www \
flags S/SA synproxy state
これで、web サーバへの接続は、PF により TCP のプロキシが行われるようになります。
synproxy state は、その動作原理から keep state および modulate state の機能も含んでいます。
bridge(4) 上で PF が動作している場合には SYN プロキシは動作しません。
PF は、以下のような antispoof キーワードを使用した、 いくつかのアドレス詐称に対する防御機能を提供しています。
antispoof [log] [quick] for interface [af]
例:
antispoof for fxp0 inet
ルールセットがロードされると、指定されている antispoof キーワードはすべて、 ふたつのフィルタルールに展開されます。インターフェイス fxp0 が IP アドレスとして 10.0.0.1 を持ち、サブネットマスクとして 255.255.255.0 (つまり /24) を持つものとすると、上記の antispoof ルールは以下のように展開されます。
block in on ! fxp0 inet from 10.0.0.0/24 to any
block in inet from 10.0.0.1 to any
これらのルールにより、以下のようなふたつのことができるようになります。
注: antispoof ルールを展開した後のフィルタルールは、 ループバックインターフェイスからローカルアドレスに送信しようとしたパケットも ブロックします。これらのアドレスは、以下の例のように、明示的にわたすべきです。
pass in quick on lo0 all
antispoof for fxp0 inet
antispoof の使用法は、IP アドレスが割り当てられているインターフェイスに限定 すべきものです。IP アドレスが割り当てられていないインターフェイスに antispoof を使用することは、以下のようなフィルタルールに展開される結果となってしまいます。
block drop in on ! fxp0 inet all
block drop in inet all
これらのルールには、すべてのインターフェイスで、すべての 内向きトラフィックをブロックしてしまう危険性があります。
pass in quick on fxp0 all allow-opts
ext_if = "fxp0" int_if = "dc0" lan_net = "192.168.0.0/24" # scrub incoming packets scrub in all # setup a default deny policy block in all block out all # pass traffic on the loopback interface in either direction pass quick on lo0 all # activate spoofing protection for the internal interface. antispoof quick for $int_if inet # only allow ssh connections from the local network if it's from the # trusted computer, 192.168.0.15. use "block return" so that a TCP RST is # sent to close blocked connections right away. use "quick" so that this # rule is not overridden by the "pass" rules below. block return in quick on $int_if proto tcp from ! 192.168.0.15 \ to $int_if port ssh flags S/SA # pass all traffic to and from the local network pass in on $int_if from $lan_net to any pass out on $int_if from any to $lan_net # pass tcp, udp, and icmp out on the external (Internet) interface. # keep state on udp and icmp and modulate state on tcp. pass out on $ext_if proto tcp all modulate state flags S/SA pass out on $ext_if proto { udp, icmp } all keep state # allow ssh connections in on the external interface as long as they're # NOT destined for the firewall (i.e., they're destined for a machine on # the local network). log the initial packet so that we can later tell # who is trying to connect. use the tcp syn proxy to proxy the connection. pass in log on $ext_if proto tcp from any to { !$ext_if, !$int_if } \ port ssh flags S/SA synproxy state |
[前に戻る: テーブル] [目次] [次に進む: ネットワークアドレス変換 (NAT)]