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 $