PF_POLICY Policy Management API, Version 1 o 現状把握 - RFC2401はSPDの構造やAPIを厳密に定義していない。 - APIは各実装がPF_KEYv2を独自拡張している。 - 本質的に PF_KEYとは別なので分けるべき。 - うまく分けるとIPフィルタにも使える共通I/Fになるかも。 o 要求事項と考察 security policy とは、あるselectorセットにマッチしたトラフィックに 対してどのように処理するかを記述した情報。 あるpolicy(s)に指示された SAを uniqueにできる。 selector1 --- policy1 --- sa1 selector2 --- policy2 --- sa2 / selector3 --- policy3 -+ selector4 -+ \ selector5 --- policy4 -+- sa3 selector6 --- policy5 --- sa4 \ +- sa5 policyのネゴって必要? 通常のフィルターには必要ない ipsecは必要 例えば、ある相手とIPsecすれば通してやるぞとか 両端点ではなくポリシサーバとのやりとりなはず 新しいホストが来て、UPnP で穴開けろというような場合... PF_POLICY の枠組ではない。ネゴd がいて、そいつが PF_POLICY を使って何かする。 PF_POLICYとは関係ないと思う policy にlifetimeは必要? 期限付きフィルターって必要でしょ 仮にないとするとポリシ管理デーモンが管理しなければいけない。 そのデーモンが死ぬといつまでもフィルタが残っちゃうから必要 daemon が落ちてポリシーをメンテナンスできない状態に なった時、消えて欲しいポリシーというものもある。 下位互換性。PF_KEYv2拡張として既に実装しちゃってるんだけど… registerしてもらえば平気 SADB_REGISTERしたプロセス => PF_KEYv2拡張 SPDB_REGISTERしたプロセス => PF_POLICY 既存のPF_KEYv2独自拡張を壊してはならない。 例えば、PF_KEYv2を使っている racoon(version 1)は 動作しなければいけない。 カーネルは古いアプリケーションを許容しなければいけない。 racoon2 は PF_POLICY を使う。 あるパケットに対するセキュリティポリシをアプリケーションが知りたい ADDとUPDATE分ける必要があるか?ADDが必ずupdate動作をするでは? 分けた方がわかりやすそう。 間違ってうっかり上書きしてしまうことを防ぐには 分かれていた方がよい。 IKEv2ではプレフィクスという概念が無くなった。 セレクタにレンジを導入せざるをえない。 同じSGW間に別のSAを張りたい このポリシのためのSAといった結び付きが必要 o Policy Index セキュリティポリシを識別するための32ビットの番号 セレクタを括るために使えるので実装上はSPDで一意である必要はない ポリシインデックスはシステムの外で使用するべきではないが 0, 0xffffffff は予約されている。 あるセキュリティポリシに対する SAを指定したい時に有効 またSAが、どのセキュリティポリシに属しているのかを指定するのに使う。 policy_index と ポリシのセレクタの違い ポリシのセレクタ source address source address prefix length source port number destination address destination address prefix length destination port number upper layer protocol SAの識別子 SA source address SA destination address security protocol spi この2つを結びつけるのが policy-index o Policy Sequence Number SPDで一意な番号 ここで指定した番号の若いセキュリティポリシから順番にパケットと比較する あとで追加できるように、番号を 10 個おきに振りたいかもしれない。 誰が面倒をみるかは実装依存でいい。(管理者(ユーザ)に任せる) policy_indexと分ける理由 SAにpolicy-Idを使われていたときのrenumberをしたくないので 0 は予約 o Security Policy Selector セレクタ source address source prefix source port source address range source port range destination address destination prefix destination port destination address range destination port range upper layer protocol number icmp type icmp code o Security Policy Rule カーネルの挙動 bypass discard ipsec o Base Message Header Format struct spdb_msg { uint8_t spdb_msg_version; uint8_t spdb_msg_type; uint8_t spdb_msg_errno; uint8_t spdb_msg_reserved; uint16_t spdb_msg_len; uint16_t spdb_msg_reserved; uint32_t spdb_msg_seq; uint32_t spdb_msg_pid; }; spdb_msg_version; 1 spdb_msg_type; o Additional Message Fields + Security policy extension header Security policy extension header specifies the way to process a traffic. this structure also includes the direction of a traffic. struct spdb_policy { u_int16_t spdb_policy_len; u_int16_t spdb_policy_exttype; u_int16_t spdb_policy_type; /* See policy type of ipsec.h */ u_int8_t spdb_policy_dir; /* direction, see ipsec.h */ u_int8_t spdb_policy_reserved; u_int32_t spdb_policy_index; u_int32_t spdb_policy_flags; }; /* sizeof(struct spdb_policy) == 16 */ spdb_policy_len length of the header in 64 bit words. it is always 2. spdb_policy_exttype SPDB_EXT_POLICY the type of the header. spdb_policy_type the type of the policy. IPSEC_POLICY_DISCARD IPSEC_POLICY_IPSEC IPSEC_POLICY_BYPASS spdb_policy_dir the direction of the packet which the policy matches with. IPSEC_DIR_INBOUND IPSEC_DIR_OUTBOUND spdb_policy_index the policy index. the kernel assigns a number to each individual security policy. spdb_policy_flags SPDB_SAFLAGS_UDPENCAP spdb_policy_reserved reserved value. it must be zeroed by the sender. + Security protocol extension header Security protocol extension header specifies the information about a single SA. This extension header is used only when security protocol is required. In other words, when spdb_policy_type in the security policy extension header is set IPSEC_POLICY_IPSEC, this extension header MUST be required. In the case of SA bundle, multiple Security protocol extension headers must exist in a single PF_KEY message. The security protocol extension header of the most of innner SA is located to the top of these headers. For example, when ESP is applied to a outbound packet and then AH applys to to the packet, the packet format is like [IP|AH|ESP|data], the extension header about ESP must be placed first, then the extension header about AH must be next. A single security protocol extension header is constructed by two parts. First part specifies the security protocol to be used including the ipsec mode, the level of the SA and the SA identifier. Second part specifies the addresses of the end point of the security association. The part must follows the first part. The second part may not be needed when the ipsec mode is transport mode. Second part is constructed by the source IP address of the SA and immediately followed by the destination IP address of the SA. These are packed into two of sockaddr structures without any padding. sa_len MUST be set exact lenght of the sockaddr structure. Each length of the sockaddr structure are not aligned to 64 bits, Total length of the security protocol extension header MUST be aligned to 64bits. The padding must be set zero. struct spdb_ipsecpolicy { u_int16_t spdb_ipsecpolicy_len; u_int16_t spdb_ipsecpolicy_proto; u_int8_t spdb_ipsecpolicy_mode; u_int8_t spdb_ipsecpolicy_level; u_int16_t spdb_ipsecpolicy_reqid; }; [total length of ipsec policy requests] = (spdb_policy_len * sizeof(uint64_t) - sizeof(struct spdb_policy)) u_int16_t spdb_ipsecpolicy_len; length of the field in 64 bit words. u_int16_t spdb_ipsecpolicy_proto; the security protocol of the security association to be used. IPPROTO_ESP 50 IPPROTO_AH 51 IPPROTO_IPCOMP 108 u_int8_t spdb_ipsecpolicy_mode; the protocol mode of the securitfy association to be used. IPSEC_MODE_ANY 0 IPSEC_MODE_TRANSPORT 1 IPSEC_MODE_TUNNEL 2 u_int8_t spdb_ipsecpolicy_level; the security level of the security association to be used. IPSEC_LEVEL_DEFAULT 0 /* reference to system default */ IPSEC_LEVEL_USE 1 /* use SA if present. */ IPSEC_LEVEL_REQUIRE 2 /* require SA. */ IPSEC_LEVEL_UNIQUE 3 /* unique SA. */ u_int16_t spdb_ipsecpolicy_reqid; the identifier of the security association to be used. this value MUST be zero when the security level is not IPSEC_LEVEL_UNIQUE. + Address Extension struct spdb_address { uint16_t spdb_address_len; uint16_t spdb_address_exttype; uint8_t spdb_address_proto; uint8_t spdb_address_prefixlen; uint16_t spdb_address_reserved; }; /* sizeof(struct spdb_address) == 8 */ /* followed by some form of struct sockaddr(s) */ spdb_address_exttype SPDB_EXT_ADDRESS_SRC SPDB_EXT_ADDRESS_DST SPDB_EXT_ADDRESS_SRCRANGE rangeを示す sockaddrが2つ続く。 SPDB_EXT_ADDRESS_DSTRANGE rangeを示す sockaddrが2つ続く。 SPDB_EXT_ADDRESS_REAL UDP encapsulationするためにNATする前のアドレスを指定 + Lifetime Extension struct spdb_lifetime { uint16_t spdb_lifetime_len; uint16_t spdb_lifetime_exttype; uint32_t spdb_lifetime_allocations; uint64_t spdb_lifetime_bytes; uint64_t spdb_lifetime_addtime; uint64_t spdb_lifetime_usetime; }; /* sizeof(struct spdb_lifetime) == 32 */ spdb_lifetime_exttype SPDB_EXT_LIFETIME_HARD + Supported Algorithms Extension struct sadb3_supported { uint16_t sadb3_supported_len; uint16_t sadb3_supported_exttype; uint32_t sadb3_supported_flags; }; sadb3_supported_flags SPDB_SUPPORTED_NAT_T o Message Types SPDB_ADD カーネルに新規セキュリティポリシを追加する policy_index == 0 の時はカーネルが決めて、 戻りのメッセージに設定する user -> kernel kernel -> user SPDB_UPDATE カーネルに既にあるセキュリティポリシを変更する policy_index != 0 user -> kernel kernel -> user SPDB_DELETE カーネルにあるセキュリティポリシをあるかたまりで削除する 以下のまとまりが有効な指定。 policy(dir) policy(index) address(S) address(D) なし なし なし なし あり なし なし なし なし あり なし なし なし なし あり なし なし なし なし あり user -> kernel kernel -> user user -> kernel kernel -> user user -> kernel kernel -> user SPDB_GET カーネルにあるセキュリティポリシをカーネルから取得する SPDのselectorにexactly matchしたエントリ(selector,rule)を返す 引数は prefixやrangeもありえる 以下のまとまりが有効な指定。 policy(dir) policy(index) address(S) address(D) なし なし なし なし あり なし なし なし なし あり なし なし なし なし あり なし なし なし なし あり * SPD全て user -> kernel kernel -> user * 特定の policy index user -> kernel kernel -> user * 範囲 user -> kernel kernel -> user SPDB_REGISTER カーネルにPF_POLICYメッセージのリスナーであることを登録する。 カーネルがサポートしているプロトコルを取得する。 send it from an user process to the kernel. return it to the socket that sent the above message. SPDB_EXPIRE ポリシがexpireしたことをユーザに知らせる。 kernel -> user kernel -> user SPDB_QUERY SPDのselectorに引っかかるpolicy indexを返す 引数はアドレス/ポートそのもの 引数は prefixやrangeはありえない あるパケットがどのポリシにマッチするかを知りたい場合に使う user -> kernel policy_index == 0 user -> kernel policy_index != 0 APPENDIX A o kame実装 see http://www.kame.net/newsletter/20021210/ SPDSETIDX って? 新規にポリシのセレクタだけを突っ込む。 SPDADD は index + rule を新規に突っ込む。 使い方 - 最初に selector だけ設定しておく。 - パケットがマッチすると rule がないので SPDACQUIRE が上がる。 - SPDUPDATE する lifetime は index, rule のどちらに属する? setidx したものが expire すると、index ごと消えるのか? i.e. filter が expire するのか、 rule がするのか。 現状では setidx にも lifetime があるようだが... これは何故? index の lifetime と rule の lifetime という考え方があって、 rule の lifetime の場合は、rule のみ消える。 index の lifetime の場合、filter じたいが消える。 両方必要か? rule の expire == index の expire という考え方もできるか? シナリオ1 setidx だけしておく。 したから上がってくると rule が設定される。 で、この rule が expire したときどうしたいか。 rule だけ消したいよね。 シナリオ2 rule にはそもそも lifetime なし。 expire したとき index ごと消えてしまう。 それでいいのか。 そもそも index と rule が分かれているのはなぜ? index だけ先に決まるという運用がありそう。 rule が決まる前にパケットが来ちゃったら? 捨てる。 その捨てるの自体、rule だと思う。 最初は discard で、あとから update するというのと同じ。 例えば UPnP なんかで、 selector と rule が別々に決まる/変化するという状況はない? $Id: memo-pfpolicy-spec-jp.txt,v 1.4 2003/06/06 07:34:39 sakane Exp $