ここにある文章は「BSD magazine No.6」に掲載された記事を アスキー社編集部の許可を得て公開しています。
WEBで公開するため若干手を加えているので、表現や言葉使いに相違があります。


IPsec/IKEとKAME

IPsecは暗号技術を基にしたセキュリティをIP層に提供するプロトコルである。 1992年頃からIETFのIPSEC分科会で設計が始まり、1995年に最初の仕様が発行された。 しかし、より高品質なセキュリティを提供するために、そして記述の曖昧さ を明確にして1998年に改定された。 1998年の仕様改定ではセキュリティ・プロトコルの互換性は保たれなかったので、 古い仕様の実装は新しい仕様の実装と通信できないことに注意する必要がある。 今回は新しい仕様をもとに、その概要と仕組みを説明して、 KAMEプロジェクトが開発したIPsecの使い方を解説する。

IPsecの概要

IPsecは、秘匿性を主に提供するIP Encapsulating Security Payload(ESP)と、 完全性と認証を提供するIP Authentication Header(AH)の 2つのセキュリティ・プロトコル、そして、それらのパラメータを交換する Internet Key Exchange(IKE)からなる。

これらのプロトコルは、暗号技術を組み合わせてIP層にセキュリティを提供している。 また、そこで使う暗号アルゴリズムは取り換えや組み合わせが自由に出来るように 設計されている。これにより将来新しいより強力な暗号アルゴリズムが開発された時に、 置き換えを容易にしている。 以降では、符号(暗号)化するアルゴリズムを暗号化アルゴリズム、 認証するためのアルゴリズムを認証アルゴリズム、 暗号技術で一般に使われるアルゴリズムを単に暗号アルゴリズムと呼ぶ。

IPsecは、それぞれのセキュリティ・プロトコルでどの暗号アルゴリズムを使うかや、 セキュリティ・プロトコルや暗号アルゴリズムで使う固有の情報を管理する必要がある。 これらのパラメータはSecurity Association(SA)と呼ばれる論理的なコネクションを 構成する一部になっている。 そして、このSAを管理するデータベースをSecurity Association Database(SAD)と呼ぶ。

SAには以下のパラメータがある。

カウンタ セキュリティ・プロトコルが使われたパケットを受信した時に、受信者はどのSAが 使われていたかを知る必要がある。このためにSPIと呼ばれる識別子が パケットに含まれている。受信者はこのSPIからSAを特定できる。 通信する相手は1つではないので、SPIは受信者の中では一意になっている必要が ある。したがってパケットの受信者がSPIを決める。 SPIは、0x100 - 0xffffffffの範囲で、かつセキュリティ・プロトコル内で 重複しなければ、何を使っても構わない。

SPIは受信者が決めるので、SAには方向がある。 セキュリティ・プロトコルを使ったパケットが往復するためにはSAが2つ必要である。 SAはホストの通信のためだけではなく、ネットワークやユーザに対しても使うことが できる。そのために以下のパラメータをSAが適用する範囲として指定することができる。

例えば、2つの組織間をVPNでつなぎたい時はネットワーク・アドレスで識別されるSAを 使う。あるホストとあるサーバ間のHTTPだけを守りたい時は、IPアドレスと トランポート層プロトコル、ポート番号で識別されるSAを使う。 また、より高いセキュリティを確保するために複数のSAをまとめて同時に使ったり、 通信経路に別のSAが存在することもできる。ここで通信経路上にいて中継する パケットにセキュリティを提供するルータを特にセキュリティ・ゲートウェイ(SGW)と 呼ぶ。

さて、送信者がパケットを送信しようとした時、どのセキュリティを適用するか 決める必要がある。またセキュリティは必要ないかもしれない。 これをSecurity Policy(SP)と呼び、SPを管理するデータベースを Security Policy Database(SPD)と呼ぶ。 SPDには、通信する単位を識別する情報が記述されている。 そして、どのセキュリティを適用するかが記述されている。

図1はSPDとSADとパケットの関係を示している。

    v                             ^
    |(1)                       (8)|
    |                             |
    |           +-----+           |
    |----(2)--->| SPD |----(7)--->|
    |           +-----+           |
    |                             |
    |           +-----+           |
    |----(3)--->| SAD |----(6)--->|
    |           +-----+           |
    |                             |
    |(4)                       (5)|
    v                             ^

    図1. SPDとSADとパケットの関係
(1)カーネルがパケットを送出する時は、(2)SPDを検索してIPsecするか決める。 もしIPsecする場合は(3)SADから必要なSAを選択し、そこに定義されたパラメータを 使って必要な処理をパケットに施し(4)送信する。

(5)パケットを受信した時、もしIPsecされていれば(6)セキュリティ・プロトコル番号と SPIにより、SADからSAを選びだしパケットに必要な処理を施す。 そして(7)SPDを検索して十分なセキュリティが適用されていたか検査し、 (8)パケットをトランスポート層へ渡す。

次に、各プロトコルについて説明する。

セキュリティ・プロトコル

ESPやAHには、トランスポート・モードとトンネル・モードの2つのモードが ある。これは各セキュリティ・プロトコルで処理するデータの範囲を示す。 前者はIPのペイロード部分、後者はIPパケット全体がその対象になる。 トンネル・モードは、RFC1853に定義されているIP in IP Tunneling 技術を 利用して、IPパケット全体をペイロードと見なして新たなIPヘッダを付加する。 ESPで使うと限定されたトラフィックフローの秘匿性を提供できるので、 VPNを構築するのに使える。

現在のIPsecの仕様ではAHやESPのトンネル・モードの組合せや、 トランスポート・モードとトンネル・モードの組み合わせを厳密には定義していない。 AHトンネル+ESPトンネル+AHトンネルのようなパケットも許している。 例えば、AHとESPのトンネル・モードを使ってネットワークXとネットワークYの通信を SGW間で守ると言った場合、図2の様な4通りのパケットに解釈できる。

    ネットワークX                      ネットワークY
          |                                   |
          |    +-----+             +-----+    |
          +----|SGW X|==== SA ====>|SGW Y|----+
          |    +-----+             +-----+    |
          |                                   |

    (1) IP2|AH|ESP|IP1|ULP
    (2) IP2|ESP|AH|IP1|ULP
    (3) IP3|AH|IP2|ESP|IP1|ULP
    (4) IP3|ESP|IP2|AH|IP1|ULP

	IP1,IP2,IP3: IPヘッダ
	ULP: 上位層プロトコル

    図2. ESPとAHの組み合わせの例
実際には(1)の形になるように使われているようである。しかし、このパケットの形は ESPトンネル+AHトランスポートとも解釈できる。この様に違う製品同士で IPsecを使う時には注意が必要だ。

ESP

ESPは以下のセキュリティの全て、またはいくつかを組み合わせて提供する。 限定されたトラフィックフローの秘匿性とは、セキュリティゲートウェイ間で パケットを暗号化して、実際に通信している2点間の通信の秘匿性を 提供するものである。これはトラフィック分析に対して弱い耐性があるとも言える。

ESPは、これらのセキュリティを提供するために暗号化アルゴリズムや 認証アルゴリズム、カウンタを使う。 暗号化アルゴリズムはDES-CBCとデバッグ用のNULL暗号が実装必須になっている。 DES-CBCはその強度に問題があるので最近は3DES-CBCに置き換えられている。 また将来的にはAESも追加される予定だ。 認証アルゴリズムは、HMAC-MD5、HMAC-SHA-1。そしてデバッグ用のNULL認証 アルゴリズムが実装必須になっている。

ESPの構成は図3の様になる。

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ----
 |                               SPI                             | ^
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
 |                             カウンタ                          | |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |認証される
 |                                                               | |範囲
 ~                               IV                              ~ |
 |                                                               | |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | -----
 |                        ペイロード・データ                     | |   ^
 ~                                                               ~ |   |
 |                                                               | |   |
 +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 秘匿される
 |               |            パディング                         | | 範囲
 +-+-+-+-+-+-+-+-+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |   |
 |                               |  パディング長 |  次ヘッダ番号 | v   v
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -------
 |                          認証データ(ICV)                      |
 ~                                                               ~
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

  図3. ESPの構成
まずSAを識別するためのSPIがある。特にESPでは元のペイロードを暗号化するので、 パケットを受信した時に上位プロトコル番号やポート番号を知ることができない。 しかしSPIがあるのでSAを特定できる。 次にAnti-replayのためのカウンタがある。これはSAが確立した時に0に初期化され、 送信者はESPの処理をするたびにカウンタを1つ増やす。 受信者はこの番号を調べて、既に届いたパケットかどうかを判断する。 これにより再送攻撃を防ぐ。 次に暗号化アルゴリズムで使う初期ベクトル(IV)がある。 このフィールドは暗号化アルゴリズムにより可変長になる。 SPIとカウンタ、IVを合わせてESPヘッダと呼ぶ。 ペイロード・データはESPが適用される前のIPのペイロードである。 トンネル・モードでは、ここにIPパケットが収まる。 暗号化アルゴリズムによって処理する単位が決まっているので、ペイロードを その単位にそろえる必要がある。そのためにペイロードに埋め合わせの データを付加する。これがパディングである。 そして付加したバイト数をパディング長に入れる。 パディングは、認証データの開始位置を4バイトの境界にそろえる役目もある。 さらに必要ならばESP処理毎にパディングの長さを調節してペイロード・データの 長さを予測させないこともできる。 元のIPペイロードに設定されていた次ヘッダ番号がパディング長に続く。 ペイロード・データとパディング、パディング長、次ヘッダ番号を合わせた部分に 暗号化アルゴリズムを適用してIPペイロードの秘匿性を提供している。

暗号化された部分とSPI、カウンタを合わせた部分に認証アルゴリズムを適用した値を 認証データに入れる。これはIntegrity Check Value(ICV)とも呼ばれる。 受信者はICVを検査して、伝送途中にパケットが改纂されたことを検出する。 これによりIPデータグラムの完全性を提供する。

次にESPがIPパケットのどの位置にあるのかを説明する。 図4は、IPv6においてESPトランスポート・モードを使った時のパケットの構成を 示したものです。IANAはESPにプロトコル番号は50を割り当てているので、直前の ヘッダの次ヘッダ番号には50が入る。

                  ESP適用前
          ------------------------
    IPv6  |IPv6  |IPv6拡張|データ|
          |ヘッダ|ヘッダ  |グラム|
          ------------------------
    
                  ESP適用後
          --------------------------------------------------------------
    IPv6  |IPv6  |IPv6拡張|ESP   |IPv6拡張|データ|ESP       |ESP       |
          |ヘッダ|ヘッダ1 |ヘッダ|ヘッダ2 |グラム|付加データ|認証データ|
          --------------------------------------------------------------
                                 |<--------- 暗号化される範囲 -------->|
                          |<------------- 認証される範囲 ------------->|

    図4. IPv6におけるESPトランスポート・モード
IPv6拡張ヘッダ1は、経路上のルータが処理するヘッダである。 例えばIPv6 Hop-by-hopオプションがある。またフラグメントされたパケットは 再構成された後にESPの受信処理をするきまりになっているので、 IPv6 フラグメント・オプションもこれに相当する。 IPv6拡張ヘッダ2は、終点で処理するヘッダである。 図4から分かる様にIPv6ヘッダとIPv6拡張ヘッダ1には認証が適用されていない。 つまりESPではIPヘッダと一部のIPv6拡張ヘッダを守れない。

AH

AH は以下のセキュリティのいくつか、または全てを組み合わせて提供する。 これらのセキュリティを提供するためにAHは認証アルゴリズムとカウンタを使う。 AHでは認証アルゴリズムとしてHMAC-MD5とHMAC-SHA-1を実装必須にしている。 暗号化アルゴリズムは使われないので、秘匿性は提供できない。

AHヘッダは図5の通りである。

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  次ヘッダ番号 |    ヘッダ長   |         予約フィールド        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                              SPI                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                            カウンタ                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   +                         認証データ(ICV)                       |
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

	図5. AH ヘッダの構成
IANAはAHにプロトコル番号は51を割り当てている。 まず、AHの次に来るヘッダの番号が次ヘッダ番号に入る。 次にAHヘッダのバイト単位の長さを4で割って2を引いた数がヘッダ長として 置かれる。2を引くのはIPv6オプションヘッダの規則に合わせたからである。 例えば、AHヘッダが16バイトならば、2がヘッダ長になる。 予約フィールドは0で埋めなければいけない。 そしてSAを識別するためのSPI、続いてAnti-replayのためのカウンタが置かれる。

ICVはIPパケット全体に認証アルゴリズムを適用した値である。 ESPと違い、ICVの計算対象にはIPヘッダやIPオプションが含まれるので、 IPデータグラムだけではなくIPヘッダの完全性も提供される。

IPヘッダの中には伝送途中に値が変わるフィールドが存在する。 これでは受信者がICVを検査しても改纂されていたのか、それとも正しい値なのか 判断できない。そのためにAHでは伝送途中に値が変わるフィールドはICVの値に 関係しないようにする。この様なフィールドには以下がある。

	IPv4:
		Type of Service (TOS)
		Flags
		Fragment Offset
		Time to Live (TTL)
		Header Checksum
	IPv6:
		Class
		Flow Label
		Hop Limit
		配送経路上変更可能ビットが立っているオプション
送信者は、ICVを計算するために、これらのフィールドを一時的に0にしてから 計算する。 受信者も同様にしてICVを検査して、伝送途中に変わるフィールドに関係なく 完全性を検証し認証できる。

鍵管理

SAを確立するためには、通信する2つのノード間でそのパラメータを共有しなければ ならない。そして、暗号アルゴリズムで使う鍵は部外者に知られては困るので、 安全に共有する必要がある。 IPsecでは、その方法として手動鍵管理と自動鍵管理を定義している。

手動鍵管理とは、フロッピディスクやマスターカードなどのネットワークを使った 通信以外の手段を用いて管理者同士がパラメータを共有する方法である。 これは実装も単純で簡単に実現できるが、以下のような場合に限界がある。

ポート番号単位のSAを必要としている環境では、新たなセッションが始まるたびに ポート番号を調べてパラメータを交換しなけれならないので、手動鍵管理ではおよそ 不可能である。またIPアドレス単位のSAでも、通信する計算機が増加すれば、 それだけ管理する手間もかかるので限界がある。 例えSAが1つだけだとしても、それが頻繁に確立と消滅が繰り返されるのであれば、 これも管理するのは不可能である。 また、ESPやAHではカウンタを使ってAnti-replayを実現している。 カウンタが1巡した時にはSAを再設定することになっているが、手動鍵管理を 使うとカウンタが1巡したかどうか管理者が見張っていなければならない。 それは非常に煩わしく不可能に近いので、結果的にAnti-replayを利用できない。 したがって手動鍵管理を導入できる環境としては以下の条件が考えられる。

IKE

手動鍵管理の制約に縛られないために、自動でパラメータを交換する仕組みが 必要である。 IPsecでは The Internet Key Exchange(IKE)と呼ばれる仕組みを実装必須になっている。 これ以外にも、Simple Key-Management For Internet Protocols(SKIP)や Photurisなどがあるが、ここでは割愛する。 IKEは仕様に曖昧な記述が多いために、またその安全性に問題が指摘されているので 新しい仕様が出る予定になっている。ここでは現在の仕様を元に説明する。

IKEはInternet Security Association and Key Management Protocol(ISAKMP) とOAKLEYを基に定義されている。ISAKMPは、SAに関係するパラメータを、 認証付きで交換するための枠組である。 IKEで交換する個々のパラメータはIPsec Domain Of Interpretation(DOI) に定義されている。

IKEはUDPのポート番号500を使ってパラメータを交換するが、その通信を守るために IPsecを使うと鶏と玉子問題になるのでIPsecのSAは使わない。 そのためにIPsecで使うSAとは別のSAを独自に確立している。 またIKEで使うSAには、IPsecのSAの様な方向性はない。1つのSAを双方向の通信で使う。 以降ではESPやAHのためのSAをIPsec-SAとし、IKEのためのSAはIKE-SAと表す。 そして、IKE-SAを確立する部分をフェーズ1と呼び、 IKE-SAの下でIPsec-SAのパラメータを交換する部分をフェーズ2と呼ぶ。

IKEパケットは、IKEヘッダとIKEペイロード(図6)から構成される。

                             1                   2                   3
         0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                                                               |
        |                                                               |
        +                            クッキー                           +
        |                                                               |
        |                                                               |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |次ペイロード番号|  バージョン  |    交換方式   |     フラグ    |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                        メッセージ識別子                       |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                           パケット長                          |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                             1                   2                   3
         0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |次ペイロード番号|予約フィールド|          ペイロード長         |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                            データ                             |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

	図6. IKEヘッダとIKEペイロード
IKEヘッダには、IKE-SAを識別するためのクッキーと呼ばれる16バイトの フィールドがある。前半8バイトは始動者が、後半8バイトは応答者がそれぞれ決める。 IKEは、それぞれのフェーズの中で、始動者がIKE-SAに必要なパラメータの組(Proposal) を複数提案し、応答者はその中から1つのProposalを選択する。 またそれ以外にも多くの情報を交換する必要がある。 そのためにIKEヘッダとIKEペイロードのヘッダ部には、次ペイロード番号が存在し 各ペイロードを数珠つなぎにできる。 次ペイロード・フィールドが0ならば、そのペイロードが数珠つなぎの最後を意味する。 次にIKEのバージョンを示すフィールドがある。前半4ビットがメジャー番号。 後半4ビットがマイナー番号になっている。現在のバージョンは1.0である。 IKEにはIKE-SAを交換する方式がいくつか用意されている。またエラー情報を 送信するパケットも定義されてる。これらを識別するために交換方式フィールドを 使う。 フラグは、パケットが暗号化されているかどうかを判断するために使う。 フェーズ2は、複数のIPsec-SAを交換できるので、 それらを識別するためにクッキーに加えてメッセージ識別子(Mid)を使う。 パケット長はIKEヘッダとIKEペイロードを合計したバイト数が入る。

フェーズ 1

フェーズ1は、IKE 同士の通信を安全にするために IKE-SA を確立するフェーズである。 交換する方法はメイン・モードとアグレッシブ・モードの2つが定義されている。 ベース・モードというのもあるが、ここでは割愛する。

フェーズ1では、IKE-SAを確立するために、暗号化アルゴリズム、認証方式、 ハッシュ方式、IKE-SAの生存期間を交換する。 暗号アルゴリズムで使う鍵を計算するための元となる情報の交換には Diffie-Hellman鍵交換方式(DH)を採用している。このために巨大な素数を予め 知る必要がある。IKEでは素数を交換する代りに素数にグループと呼ばれる番号を 付与して、それを交換する。 認証方式として電子署名、公開鍵暗号、Pre-shared keyの3つが定義されていて、 通信するIKE同士がどれか1つを合意し使う。

図7はPre-shared key認証方式を使ったメイン・モードのパケットの流れである。

      始動者                     応答者
      ----------                 -----------
      HDR, SA(複数可)     -->
                          <--    HDR, SA
      HDR, KE, Ni         -->
                          <--    HDR, KE, Nr
      HDR*, IDii, HASH_I  -->
                          <--    HDR*, IDir, HASH_R

        HDR: IKEヘッダ
        SA: SAパラメータ
        KE: DH公開情報
        Ni,Nr: 乱数値
        IDii,IDir: 自己情報
        HASH_I,HASH_R: ハッシュ値

    図7. Pre-shared key認証方式を使ったメイン・モード
始めに始動者はIKE-SAのProposalをいくつか相手に送信する。 応答者はこの中から相応しいProposalを1つだけ選んで返する。 次に互いに、DHの公開情報と乱数値を相手に送信する。 この時点でDHの秘密情報を計算し、その情報とPre-shared keyから 乱数値から暗号アルゴリズムに使う鍵を計算する。 鍵の計算ができたので、これ以降の通信はIKE-SAに守られる。 この後、自己情報とハッシュ値を送信してフェーズ1は終了する。 ハッシュ値は、モードごとに定義された計算方法を使う。 前述した安全性の問題とは、このハッシュ値の計算方法にある。 自己情報には、IPアドレス、メールアドレス、ホスト名等が使える。 これは通信相手を認証するために使う。

図8は同じくPre-shared key認証方式を使った、アグレッシブ・モードの場合である。

      始動者                             応答者
      ----------                         -----------
      HDR, SA(複数可), KE, Ni, IDii -->
                                    <--  HDR, SA, KE, Nr, IDir, HASH_R
      HDR, HASH_I                   -->

        HDR: IKEヘッダ
        SA: SAパラメータ
        KE: DH公開情報
        Ni,Nr: 乱数値
        IDii,IDir: 自己情報
        HASH_I,HASH_R: ハッシュ値

    図8. Pre-shared key認証方式を使ったアグレッシブ・モード
メイン・モードではIKE-SAを確立した後に自己情報を交換するので保護できるが、 アグレッシブ・モードでは、最初に交換するので保護できない。 ただし、認証方式に公開鍵暗号を使うと自己情報の保護が可能になる。 フェーズ1では最初にIKE-SAのパラメータの交換をするので、通信相手毎に パラメータを変えたいとすると、フェーズ1の最初のパケットを受け取った時に 相手を特定する必要がある。IPアドレスが固定ならば、パケットの送信元IPアドレスを 使って相手を特定できる。しかし、IPアドレスが不定な相手ならば、それを特定する 目的でIPアドレスを使えない。そのためには自己情報が変わりに使えそうだが、 メインモードは最後にそれを交換するので、これも使えない。 このためPre-shared key認証方式を使う場合、IPアドレスが不定な相手とは アグレッシブモードを使う。 またアグレッシブ・モードは、メイン・モードに比べて交換する回数が少ないため 時間を短縮するためにも使われる。

フェーズ 2

フェーズ2は、フェーズ1で確立したIKE-SAの下で、IPsec-SAのパラメータを 交換するフェーズである。クィック・モードと呼ばれる方式が定義されている。 1つのIKE-SAを使って、複数のIPsec-SAのパラメータの交換ができるが、 Perfect Forward Securecy(PFS)の度合によっては、1つのIKE-SAで1つのIPsec-SAしか 交換しない場合もある。 また、交換するパラメータにはIPsec-SAの方向の区別がない。つまりIKEを使うと 双方向に同じセキュリティ・プロトコルと暗号化アルゴリズムが設定される。

図9はクイック・モードのパケットの流れである。

      始動者                               応答者
      ----------                           -----------
      HDR, HASH(1), SA(複数可), Ni,  -->
                    KE, IDci, IDcr
                                     <--   HDR, HASH(2), SA, Nr
                                                 KE, IDci, IDcr
      HDR, HASH(3)                   -->

        HDR: IKEヘッダ
        HASH(1),HASH(2),HASH(3): ハッシュ値
        SA: SAパラメータ
        Ni,Nr: 乱数値
        KE: DH公開情報
        IDci,IDcr: IPsec-SAの識別子

    図9. クイック・モード
始動者は、IPsec-SAのProposalをいくつかと、乱数値、DHの公開情報、 IPsec-SAの識別子を送る。この時、自分向きのIPsec-SAのSPIも送る。 応答者はこの中から相応しいProposalを1つだけ選んで返す。 この時にもやはり自分向きのIPsec-SAのSPIを返す。 PFSが必要ない時は、DHの公開情報を送る必要はない。 またトランスポート・モードのIPsec-SAを交換する場合、IPsec-SAの識別子を 省略できる場合もある。 それぞれのパケットには完全性を高めるために交換する情報を基にハッシュ値 を計算し含めている。

KAMEプロジェクトのIPsecスタック

IPsecの商用実装は1996年頃からでてきていたが、仕様を全て満たしていなかったり、 一般のユーザには意識しづらい所で使われていた。 非商用実装は当時からあったが容易に利用できる形で配布されていたとは言えなかった。 また、これらはいずれもIPv4に限定されたものだった。

KAMEプロジェクトはIPv6の普及を目的として1998年に結成され、ここで開発した ソフトウエアを世界中に配布してきた。IPv6ではIPsecを実装必須にしているので、 このプロジェクトではIPsecも同様に開発を進めてきた。 開発当初からBSD/OS,FreeBSD,NetBSDに対するパッチを配布しているが、 FreeBSDには4.0から、またNetBSDには1.5から標準で入っている。

KAMEプロジェクトが開発したIPsecスタック(以降では、これをKAMEスタックと呼ぶ) はFreeBSD4.0以降, NetBSD1.5, BSD/OS4.2に入っている。(注1) (注1: OpenBSDは独自のIPsecスタックを持っているので、KAMEプロジェクトの それは使っていない。IPv6スタックは入っている。) IPsecは全体としては今だ発展途中の技術なので、KAMEプロジェクトもそれを追従して 開発を進めている。最新のキットはhttp://www.kame.net/から配布されている。

KAMEスタックの大きな特徴は何と言ってもIPv6でも使えることである。 また新旧仕様をサポートしている。 SAを適用する範囲は、ネットワーク単位、ホスト単位、ネットワークサービス単位、 ソケット単位を設定できる。 AH,ESPともにトンネル・モード、トランスポート両方をサポートしていて、 2つのプロトコルと2つのモードは何重にも自由に組み合わせられる。

以下はサポートしている暗号アルゴリズムの一覧である。

認証アルゴリズム: HMAC-MD5, HMAC-SHA1, KEYED-MD5, KEYED-SHA1
暗号化アルゴリズム: DES-CBC, 3DES-CBC, BLOWFISH-CBC, CAST128-CBC, RIJNDAEL-CBC, TWOFISH-CBC また、デバッグ用にAHのICVなしや、ESPの暗号化なしもサポートしている。

SAD,SPDの操作にはsetkeyを使う。SADの操作は PF_KEY Key Management API, Version 2(PFKEYv2)に準拠しているが、 SPDの操作は仕様が定まっていないので独自実装している。 IKEはracoonと呼ばれるデーモンとして実装している。 またソケット単位のSAを使うための関数libipsecを提供している。

KAMEスタックのSPDにはパケットにIPsecを適用するかどうか、そしてどのIPsec-SAを 使うかを記述する。IPsec-SAの組み合わせは自由に設定できるので、 AHトランスポート+AHトランスポート+AHトランスポートと言うパケットも作れる。 図10に、IKEを使った場合に、KAMEスタックがパケットにIPsecを適用するまでの流れを 示す。

         setkey                racoon  <-------(IKE)-------> somebody
           |                    ^  |      (5)
           |                    |  |(6)
           |(1)           +-----+  +---+
           |           (4)|            |
           v              |            v
        +-----+  (2)      |    (3)  +-----+
        | SPD |<----- kernel ------>| SAD |
        +-----+         |           +-----+
                        |(7)
                        v

	図10. KAMEスタックのIKE
  1. 管理者はsetkeyを使って、どのパケットにIPsecを使うかをSPDに登録する。
  2. カーネルはSPDを検索してパケットにIPsecを適用するかどうかを判断する。
  3. IPsecを適用すると分かったら、SADを検索して対応するIPsec-SAのパラメータを 取得する。
  4. 鍵情報がなかった場合、racoonへIPsec-SAの確立要求をする。
  5. racoonはIPsec-SAを確立すべき相手とIKEを使ってパラメータを交換する。
  6. racoonは交換したパラメータを SADに登録する。

上記(4)から(6)までの間、KAMEスタックはIPsec-SAが設定されるまで パケットを単に捨てる。再送は上位のプロトコルに任せている。

KAMEスタックの使い方

まず、はじめにIKEを使わない方法から説明する。

IKEを使わないのでSAはsetkeyを使って設定する。 setkeyはSAを操作する構文を記述したファイルを読み込んで 設定や削除、SADを表示できる。 また構文は標準入力からも読む込める。

SAを設定する構文は以下の通りである。

	add 送信元IPアドレス 受信先IPアドレス セキュリティ・プロトコル SPI
		アルゴリズムの定義 ...
アルゴリズムの定義はセキュリティ・プロトコルによって書き方が変わる。 ESPの場合は暗号アルゴリズムと認証アルゴリズムを定義しなければいけないので、 この定義の部分は以下の様になる。
	-E 暗号アルゴリズム 鍵 -A 認証アルゴリズム 鍵
例えば、ホストAとサーバBのHTTPの通信に秘匿性を持たせるとする。 IPアドレスはそれぞれ、3ffe:501:ffff::1, 3ffe:501:ffff::2とする。 秘匿性を持たせるのでセキュリティ・プロトコルはESPを使う。 また、トラフィックフローの秘匿性は必要ないのでトランスポート・モードを、 暗号アルゴリズムはblowfish、認証アルゴリズムはHMAC-SHA1を使う。 blowfishに使う鍵は文字列で"1234567812345678"、 HMAC-SHA1に使う鍵は文字列で"12345678123456781234"とする。 双方向の通信をするためには2つのSAが必要なことに注意すると、 ホストAのSAの定義は以下の様になる。
	add 3ffe:501:ffff::1 3ffe:501:ffff::2 esp 0x1111
		-E blowfish-cbc"1234567812345678"
		-A hmac-sha1 "12345678123456781234" ;

	add 3ffe:501:ffff::2 3ffe:501:ffff::1 esp 0x1112
		-E blowfish-cbc"1234567812345678"
		-A hmac-sha1 "12345678123456781234" ;
SAのSPIは、他の自分向きのIPsec-SAのSPIと重複しない値を選ぶ。 最後のセミコロン(';')は文の最後を示す文字である。 これをsa.confに保存して、以下のようにしてsetkeyを使ってSAを設定する。
	% setkey -f sa.conf
setkey -Dを使うと現在のSADを確認できる。 サーバBでもSAの定義は同様である。

以下の暗号アルゴリズムは、その安全性を保証するために鍵を 固定長にしなければいけないので、設定する鍵の長さに注意する。

	algorithm       key length (ビット)
	------------    -----------
	hmac-md5        128
	hmac-sha1       160
	keyed-md5       128
	keyed-sha1      160
	des-cbc         64
	3des-cbc        192
	rijndael-cbc    128/192/256
さて、SAを使うためにはSPDが必要である。 SPDを設定するにもsekteyを使う。

構文は以下の通りである。

	spdadd IPアドレスによる識別子 上位プロトコル番号 -P 方向 動作
IPアドレスによる識別子には、IPアドレス、プレフィクス、ポート番号を記述する。 ここに対応するパケットが方向で示される処理をする時にどうするかを動作に 記述する。動作には、以下が記述できる。
	none
	discard
	ipsec セキュリティ・プロトコルの宣言 ...
noneはIPsecに関しては何もしないことを意味する。 discardは対応するパケットを捨てる。 最後のipsecがIPsecすることを意味する。

ipsecの後には、どのセキュリティ・プロトコルを使うか指定する。 セキュリティ・プロトコルの宣言は複数書ける。 個々の宣言の構文は、以下の通りである。

	セキュリティ・プロトコル/モード/SAの両端のIPアドレス/レベル
セキュリティ・プロトコルにはespまたはahを指定する。 モードはtunnelかtransportを指定する。 トランスポート・モードを使う場合は、SAの両端のIPアドレスを省略できる。 レベルには use, require, uniqueが指定できる。 それぞれの意味は以下の通りである。
	パケット送信時
	use     | IPsec-SAがあれば使う。なければ通常処理しつつIKEへ要求する。
	require | IPsec-SAがなければ、パケットを捨ててIKEへ要求する。
	unique  | requireに加えて、一意なIPsec-SAを要求する。

	パケット受信時
	use     | IPsecされてなくても受信する。
	require | IPsecされていなければパケットを破棄する。
	unique  | 一意なIPsec-SAが使われていなければ破棄する。
では、ホストAでのSPの定義をしてみる。
	spdadd 3ffe:501:ffff::1 3ffe:501:ffff::2[80] tcp -P out ipsec
		esp/transport//require;

	spdadd 3ffe:501:ffff::2[80] 3ffe:501:ffff::1 tcp -P in ipsec
		esp/transport//require;
これをpolicy.confに保存してsetkeyを使って設定する。 方法はSAの設定の時と同じである。
	% setkey -f policy.conf
setkey -DPを使ってSPDを確認できる。 次に、ホストB側も同様に、SPの方向に注意して設定する。 これでホストAとホストBの通信は全てESPが使えるようになる。

別の例を試してみよう。今度は組織Pと組織QがVPNを構築することを考える。 セキュリティゲートウェイのIPアドレスはそれぞれ 3ffe:501:ffff:10::1, 3ffe:501:ffff:20::2とする。 組織内のネットワークアドレスはそれぞれ、 3ffe:501:ffff:11::/64, 3ffe:501:ffff:22::/64とする。 VPNなので通信には秘匿性が必要である。モードはトンネル・モードを使う。 またセキュリティゲートウエイが作るIPヘッダにも認証を必要とする。 このためにESPとAHを使う。 暗号アルゴリズムは3DES、認証アルゴリズムはHMAC-SHA1を使う。 3DESに使う鍵は文字列で"123456781234567812345678"、 HMAC-SHA1に使う鍵は文字列で"12345678123456781234"とする。

組織Pのセキュリティゲートウェイでは以下の様な設定をする。

% cat sa.conf
add 3ffe:501:ffff:10::1 3ffe:501:ffff:20::2 esp 0x1000 
	-E 3des-cbc "123456781234567812345678"
	-A hmac-sha1 "12345678123456781234";

add 3ffe:501:ffff:20::2 3ffe:501:ffff:10::1 esp 0x1000 
	-E 3des-cbc "123456781234567812345678"
	-A hmac-sha1 "12345678123456781234";

add 3ffe:501:ffff:10::1 3ffe:501:ffff:20::2 ah 0x1000 
	-A hmac-sha1 "12345678123456781234";

add 3ffe:501:ffff:20::2 3ffe:501:ffff:10::1 ah 0x1000 
	-A hmac-sha1 "12345678123456781234";

% cat poliy.conf
spdadd 3ffe:501:ffff:11::/64 3ffe:501:ffff:22::/64 any -P out ipsec
	esp/tunnel/3ffe:501:ffff:10::1-3ffe:501:ffff:20::2/require
	ah/transport//require;

spdadd 3ffe:501:ffff:22::/64 3ffe:501:ffff:11::/64 any -P in ipsec
	esp/tunnel/3ffe:501:ffff:20::2-3ffe:501:ffff:10::1/require
	ah/transport//require;

racoon

次にIKEを使った場合を説明する。 そのためにはracoonを使う。 racoonは開発途中なのでportsで提供しているが、KAMEプロジェクトが定期的に 出しているキットをインストールすると、racoonもインストールされる。 racoonは暗号アルゴリズムを全てOpenSSLに任せているので、OpenSSL0.9.5aを インストールする必要がある。

racoonには多くのパラメータがあるが、ここでは抜粋して説明する。 図11は認証方式のpre-shared key方式を使った場合の設定例である。

        # cat case1.conf
        path pre_shared_key "/usr/local/v6/etc/psk.txt" ;

        remote 3ffe:501:ffff::2
        {
                exchange_mode main ;
		my_identifier user_fqdn "sakane@kame.net" ;
		peers_identifier fqdn "mine.kame.net" ;
                lifetime time 24 hour ;
                proposal {
                        encryption_algorithm 3des;
                        hash_algorithm sha1;
                        authentication_method pre_shared_key ;
                        dh_group 2 ;
                }
        }

        sainfo address 3ffe:501:ffff::1 tcp address 3ffe:501:ffff::2[80] tcp
        {
                pfs_group 2;
                lifetime time 12 hour ;
                lifetime byte 50 MB ;
                encryption_algorithm blowfish ;
                authentication_algorithm hmac_sha1 ;
                compression_algorithm deflate ;
        }

	図11. 設定例
この設定例について、上から順番に説明する。

path pre_shared_keyはPhase 1のPre-shared Key方式で使う情報を記述している ファイルを示する。認証方式としてPre-shared Key方式を使わない場合は 設定しなくてよい。このファイルのフォーマットは/etc/hostsと同様に 行の先頭に識別子を書いて、空白文字で区切り、続いて鍵を記述する。 この識別子と鍵のペアを複数書く時は改行する。

フェーズ1を設定するためにremoteを使いIPアドレスを記述する。 相手を特定しない時はremote anonymousとする。 exchange_modeはフェーズ1のモードを設定する。aggressiveは、 アグレッシブ・モードで通信することを意味する。 メインを使う時はmainと記述する。 ここに設定したモード以外で相手が通信しようとすると拒否する。 始動者としてはメイン・モードを使うが、応答者としてはアグレッシブ・モードも 許す時は、exchange_mode main,aggressiveと記述する。 my_identiferは、自己情報を記述する。この情報を相手に送信して、認証情報の 一つとして使う。例では、タイプとしてユーザFQDNを使っている。 自己情報はIPアドレス、ユーザFQDN、FQDN等が使える。IPアドレスを使う時は 省略できる。ユーザFQDNとFQDNの時はそれぞれuser_fqdn, fqdnと記述し、 続けてdouble quotation(")で囲まれた文字列を書く。 peers_identiferには、相手の自己情報を設定する。上記の場合、fqdnとして "mine.kame.net"が送られてくることを期待している。 lifetime timeは、IKE-SAの有効時間を設定する。 有効期間の単位としては sec, min, hourが使える。 proposalはフェーズ1で使うパラメータの組を設定する。複数の組を記述する時は、 proposalを複数書く。 encryption_algorithmは暗号化アルゴリズムを設定する。暗号化アルゴリズム としてはDES-CBC, 3DES-CBC, RC5-CBC, IDEA-CBC, CAST-CBC, BLOWFISH-CBCが使える。 それぞれdes, 3des, rc5, idea, cast, blowfishと記述する。 hash_algorithmはハッシュアルゴリズムを設定する。ハッシュアルゴリズム としては MD5, SHA1が使える。それぞれ md5, sha1として記述する。 authentication_methodは認証方式を設定する。例ではPre-shared Key方式を 意味する。他に証明書を使った認証方式も使えるがここで説明を省く。 dh_groupはDHのグループを設定する。グループとして、1, 2, 5が使える。 それぞれ 1, 2, 5と記述する。

フェーズ2の設定にはsainfoを使う。sainfoの後にIPsecを識別する情報を 記述する。例ではIPアドレスを使っている。この情報はSPの識別子と一致する 必要がある。例外としてanonymousがある。これは全ての識別子に一致する。 pfs_groupはフェーズ2でPFSが必要な時に使うDHのグループを設定する。 グループとして、1, 2, 5が使える。それぞれ 1, 2, 5として設定する。 lifetime timeとlifetime byteは、それぞれ時間とバイト数によるIPsec-SAの 有効期間を設定する。有効期間の単位はフェーズ1のそれと同じである。 有効バイト数の単位としては B, KB, MB, TBが使えるが、1024B以上を指定しなければいけない。 encryption_algorithmはESPで使う暗号化アルゴリズムの候補を設定する。 暗号化アルゴリズムとしては DES-CBC, 3DES-CBC, RC5-CBC, CAST-CBC, BLOWFISH-CBC, NULLが使える。それぞれ des, 3des, rc5, idea, cast, blowfish, null_encと 記述する。 authentication_algorithmはESPまたはAHで使う認証アルゴリズムの候補を設定する。 認証アルゴリズムとしては HMAC-SHA1, HMAC-MD5, Keyed-MD5が使える。それぞれ hmac_sha1, hmac_md5, kpdkと記述する。 compression_algorithmはIPcompで使う圧縮アルゴリズムの候補を設定する。 encryption_algorithm、authentication_algorithm、compression_algorithmは 省略できない。これらはを実際に使うかどうかはSPに書かれた セキュリティ・プロトコルに依存する。

簡単な設定例

前述したホストAとサーバBのHTTPの通信にIKEを導入してみる。 ホストAのracoonの設定は図11がそのまま使える。 サーバBの設定を図12に示する。
        # cat case1.conf
        path pre_shared_key "/usr/local/v6/etc/psk.txt" ;

        remote 3ffe:501:ffff::1
        {
                exchange_mode main ;
		my_identifier fqdn "mine.kame.net" ;
		peers_identifier user_fqdn "sakane@kame.net" ;
                lifetime time 24 hour ;
                proposal {
                        encryption_algorithm 3des;
                        hash_algorithm sha1;
                        authentication_method pre_shared_key ;
                        dh_group 2 ;
                }
        }

        sainfo address 3ffe:501:ffff::2[80] tcp address 3ffe:501:ffff::2 tcp
        {
                pfs_group 2;
                lifetime time 12 hour ;
                lifetime byte 50 MB ;
                encryption_algorithm blowfish ;
                authentication_algorithm hmac_sha1 ;
                compression_algorithm deflate ;
        }

	図12.
それぞれのracoonの設定ファイルを racoon.confとして保存しておく。

Pre-shared keyには "hoge"を使う。それぞれ次の様に設定する。

	ホストA
	# cat /usr/local/v6/etc/psk.txt
	3ffe:501:ffff::2 hoge

	サーバB
	# cat /usr/local/v6/etc/psk.txt
	3ffe:501:ffff::1 hoge
さて、racoonを起動するにはルート権限が必要である。 以下のような起動オプションがある。
	-f configfile
	  設定ファイルを指定する。初期値は、/usr/local/v6/etc/racoon.conf
	  
	-l logfile
	  ログファイルを指定する。指定されなければ syslog(8)へ出力する。
	  
	-d
	  デバッグモードで起動する。

	-F
	  デーモンにならずに起動する。
ホストA、サーバBで以下のように起動しておく。
	# racoon -f racoon.conf
次にSPDも必要だが、これは手動設定の時に使ったpolicy.confがそのまま使える。

この状態でHTTPのセッションを開始するとIKEの交換が始まり、 しばらくするとIPsec-SAが設定されてHTTPの通信が始まる。 もしうまくいかない時は、以下の様に起動すると非常に多くの情報が標準出力に 表示されるので、何が起きているのかわかるかもしれない。

	# racoon -F -d

さいごに

今回は、IPsecの概要とKAMEプロジェクトのIPsecスタックの概要を説明した。 そしてFreeBSD3.5でのIPsecの使用方法を例と共に説明した。 IPsecは名前こそ有名だが、まだまだ個人で使っている人は少ないのではないだろうか? 今回の記事をきっかけにユーザが増えることを期待する。

参考文献