$Id: memo-kame-ipsec-policy.txt,v 1.1.1.1 1999/10/26 17:19:17 sakane Exp $ %Hd: KAME IPsec POLICY やりたいこと - セキュリティゲートウェイ(SG)とホスト(H)でのパケットを扱う。 - IPsec の適用には自由度を持たせる。 セキュリティポリシーデータベース(SPD)の役割 - インデックスに対して、 o パケットの扱い o セキュリティプロトコルの適用順序 o セキュリティプロトコルのレベル を定義する。 - インデックスとは protocol family, src/mask, dst/mask, next protocol, src/dst port - あるパケットに対して唯一つのポリシーを割り当てる。 つまりIPsec トンネルしても再度SPDを見ない。 ※INBOUNDパケットとSPDの関係が良くわからない。 -> どうやって索くか?適用されていた順番とかまで見る? -> IPsec 必要だよ ICMP を突っ返す判断とか。 -> ※Firewallの内側のSGWと通信するISAKMPパケットとかはどうする? -> 500番は素通し? -> パケットの扱い - DISCARD 捨てる。 - BYPASS IPsec しない。root 権限を持ったsocket だけ設定可能。 security-api の Never と等価。SP には適用されない。 - NONE IPsec しない。 - ENTRUST SPD に従う。無ければシステムの値を見て捨てる/通過させる。 setsockopt しない時のデフォルト値。SP には適用されない。 パケットに SP が割り当てらると ENTRUST は他に置き換えられる。 - IPSEC IPsec する。 セキュリティプロトコルの適用順序 自由に設定。 ※ほんと? ->多分 セキュリティプロトコルのレベル - DEFAULT プロトコルとモード毎に定義された system default を参照する。 - USE SA が無ければ ACQUIRE 出して処理を続ける。 通信の途中から IPsec される可能性がある。 ※多重IPsecの時の途中が USE で、かつSAが無ければどうする? -> 飛ばすか? -> - REQUIRE SA が無ければ ACQUIRE 出してパケット破棄。 - see security-api. ※Never っている? -> セキュリティプロトコルの属性じゃないと思う。 -> ※Barrier っている? -> E E は E に展開されるので、Eb E と定義するということ。 紛らわしいのでは? -> ポリシの設定場所 SPD PCB system default ※名前がいい加減かも?ポリシ全体で SPD と呼ぶはず。 -> 優先順序 priviliged socket PCB -> SPD -> system default non-priviliged socket SPD -> PCB -> system default non-socketable SPD -> system default ポリシの設定方法 - setkey SPD を直接操作。 設定可能な値 IPSEC/NONE/DISCARD - setsockopt PCB に登録。 設定可能な値 IPSEC/ENTRUST (デフォルト)/BYPASS ※SPD に登録すべきか? attach で登録。detatch で削除。 port まで含む。 i.g. setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY, &request, request_length); request は struct sadb_x_policy ライブラリ作る ipsec_set_request() をコールする? もちろん getsockopt も可能。 ※超長い request のテスト。done - net.inet{,6}.ipsec{,6}.def_policy 下のいずれかを設定することと等価。 spdadd 0.0.0.0 0.0.0.0 any -P discard spdadd 0.0.0.0 0.0.0.0 any -P bypass ※いっそ SPD と PCB だけにしては? -> non-privileged socket の時、SPD に無ければ PCB を使う という判断が面倒なので def_policy を使う。 - net.inet{,6}.ipsec{,6}.{esp,ah}_{trans,net}_deflev IPSEC_LEVEL_DEFAULT を展開する。 登場人物の説明 SPD の構造 - PF_KEY で操作。 - セキュリティプロトコルの適用順序とレベルを設定を管理する。 - 方向で管理 - security_index protocol family, src/pref, dst/pref, next protocol, src port, dst port - パケットの扱いフラグ [u_int policy] o 取り得る値 DISCARD IPSEC NONE o パケットの扱い参照。 - policy が IPsec ならば [struct ipsecrequest] に値が入る。 - ipsecrequest は数珠繋ぎ。NULL で終了。 o security protocol の種類 [u_int proto] 取り得る値 ESP AH o security protocol の mode [u_int mode] 取り得る値 transport mode tunnel mode o security protocol の level [u_int level] 取り得る値 DEFAULT USE REQUIRE o tunnel mode の時の end point [struct sockaddr *] o SA へのポインタ 毎回 SAD をなめる。※ほんと? in{,6}pcb.in{,6}p_sp - socket の policy を設定。 SPDのエントリと同じ構造 ただしパケットの扱いフラグの取り得る値は IPSEC ENTRUST (デフォルト) BYPASS - setsockopt で設定。 ESP/AH, transport/tunnel それぞれの level と順序を定義 - setsockopt しない時 ENTRUST がデフォルト net.inet{,6}.ipsec{,6}.def_policy: - SPD (または PCB)にポリシが設定されてない時の処理。 - 取り得る値。 DISCARD NONE net.inet{,6}.ipsec{,6}.{esp,ah}_{trans,net}_deflev - ipsecrequest の level に設定される IPSEC_LEVEL_DEFAULT を展開するために利用。 - 取り得る値。 USE REQUIRE SAD の構造 - PF_KEY で操作。 - 方向で管理 - security_index protocol family, src/pref, dst/pref, next protocol, src port, dst port - SA のステータスで管理 LARVAL, MATURE, DYING, DEAD - SA へのポインタ SA のパラメータ SPI, key, algorithm,... ホストとしてのポリシ決定方法 - transport mode, tunnel mode ともに使用可能。 - socket を持たないパケットの扱いはセキュリティゲートウェイを参照。 - SP が変わることを想定して出す時はip{,6}_output で決定する。 - 入って来る時は {udp,tcp,icmp,*}{4,6}_input の最初でチェックする。 ※現行KAMEは {esp,ah}{4,6}_input でもやっている。 -> - setsockopt で socket 単位のポリシが設定可能。 - setkey で system のポリシを設定可能。 - root と一般ユーザでは選択方法が異なる。 privileged socket - setsockopt で設定された値が常に優先される。 - setsockopt しない時は、SPD の値を採用する。 - SPD にも無ければシステムの値[def_policy]を見て、 捨てる/通過させる。 non-privileged socket - SPD で設定された値が優先される。 - SPD に無ければ setsockopt で設定された値を採用。 BYPASS は設定不可。 - SPD にも無ければシステムの値[def_policy]を見て、 捨てる/通過させる。 セキュリティゲートウェイとしてのポリシ決定方法 - forward するパケットには tunnel mode のみ使用可能。 - user land からのパケットの扱いはホストのポリシ決定方法参照。 - SP が変わることを想定して出す時はip{,6}_output で決定する。 - 入って来る時は ip{,6}_forward の最初でチェックする。 ※現行KAMEは {esp,ah}{4,6}_input でもやっている。 -> - SPD の値により処理する。 - 無ければシステムの値[net.inet{,6}.ipsec{,6}.def_policy]を見て、 捨てる/通過させる。 - SP や SA を拾う時、forward するパケットは上位層ヘッダを見ない。 ※IP6F_MORE_FRAG とか IP_MF を見るか? - セキュリティゲートウェイであることの判断方法 net.inet.ip.forwarding == 1 ならば IPv4 に関して net.inet6.ip6.forwarding == 1 ならば IPv6 に関して ※マッチしたSPDにtunnel が設定されていたら? -> パケットの通り道による分類 1. socket(userland)から入って来てifへ出て行く [outbound] 2. ifから入って来てifへ出ていく [forward] 3. ifから入って来てifへ出ていく [icmp echoとか] 4. ifから入って来てsocket(userland)へ出て行く [inbound] m_flags M_AUTHENTIC data origin authentication for IP header M_DECRYPTED confidentiality M_INTEGRITY data origin authentication 略語定義 packet index 1 protocol family, src, dst, next protocol, src port, dst port packet index 2 protocol family, src, dst, ※IPv4 は next protocol を含めるか? -> packet index 3 protocol family, src, dst, security protocol, spi 1. について出て行く時 - privilieged socket の時 PCB policy == BYPASS ならば何もしない。 PCB policy == ENTRUST ならば packet index 1 で SPD を探す。 SP が無ければ def_policy を見て捨てる/通過させる。 PCB policy == IPSEC ならば設定されている SP を採用。 setsockopt で SP が設定されいるはず。 - non-privilieged socket の時 packet index 1 で SPD を探す。 SP が無ければ PCB policy == BYPASS ならばエラー。そもそも設定出来ない。 PCB policy == ENTRUST ならばdef_policy を見て捨てる/通過させる。 PCB policy == IPSEC ならば設定されている SP を採用。 - SP に設定されている policy をみる。 SP policy == DISCARD ならばパケット破棄 SP policy == NONE ならばなにもしない SP policy == IPSEC ならば以下に続く。 - SP に設定されている ipsec request に適応した SA を SAD から拾う。 level == DEFAULT ならば ipsec{,6}.{esp,ah}_{trans,net}_deflev を適用。 level == REQUIRE かつ SA == NULL ならば ACQUIRE して破棄。 - 必要なだけひねる 2. について出て行く時 - packet index 2 で SPD を探す。 ※IP6F_MORE_FRAG とか IP_MF を見て packet index 1 にする? -> SP が無ければ def_policy を見て捨てる/通過させる。 - SP に設定されている ipsec request に適応した SA を SAD から拾う。 level == DEFAULT ならば ipsec{,6}.{esp,ah}_{trans,net}_deflev を適用。 level == REQUIRE かつ SA == NULL ならば ACQUIRE して破棄。 - 必要なだけひねる 3. について出て行く時 - packet index 1 で SPD を探す。 SP が無ければ def_policy を見て捨てる/通過させる。 - SP に設定されている ipsec request に適応した SA を SAD から拾う。 level == DEFAULT ならば ipsec{,6}.{esp,ah}_{trans,net}_deflev を適用。 level == REQUIRE かつ SA == NULL ならば ACQUIRE して破棄。 - 必要なだけひねる ※ 3. かどうかの判断は? -> v4 は (flag & IP_FORWARDING) == IP_FORWARDING && so == NULL -> MT_DUMMYNET の時 flag をクリアしちゃうけど平気? -> ※上にあがって来た時点で双方向の SA は確立しているはずなので、 もしSAが無ければ ACQUIRE しないで破棄するのが正しい動作? -> ※port unreach の時は? -> 2,3,4. について入って来る時 - next protocol で {esp,ah}_input()が呼ばれる。 - packet index 3 で SAD を探す。 - ほどく - ESP なら M_DECRYPTED 立てる。 - ICV あるなら M_INTEGRITY も。 - AH なら M_AUTHENTIC, M_INTEGRITY ※どうやって SP と比較するか? -> mbuf で履歴持てないので、とりあえず m_flags だけ見る。 -> 2. に関して - packet index 2 で SPD を探す。 ※IP6F_MORE_FRAG とか IP_MF を見て packet index 1 にする? -> SP が無ければ def_policy を見て捨てる/通過させる。 - SP に設定されている ipsec request に応じてチェックする。 3. に関して - packet index 3 で SPD を探す。 SP が無ければ def_policy を見て捨てる/通過させる。 - SP に設定されている ipsec request に応じてチェックする。 4. に関して - privilieged socket の時 PCB policy == BYPASS ならば何もしない。 PCB policy == ENTRUST ならば packet index 1 で SPD を探す。 SP が無ければ def_policy を見て捨てる/通過させる。 PCB policy == IPSEC ならば設定されている SP を採用。 setsockopt で SP が設定されいるはず。 - non-privilieged socket の時 packet index 1 で SPD を探す。 SP が無ければ PCB policy == BYPASS ならばエラー。そもそも設定出来ない。 PCB policy == ENTRUST ならばdef_policy を見て捨てる/通過させる。 PCB policy == IPSEC ならば設定されている SP を採用。 - SP に設定されている policy をみる。 SP policy == DISCARD ならばパケット破棄 SP policy == NONE ならばなにもしない SP policy == IPSEC ならば以下に続く。 - SP に設定されている ipsec request に応じてチェックする。 例1. {IPa}---{IPx}==={IPy}---{IPb} IPx では setkey を使って SPD に設定されている。 (1) IPa->IPb: ipsec esp/IPy (2) IPb->IPa: ipsec esp/IPx この時、IPx から出るパケットは (1) を使って、 [IPx->IPy]|ESP|[IPa->IPb] 入って来るパケットは、 [IPy->IPx]|ESP|[IPb->IPa] 剥いた後の IPx でのチェックは IPb->IPa で SPD を検索して (2) を使う。 例2. IPa では setsockopt を使って PCB に設定されている。 (3) IPa->IPb: ipsec esp この時、IPa から出るパケットは (3) を使って、 [IPa->IPb]|ESP|[IPa->IPb] 入って来るパケットは、 [IPb->IPa]|ESP|[IPb->IPa] 剥いた後の IPa でのチェックは、 privileged socket PCB の (3) を使う。 non-privileged socket IPb->IPa で SPD を検索する。なければ PCB の (3) を使う。 注意 - ひとまず汎用フィルタからは切り離して考える。