25.3. IPv6/IPsec の実装

原作: 井上 良信 , 2000 年 3 月 5 日.

訳: 日野 浩志 , 2001 年 3 月 19 日.

訳注: 訳語については "IPv6 次世代インターネット・プロトコル", クリスチャン・ウイテマ著, 村井純監修, WIDE プロジェクト IPv6 分科会監訳, 松島栄樹訳, 1997, ISBN4-88735-010-4 を参考にさせていただきました.

本章では, IPv6 と IPsec に関連する実装の詳細について説明します. これらの機能は KAME プロジェクトの成果を取り込んだものです.

25.3.1. IPv6

25.3.1.1. 規格適合性

わたしたちの IPv6 関連の機能は, 最新の IPv6 仕様に準処してい るか, または準処しようと努力しています. 今後の参考のために以下 に参考文献を挙げておきます (: これ は完全なリストではありません - それを維持するのは大変ですか ら...).

詳しくは, 本文書の各章や, RFC, マニュアル ページ, そしてソースコード中のコメントを参照してください.

規格適合テストは, TAHI プロジェクトにより KAME STABLE kit に対して行われました. その結果は, http://www.tahi.org/report/KAME/ で見ることができます. わたしたちはまた, ニューハンプシャー大学で行われた IOL テスト (http://www.iol.unh.edu/) に以前のバージョンで参加したこともあります.

  • RFC1639: FTP Operation Over Big Address Records (FOOBAR) (大きなアドレスレコードを用いる FTP 操作)

    • RFC2428 は RFC1639 よりも推奨されます. FTP クラ イアントは, まず RFC2428 を試し, もしそれが失敗したな ら RFC1639 を試します.

  • RFC1886: DNS Extensions to support IPv6 (IPv6 をサポー トするための DNS 拡張)

  • RFC1933: Transition Mechanisms for IPv6 Hosts and Routers (IPv6 ホストおよびルータのための移行機構)

    • IPv4 互換アドレスはサポートされません.

    • 自動トンネリング (RFC の 4.3 で述べられています) はサポートされません.

    • gif(4) インタフェースは IPv[46]-over-IPv[46] トンネルを包括的な方法で実装しており, それは仕様で述べ られている "configured tunnel (構成されたトンネル)" を カバーしています. 詳細は本文書の 23.5.1.5をご覧ください.

  • RFC1981: Path MTU Discovery for IPv6 (IPv6 における 経路 MTU 探索)

  • RFC2080: RIPng for IPv6 (IPv6 のための RIPng)

    • usr.sbin/route6d がこれをサポートしています.

  • RFC2292: Advanced Sockets API for IPv6 (IPv6 のため の拡張ソケット API)

    • サポートされているライブラリ関数やカーネルの API については, sys/netinet6/ADVAPI をご覧ください.

  • RFC2362: Protocol Independent Multicast-Sparse Mode (PIM-SM) (プロトコル独立マルチキャスト - 疎モード (sparse mode))

    • RFC2362 は PIM-SM のパケットフォーマットを定義し ています. draft-ietf-pim-ipv6-01.txt はこれ に準じて書かれています.

  • RFC2373: IPv6 Addressing Architecture (IPv6 アドレス 体系)

    • ノードに必須のアドレス群をサポートし, スコープ要 求に準処しています.

  • RFC2374: An IPv6 Aggregatable Global Unicast Address Format (IPv6 集約可能グローバルユニキャストアドレス形式)

    • 64 ビット長のインタフェース ID をサポートしていま す.

  • RFC2375: IPv6 Multicast Address Assignments (IPv6 に おけるマルチキャストアドレス割り当て)

    • ユーザランドのアプリケーション群は本 RFC で割り 当てられている well-known なアドレスを使用しています.

  • RFC2428: FTP Extensions for IPv6 and NATs (IPv6 と NAT のための FTP 拡張)

    • RFC2428 は RFC1639 よりも推奨されます. FTP クラ イアントは, まず RFC2428 を試し, もしそれが失敗したな ら RFC1639 を試します.

  • RFC2460: IPv6 specification (IPv6 仕様)

  • RFC2461: Neighbor discovery for IPv6 (IPv6 における 近隣探索)

    • 詳しくは本文書の 23.5.1.2 をご覧く ださい.

  • RFC2462: IPv6 Stateless Address Autoconfiguration (IPv6 におけるステートレスアドレス自動設定)

    • 詳しくは本文書の 23.5.1.4 をご覧ください.

  • RFC2463: ICMPv6 for IPv6 specification (IPv6 のため の ICMPv6 仕様)

    • 詳しくは本文書の 23.5.1.9 をご覧ください.

  • RFC2464: Transmission of IPv6 Packets over Ethernet Networks (イーサネット上での IPv6 パケットの転送方式)

  • RFC2465: MIB for IPv6: Textual Conventions and General Group (IPv6 用 MIB: 文字列的変換法と一般グループ)

    • 必要な統計情報はカーネルにより集計されています. 実際の IPv6 MIB サポートは ucd-snmp に対するパッチキッ トとして提供されています.

  • RFC2466: MIB for IPv6: ICMPv6 group (IPv6 用 MIB: ICMPv6 グループ)

    • 必要な統計情報はカーネルにより集計されています. 実際の IPv6 MIB サポートは ucd-snmp に対するパッチキッ トとして提供されています.

  • RFC2467: Transmission of IPv6 Packets over FDDI Networks (FDDI ネットワーク上での IPv6 パケットの転送方式)

  • RFC2497: Transmission of IPv6 packet over ARCnet Networks (ARCnet ネットワーク上での IPv6 パケットの転送方 式)

  • RFC2553: Basic Socket Interface Extensions for IPv6 (IPv6 のための 基本的ソケットインタフェースの拡張)

    • IPv4 射影アドレス (3.7) と IPv6 ワイルドカードバ インドソケットの特別な動作 (3.8) をサポートしています. 詳しくは本文書の 23.5.1.12 をご覧ください.

  • RFC2675: IPv6 Jumbograms (IPv6 巨大パケット)

    • 詳しくは本文書の 23.5.1.7 をご覧ください.

  • RFC2710: Multicast Listener Discovery for IPv6 (IPv6 のためのマルチキャスト受信者探索)

  • RFC2711: IPv6 router alert option (IPv6 ルータ警報オ プション)

  • draft-ietf-ipngwg-router-renum-08: IPv6 におけるルータの再番号付け

  • draft-ietf-ipngwg-icmp-namelookups-02: ICMP による IPv6 名前検索

  • draft-ietf-ipngwg-icmp-name-lookups-03: ICMP による IPv6 名前検索

  • draft-ietf-pim-ipv6-01.txt: IPv6 用 PIM

    • pim6dd(8) は密モード (dense mode) を実装しています. pim6sd(8) は疎モード (sparse mode) を実装しています.

  • draft-itojun-ipv6-tcp-to-anycast-00: IPv6 エニーキャストアドレス向けに TCP 接続を切断

  • draft-yamamoto-wideipv6-comm-model-00

    • 詳細は本文書の 23.5.1.6 を参照してください.

  • draft-ietf-ipngwg-scopedaddr-format-00.txt : IPv6 のスコープ化アドレス形式の拡張

25.3.1.2. 近隣探索

近隣探索はきわめて安定しています. 現在, アドレス検索 (Address Resolution), 重複アドレス検出 (Duplicated Address Detection), 近隣到達不能性検出 (Neighbor Unreachability Detection) がサポートされています. もうすぐ, カーネルに代理近 隣通知 (Proxy Neighbor Advertisement) サポートを加え, 管理者ツー ルとして近隣探索取消要請 (Unsolicited Neighbor Advertisement) を送出するコマンドを加える予定です.

DAD (重複アドレス検出) が重複を検出した場合, そのアドレ スは "重複している" という印が付けられ, syslog にメッセージが 記録されます (そして通常はコンソールに表示されます). "重複して いる" 印は ifconfig(8) で調べることができます. 重複検出の チェックおよび重複状態を解消することは管理者の責任となります. この動作は近いうちに改良するべきです.

いくつかのネットワークドライバは, そうしないようにと指示 された場合でもマルチキャストパケットを自分自身に送り返してしま います (特に無差別 (promiscuous) モードでは). このような状況で は DAD は重複を検出するでしょう. なぜなら DAD を実行するプログ ラムは NS パケットの到着を検出し (それが自ノードが出力したもの であるにもかかわらず) それが重複を表しているとみなすからです. この問題に対処する方法は, sys/netinet6/nd6_nbr.c:nd6_dad_timer() 中の "heuristics" とマー クされた #if 条件のあたりを見てください ("heuristics" 部分のプ ログラムコードは仕様に反していることに注意してください).

近隣探索の仕様 (RFC2461) では, 以下に述べる状況での近隣 情報キャッシュの取り扱いについて記述されていません:

  1. 近隣情報キャッシュが空の時に, 下位層 (リンク層) アド レスを持たない RS/NS/NA/redirect 削除要請パケットを受信

  2. 下位層アドレスを持たない通信メディアにおける近隣情報 キャッシュの取り扱い (IsRouter ビットのために一つの近隣情 報キャッシュエントリが必要です)

一つめの場合については, IETF ipngwg メーリングリストで行 われた議論に基づく対応策を実装しています. より詳しくは, ソース コード中のコメントと, 1999 年 2 月 6 日の (IPng 7155) というメー ルから始まったスレッドを参照してください.

IPv6 における同一リンク上かどうかの判断ルール (RFC2461) は, BSD のネットワークコードが想定している条件と全く異なります. とりあえず, デフォルトルータのリストが空の時には同一リンク上か どうかの判断ルールはサポートしていません (RFC2461 の 5.2 章, 第二文節の最後の文 - この仕様のこの章では何カ所かで "host" と "node" という単語の間違った使い方をしていることに注意).

サービス妨害攻撃と無限ループをさけるために, ND パケット 中のオプションは 10 個だけが受け付けられます. そのため, もし RA に 20 個のプレフィックスを載せたとしても先頭の 10 個のプレ フィックスしか理解されません. もしこのことが問題となるのなら, FREEBSD-CURRENT メーリングリストに質問するか, または sys/netinet6/nd6.c 中の nd6_maxndopt を変 更してください. もし多くの要求があるようなら, この変数を変更す る sysctl 変数を用意できるでしょう.

25.3.1.3. スコープ番号

IPv6 はスコープ化されたアドレスを使います. そのため, IPv6 アドレスにスコープ番号 (リンクローカルアドレスではインタ フェース番号, サイトローカルアドレスではサイト番号) を指定する ことは非常に重要です. スコープ番号が無いと, カーネルにとってス コープ化された IPv6 アドレスは曖昧なものとなり, そしてカーネル はそのパケットを出力するインタフェースを選ぶことができないでしょ う.

ユーザランドのアプリケーションは, スコープ番号またはイン タフェース番号を指定するために, 通常は拡張 API (RFC2292) を使 うべきです. 同様の目的のために, RFC2553 において sockaddr_in6 構造体にsin6_scope_id メンバが定義されています. しかしながら, sin6_scope_id の意味づけは少々曖昧です. もし, あなたが自分のア プリケーションの移植性について気をつけたいのなら, sin6_scope_id ではなく拡張 API を使うことをお勧めします.

カーネル中では, リンクローカルスコープのアドレスに対応す るインタフェース番号は IPv6 アドレスの二番目の 16 ビット語 (三 番めと四番めのバイト) に埋め込まれます. たとえばルーティングテー ブルとインタフェースアドレス構造体 (struct in6_ifaddr) の中で, 以下のような例を見ることができるでしょう:

    fe80:1::200:f8ff:fe01:6317

上で述べたアドレスはリンクローカルなユニキャストアドレス で, それはインタフェース番号が 1 であるネットワークインタフェー スに属するものです. 埋め込まれた番号によって, 複数のインタフェー スに対する IPv6 リンクローカルアドレス群を, 効率的に, かつ少々 のプログラムの対応だけで, 識別することができます.

route6d(8)ifconfig(8) のような, ルーティン グデーモンと設定プログラムは "埋め込まれた" スコープ番号を取り 扱う必要があります. これらのプログラムはルーティング用のソケッ トと (SIOCGIFADDR_IN6 のような) ioctl 群を使います. そしてカー ネル API は二番目の 16 ビット語を書き込んでから IPv6 アドレス を返します. これらの API はカーネル内部構造体を操作するための ものです. これらの API を利用するプログラムは, どちらにしろカー ネル間の違いについて意識する必要があります.

コマンドラインでスコープ化されたアドレスを指定するときに は, (ff02:1::1 や fe80:2::fedc のような) 埋め込まれた形式を * 絶対に* 使わないでください. たぶんこれでは動きません. インタ フェースを指定するコマンドラインオプション (たとえば ping6 -I ne0 ff02::1) を使うときには, 必ず ff02::1 や fe80::fedc のような標準形式を使ってください. 一般的 にいって, コマンドが出力インタフェースを指定するコマンドライン オプションを持っていないのならば, そのコマンドはスコープ化され たアドレスを受け付けることはできないでしょう. このことは IPv6 の, "歯医者のオフィス" をサポートするという前提に反するように 思えるでしょう. この問題に関して, わたしたちは仕様に何らかの改良を 加える必要があると信じています.

いくつかのユーザランドのツールは, draft-ietf-ipngwg-scopedaddr-format-00.txt で文書化されている, IPv6 拡張数値記法をサポートしています. "fe80::1%ne0" というように, 出力インタフェースの名前を使って, パケットを出力するリンクを指定することができます. この方法によっ て, 特に問題なくリンクローカルなスコープ化されたアドレスを指定 することができるでしょう.

あなたのプログラムでこの拡張数値記法を使うためには, getaddrinfo(3), と getnameinfo(3) を NI_WITHSCOPEID をつけて使用する必要があります. 現在の実装では, リンクとインタ フェースとが一対一に対応していることを想定しています. これは仕 様で述べられているよりも強い想定です.

25.3.1.4. プラグ & プレイ

ほとんどの IPv6 ステートレスアドレス自動設定はカーネル中 に実装されています. 近隣探索機能は全てカーネル内に実装されてい ます. ルータ通知 (RA: Router Advertisement) のホストへの入力は カーネル内で実装されています. ルータ要請 (RS: Router Solicitation) の終端ホストからの出力, RS のルータへの入力, そ してルータでの RA の出力はユーザランドで実装されています.

25.3.1.4.1. リンクローカルアドレスと特別アドレスの割り当て

IPv6 リンクローカルアドレスは IEEE802 アドレス (イーサ ネットの MAC アドレス) から生成されます. 各インタフェースに は, そのインタフェースが利用可能になったとき (IFF_UP) に自動 的にリンクローカルアドレスが一つ割り当てられます. 同時に, そ のリンクローカルアドレスに対する直接のルートがルーティングテー ブルに加えられます.

以下に netstat コマンドの出力を示します:

    Internet6:
    Destination                   Gateway                   Flags      Netif Expire
    fe80:1::%ed0/64               link#1                    UC          ed0
    fe80:2::%ep0/64               link#2                    UC          ep0

IEEE802 アドレスを持っていないインタフェース (トンネル インタフェースのような疑似インタフェースや, ppp インタフェー ス) は, できる限り, イーサネットインタフェースなどの他のイン タフェースから IEEE802 アドレスを借用します. もし IEEE802 ア ドレスを持ったハードウェアが一つもなければ, 最後の手段として (MD5(ホスト名)で計算される) 疑似乱数値がリンクローカルアドレ スの元として使われます. もしこれがあなたの用途に合わないなら, リンクローカルアドレスを手動で設定する必要があるでしょう.

もしあるインタフェースで IPv6 を使えない (たとえばマルチ キャストをサポートしない, 等の理由で) ならば, そのインタフェー スにはリンクローカルアドレスは割り当てられません. 詳細は 2 章をご覧ください.

各インタフェースは要請されたマルチキャストアドレスとリ ンクローカルな「全ノード」マルチキャストアドレスに加わります (すなわち, そのインタフェースがつながれたリンク上で, それぞ れ fe80::1:ff01:6317 と ff02::1 です). リンクローカルアドレ スに加え, ループバックアドレス (::1) がループバックインタフェー スに割り当てられます. また, ::1/128 と ff01::/32 が自動的に ルーティングテーブルに追加され, そしてループバックインタフェー スはノードローカルマルチキャストグループである ff01::1 に加 わります.

25.3.1.4.2. ホスト上でのステートレスアドレス自動設定

IPv6 仕様では, ノードは二種類に分類されます: ルータホストです. ルータは他宛のアドレスがついたパケットを転送します. ホストは パケットの転送を行いません. net.inet6.ip6.forwarding によっ て, このノードがルータであるかホストであるかが決定されます (1 ならルータで, 0 ならホストです).

ホストがルータ通知 (Router Advertisement) をルータから 受信すると, ホストはステートレスアドレス自動設定によって自ら を自動設定することができます. この動作は net.inet6.ip6.accept_rtadv によって制御できます (1 にセット されているとホストは自らを自動設定します). 自動設定によって, この受信したインタフェースにネットワークアドレスプリフィック ス (通常はグローバルアドレスプリフィックス) が追加されます. デフォルトルートも同時に設定されます. ルータは定期的にルータ 通知パケットを送出します. 隣接するルータに RA パケットを送出 するよう要求するために, ホストはルータ要請 (Router Solicitation) を送信することができます. 好きなときに RS パケッ トを送出するためには, rtsol コマンドを 使います. また, rtsold(8) デーモンもあります. rtsold(8) は必要なときにはいつでもルータ要請を送出しま す. これは移動体のような使い方 (ノート型やラップトップ型コン ピュータ) をするときにとても調子良く働きます. もしルータ通知 を無視したいのなら, sysctl で net.inet6.ip6.accept_rtadv を 0 にしてください.

ルータでルータ通知を送出するには rtadvd(8) デーモ ンを使います.

IPv6 仕様では, 以下の事柄を想定しており, それらに合致 しないケースに関しては仕様化されていないことに注意してくださ い:

  • ホストだけがルータ通知を待ち受けている

  • ホストは (ループバック以外には) ネットワークインタ フェースを一つだけ持つ

以上のことより, ルータや複数のインタフェースを持つホス トで net.inet6.ip6.accept_rtadv を有効にすることは賢いことで はないことが分かります. 設定を失敗したノードは変な動作をする 可能性があります (経験をしてみたい人のために仕様にあわない設 定も許されています).

sysctl 変数を整理すると:

    	accept_rtadv	forwarding	ノードの役割
    	---		---		---
    	0		0		ホスト (手動で設定された)
    	0		1		ルータ
    	1		0		自動設定されたホスト
    					(仕様ではホストはインタフェー
    					スを一つのみ持つことを想定して
    					いるので, 複数のインタフェース
    					を持つホストの自動設定は想定外)
    	1		1		不正, または実験的
    					(仕様の想定外)

RFC2462 の 5.5.3 (e) には到着した RA プリフィックス情 報オプションの検証ルールが書いてあります. これは悪意のある (または設定を失敗した) ルータが非常に短いプリフィックス生存 期間を通知してくることに対してホストを防御するためのものです. ipngwg メーリングリストで Jim Bound による更新があり (メーリ ングリストアーカイブの "(ipng 6712)" をご覧ください), ここで の実装はこの Jim の更新を取り入れたものです.

DAD と自動設定との関係については, 本文書の 23.5.1.2 をご覧ください.

25.3.1.5. 包括的トンネルインタフェース (Generic tunnel interface)

GIF (包括的インタフェース: Generic Interface) は構成された トンネルのための疑似インタフェースです. 詳細は gif(4) に 述べられています. 現在,

  • v6 in v6

  • v6 in v4

  • v4 in v6

  • v4 in v4

が利用できます. gif インタフェースに物理的な (外側の) 始 点と終点アドレスを割り当てるためには gifconfig(8) を使い ます. 内側と外側の IP ヘッダで同じアドレスファミリを使う (v4 in v4, または v6 in v6) 設定は危険です. 無限段数のトンネルを作っ てしまうようにインタフェースとルーティングテーブルを設定するの はとても簡単だからです.注意してください!

gif は ECN (Explicit Congestion Notification: 明示的輻輳 通知) とともに使えるように設定することができます. ECN との親和 性については 23.5.4.5 をご覧ください. また, 設定方法に関しては gif(4) をご覧ください.

もし IPv4-in-IPv6 トンネルを gif インタフェースを使って 設定しようと思っているなら, gif(4) を注意深く読んでくださ い. gif インタフェースに自動的に割り当てられる IPv6 リンクロー カルアドレスを削除する必要があるでしょう.

25.3.1.6. 始点アドレスの選択

現在の始点選択ルールはスコープ指向です (いくつかの例外も あります - 以下を参照してください). ある終点アドレスに対する始 点 IPv6 アドレスは以下の規則に従って選択されます:

  1. もし始点アドレスがユーザにより明示的に指定 (たとえば拡 張 API を通じて) されていたならば, その指定されたアドレス が使われる.

  2. 出力インタフェース (通常はルーティングテーブルを検索 することにより決定される) にアドレスが割り当てられており, そのアドレスが終点アドレスと同一のスコープを持っているなら ば, そのアドレスが使われる.

    これがもっとも一般的な場合です.

  3. もし上記の場合を満たすアドレスがなかったときには, 送 出するノードが持つインタフェースのうちのどれか一つに割り当 てられているグローバルアドレスを選択する.

  4. もし上記の場合を満たすアドレスがなかったときで, 終 点アドレスがサイトローカルスコープであった場合には, 送出す るノードが持つインタフェースのうちのどれか一つに割り当てら れているサイトローカルアドレスを選択する.

  5. もし上記の場合を満たすアドレスがなかったときは, 終 点に向かっているルーティングテーブルエントリに関連づけられ たアドレスを選択する. これは最後の手段であり, スコープ違反 を引き起こす可能性がある.

たとえば, ff01::1 に対しては ::1 が選択され, fe80:1::2a0:24ff:feab:839b に対しては fe80:1::200:f8ff:fe01:6317 が選択されます (埋め込まれたインタ フェース番号に注意 - 23.5.1.3 で述べられている - この番号により正しい始点アドレスが選択できます. これらの埋め込 まれた番号は通信路 (wire) 上では存在しません). もし出力インタ フェースが該当するスコープに対して複数のアドレスを持っていた場 合は, 始点は最長一致法 (規則 3) で選択されます. たとえば, 出力イ ンタフェースに, 3ffe:501:808:1:200:f8ff:fe01:6317 と 3ffe:2001:9:124:200:f8ff:fe01:6317 が付けられていたとします. 終点アドレスが 3ffe:501:800::1 であるとすると, 始点アドレスと しては 3ffe:501:808:1:200:f8ff:fe01:6317 が選択されます.

上記の規則は IPv6 仕様では文書化されていないことに注意し てください. これは「実装に任された」項目と考えられているのです. 上記の規則に則らないケースがいくつかあります. 一つの例は, 接続 済みの TCP セッションで, この場合は tcb に保存されているアドレ スを始点とします. 他の例としては, 近隣通知 (Neighbor Advertisement: NA) の際の始点アドレスです. 仕様 (RFC2461 7.2.2) によれば, NA の始点アドレスは対応する NS (近隣要請) の ターゲットアドレスであるべきとされています. この場合は, 上記の 最長一致規則ではなく仕様に従います.

新規に接続を行うとき (規則 1 に当てはまらないとき) に, 他に選択肢がある限り, 推奨有効期間切れアドレス (preferred lifetime が 0 であるアドレス)を始点アドレスとして選択すること はありません. もし他の選択肢がなければ, 最後の手段として推奨有 効期限切れアドレスが使われます. もし複数の推奨有効期間切れアド レスがあるときには, 上記のスコープ規則に従ってそれらのアドレス からの選択が行われます. もし何らかの理由により推奨有効期間切れ アドレスの使用を禁止したいのならば, net.inet6.ip6.use_deprecated を 0 に設定してください. 推奨有効 期間切れアドレスに関連する問題は, RFC2462 5.5.4 に記述されてい ます (注意: IETF の ipngwg では推奨有効期間切れアドレスをどの ように使うべきかの議論がいくつか進行中です).

25.3.1.7. 巨大ペイロード

巨大ペイロード中継点毎オプションは実装されており, 65,535 バイトよりも長いペイロードを持つ IPv6 パケットを送信するときに 利用できます. しかし, MTU が 65,535 よりも大きな物理インタフェー スは現在サポートされていませんから, そのようなペイロードはルー プバックインタフェース (たとえば lo0) 上でのみ利用できます.

もし巨大ペイロードを試してみたいのならば, まず始めに, ルー プバックインタフェースの MTU が 65,535 バイトよりも大きくなる ようにカーネルの再構成を行わなければなりません; 以下の行をカー ネル構成ファイルに追加してください:

options "LARGE_LOMTU" #To test jumbo payload

そして新しいカーネルをコンパイルしてください.

次に, ping6(8) コマンドを -b と -s オプション付きで 使うことで巨大ペイロードを試してみることができます. -b オプショ ンはソケットバッファの大きさを拡大するために指定しなければなリ ません. -s オプションによりパケット長を指定します. その値は 65,535 よりも大きくなるでしょう. たとえば以下のように入力してく ださい:

% ping6 -b 70000 -s 68000 ::1

IPv6 仕様では, 巨大ペイロードオプションは分割された (fragtment) ヘッダを持つパケットでは使えないことになっています. この条件が破られると ICMPv6 Parameter Problem メッセージが送信 元に送られるはずです. この仕様には従っているのですが, 通常はこ の ICMPv6 エラーを見ることはできないでしょう.

IPv6 パケットが受信されると, そのフレーム長が調べられ, そして IPv6 ヘッダ中のペイロード長フィールド, またはもしあれば 巨大ペイロードオプションの値, で指定された長さと比較されます. もし前者の方が後者よりも短ければ, パケットは廃棄され統計情報が 更新されます. この統計情報は, netstat(8) コマンドを `-s -p ip6' オプション付きで実行すると見ることができます:

    	  % netstat -s -p ip6
    	  ip6:
    		(snip)
    		1 with data size < data length
            

それ故, カーネルはエラーを起こしたパケットが本当に巨大ペ イロードである, すなわち, そのパケット長が 65,535 バイトよりも 長い場合にしか ICMPv6 エラーを送りません. 上で述べたように, 現 在そのような巨大な MTU をもつ物理インタフェースはサポートされ ていませんので, IPMPv6 エラーが返ることは滅多にないでしょう.

現状では, 巨大パケット上の TCP/UDP はサポートされていま せん. これはテストできる通信メディアが (ループバック以外) 存在 しないためです. もしこれを必要としているなら, わたしたちに連絡して ください.

IPsec は巨大パケットの上では動作しません. これは, 巨大パ ケットと AH を同時にサポートする場合の仕様の「ねじれ」のせいで す (AH ヘッダサイズはペイロード長に影響を及ぼし, そしてこのこ とが, 巨大ペイロードオプションと AH が両方付いた到着パケッ トを認証することを本当に困難にしてしまうのです).

*BSD において巨大パケットをサポートするには基本的な問題 がいくつかあります. それらをここで指摘したいのですが, このリス トを完成させるためにはもっと時間が必要です. その中のいくつかを 以下に挙げます:

  • 4.4BSD では mbuf の pkthdr.len フィールドは "int" 型 ですから, 32 ビットアーキテクチャの CPU 上では 2 ギガバイ ト以上の巨大パケットを保持できません. 巨大パケットを正しく サポートするには, このフィールドは, 4 ギガバイト + IPv6 ヘッ ダ + 下位層ヘッダを保持できるように拡張されなければなりま せん. そのため, 少なくとも int64_t に拡張する必要がありま す (u_int32_t では十分では*ありません*).

  • 多くの場所で, パケット長を格納するための場所を誤って "int" としてしまっています. それらをもっと大きな整数型に変 換する必要があります. この作業には細心の注意が必要です. な ぜならパケット長の計算をするときにオーバフローを起こしてし まうかもしれないからです.

  • たくさんの場所で, パケットのペイロード長を調べるのに, 間違って IPv6 ヘッダの ip6_plen フィールドをチェックしてい ます. そうではなくて, mbuf の pkthdr.len を調べなければな りません. ip6_input() が入力時に巨大ペイロードオプションの 健全性をチェックするようにすれば, その後は mbuf の pkthdr.len を安全に使うことができるでしょう.

  • TCP のコードには, もちろん, たくさんの場所の注意深い更 新が必要でしょう.

25.3.1.8. ヘッダ処理中のループ防止

IPv6 仕様はパケットに任意の数の拡張ヘッダがつくことを許 しています. もし IPv6 パケット処理コードを BSD の IPv4 コード が実装されているのと同様の方法で実装すると, 何重もの関数呼び出 しのせいでカーネルスタックがオーバーフローしてしまうでしょう. sys/netinet6 のコードは, カーネルスタックオーバフローを回避す るように注意深く設計されています. そのために, sys/netinet6 の コードでは独自のプロトコルスイッチ構造体を "struct ip6protosw" (netinet6/ip6protosw.h を参照してください) として定義しています. 互換性のために, IPv4 の部分 (sys/netinet) にはこの変更を行っていませんが, しかし, 小さな変 更が pr_input() のプロトタイプについて行われています. そのため "struct ipprotosw" も定義されています. 以上の理由により, 非常 に多くの IPsec ヘッダを持つ IPsec-over-IPv4 パケットを受け取っ たときにカーネルスタックがオーバーフローする可能性があります. IPsec-over-IPv6 は大丈夫です. (もちろん, それら全ての IPsec ヘッ ダが全て処理されるには, 一つ一つの IPsec ヘッダがそれぞれ IPsec の試験をパスする必要があります. そのため, 外部の攻撃者が そのような攻撃をすることは不可能です.)

25.3.1.9. ICMPv6

RFC2463 が公開された後, IETF の ipngwg は, ネットワーク メディア上の ICMPv6 ストームを引き起こさないように, ICMPv6 向 け直し (redirect) に対して ICMPv6 エラーパケットを出さないよう に決定しました. これはすでにカーネル内で実装されています.

25.3.1.10. アプリケーション

ユーザランドのプログラミングのために, RFC2553, RFC2292, そして発行準備中の internet draft で定義されている, IPv6 ソケッ ト API をサポートしています.

IPv6 上の TCP/UDP は利用可能であり, きわめて安定していま す. telnet(1), ftp(1), rlogin(1), rsh(1), ssh(1), 等を試してみてください. これらのアプリケーションは プロトコル非依存となっています. つまり, DNS に従って自動的に IPv4 と IPv6 を選択します.

25.3.1.11. カーネルの内部

ip_forward() は ip_output() を呼びだしていますが, ip6_forward() は ip_output() を直接呼びだします. これは, ルー タは IPv6 のパケットを断片に分割してはいけないからです.

ICMPv6 は最大 1280 まで, できる限り元のパケットをコピー して含んでおく必要があります. たとえば, UDP6/IP6 ポート不到達 ICMPv6 パケットは, 全ての拡張ヘッダと, *未変更の* UDP6 と IP6 ヘッダを含まなければなりません. そのため, TCP を除く全ての IP6 関数はオリジナルのパケットを保存しておくために, ネットワー クバイト順をホストバイト順に変換しません.

tcp_input() と udp6_input(), icmp6_input() は, 拡張ヘッ ダがあるために, IP6 ヘッダのすぐ後ろにトランスポートヘッダがあ ることを仮定できません. そのため, in6_cksum() は IP6 ヘッダと トランスポートヘッダが連続しないようなパケットを処理できるよう に実装されています. チェックサム計算のための TCP/IP6 ヘッダ構 造体も, UDP6/IP6 ヘッダ構造体も存在しません.

IP6 ヘッダと, 拡張ヘッダ, トランスポートヘッダを容易に処 理できるように, ネットワークドライバに対する新たな要求事項とし て, パケットを一つの内部 mbuf に納めるか, または, 一つ以上の外 部 mbuf に納める必要性を追加しました. 典型的な古いドライバは, 96 から 204 バイトのデータ用の二つの内部 mbuf を用意しますが, 今後はそのようなパケットデータは一つの外部 mbuf に記録されるこ とになります.

netstat -s -p ip6 を実行すると, ドラ イバが上記の要求を満たしているかどうかが分かります. 以下の例で は "cce0" は要求を満たしていません (詳細は 2 章をご覧ください.)

            Mbuf statistics:
                    317 one mbuf
                    two or more mbuf::
                            lo0 = 8
    			cce0 = 10
                    3282 one ext mbuf
                    0 two or more ext mbuf
    	

各入力関数は始めの段階で, IP6 とそのヘッダが連続した領域 にあるかどうかを調べるために IP6_EXTHDR_CHECK を呼び出します. IP6_EXTHDR_CHECK は mbuf が M_LOOP フラグを持っているときのみ m_pullup() を呼び出します. M_LOOP フラグは, パケットがループバッ クインタフェースからきたことを示します. 物理的なネットワークイ ンタフェースからきたパケットに対しては m_pullup() が呼ばれるこ とはありません.

IP と IP6 両方の再構成 (reassemble) 機能は m_pullup() を 呼び出すことはありません.

25.3.1.12. IPv4 射影アドレスと IPv6 ワイルドカードソケット

RFC2553 では, IPv4 射影 (mapped) アドレス (3.7) と IPv6 ワイルドカードバインドソケットの特別な振る舞い (3.8) が記述さ れています. 仕様では以下の動作が許されています:

  • AF_INET6 ワイルドカードバインドソケットで IPv4 接続 を受け付ける.

  • 特別な形式のアドレス, たとえば ::ffff:10.1.1.1 を使うこ とで AF_INET6 ソケットから IPv4 のパケットを送出する.

しかし, 仕様自体が非常に込み入っており, またこの仕様では ソケット層がどう動作すべきかということについて何も規定していま せん. ここでは前者を "待ち受け側" と呼び, 後者を "開始側" と呼 ぶことにします.

同一のポート上で, 両アドレスファミリのワイルドカードバイ ンドを実行することができます.

以下の表に FreeBSD 4.x の動作を示します.

                    待ち受け側              開始側
                    (AF_INET6 ワイルド     (::ffff:10.1.1.1 への接続)
                    カードソケットが
                    IPv4 接続を受ける.)
                    ---                     ---
    FreeBSD 4.x     設定可能                サポートされている
                    デフォルト: 有効
    	

以下の章で, より詳細を述べると共に, どうやってこの動作を 設定するかを示します.

待ち受け側に対するコメント:

RFC2553 は, ワイルドカードバインドの問題についてあまりに も少ししか議論していません. 特に, ポート空間の問題, 失敗モード, そして AF_INET/INET6 ワイルドカードバインド間の関連について. この RFC に関しては, これに準処しているにもかかわらず異なった 動作をするいくつかの別々の解釈が成り立ちます. そのため, 移植可 能なアプリケーションを実装する際には, カーネルの動作について一 切の仮定をおくべきではありません. getaddrinfo(3) を使う のがもっとも安全な方法です. ポート番号空間とワイルドカードバイ ンドの問題は, 1999 年 3 月半ばに ipv6imp メーリングリストにお いてつっこんだ議論がなされましたが, 最終的な合意は得られなかっ たようです (つまり, 実装次第ということです). メーリングリスト のアーカイブを調べてみてはいかがでしょうか.

サーバアプリケーションで, IPv4 と IPv6 の両方の接続を受 けたいのなら, 別の方法が二つあります.

一つは, AF_INET ソケットと AF_INET6 ソケットを使う方法で す (二つのソケットが必要です). getaddrinfo(3) を ai_flags に AI_PASSIVE を設定して使い, そして, 返ってきた全て のアドレスに対して socket(2)bind(2) を使います. 複数のソケットを開くことで, 適切なアドレスファミリを持つソケッ ト上で接続を受けることができます. IPv4 接続は AF_INET ソケット で受けられ, そして IPv6 接続は AF_INET6 ソケットで受けられるで しょう.

もう一つの方法は, AF_INET6 のワイルドカードバインドソケッ トを使う方法です. ai_flags にAI_PASSIVE を, ai_family に AF_INET6 を設定し, そして一つ目の引数であるホスト名を NULL に して getaddrinfo(3) を使ってください. そして返ってきたア ドレス (IPv6 の未指定アドレスであるはずです) に対して socket(2)bind(2) を行います. この一つのソケット で, IPv4 と IPv6 のパケットを受けることができます.

移植可能な方法で, AF_INET6 ワイルドカードバインドソケッ トで IPv6 のみをサポートするには, 待ち受けしている AF_INET6 ソ ケットに対して接続要求をしてきた相手アドレスを毎回チェックする ようにしてください. もしそのアドレスが IPv4 射影アドレスであっ たなら, その接続を遮断する必要があるかもしれません. この条件を 判定するのに, IN6_IS_ADDR_V4MAPPED() マクロを使うことができま す.

この問題をもっと簡単に解決するために, システム依存の setsockopt(2) オプション, IPV6_BINDV6ONLY があります. そ の使い方を以下に示します.

    	int on;
    
    	setsockopt(s, IPPROTO_IPV6, IPV6_BINDV6ONLY,
    		   (char *)&on, sizeof (on)) < 0));
    	

この呼び出しが成功すれば, このソケットは IPv6 パケットの みを受信します.

開始側についてのコメント:

アプリケーション実装者へのアドバイス: 移植可能な (複数種 の IPv6 カーネル上で動作する) IPv6 アプリケーションを実装する には, 以下に述べる点が成功への鍵となると信じます:

  • *絶対に* AF_INET も AF_INET6 もハードコードしない.

  • システムを通じて getaddrinfo(3)getnameinfo(3) を使う. gethostby*() や, getaddrby*(), inet_*(), getipnodeby*() を絶対に使わない (既存アプリケー ションを簡単に IPv6 対応とするために, getipnodeby*() が便 利なこともあるでしょう. しかし, 可能であれば, コードを書き 直して getaddrinfo(3)getnameinfo(3) を使うよ うに努力してみてください.)

  • ある終点 (destination) に対して接続したいときは, telnet(1) のように, getaddrinfo(3) を使って, 返っ てきた全ての終点について試すようにしてください.

  • いくつかの IPv6 プロトコルスタックは, バグありの getaddrinfo(3) 付きで出荷されています. 最低限きちんと 動作するバージョンをあなたのアプリケーションと一緒に出荷し, それを最後の手段として使いましょう.

もし AF_INET6 ソケットから IPv4 と IPv6 の両方の接続を行 いたいのなら, getipnodebyname(3) を使う必要があるでしょう. 既存のアプリケーションを工数最小で IPv6 対応に更新したいのなら ば, この方法がよいでしょう. しかし, これは一時的な解であること に注意してください. なぜなら, スコープ化された IPv6 アドレスを 全く扱うことができないという欠点があるので getipnodebyname(3) 自身を推薦できないからです. IPv6 の名 前検索には, getaddrinfo(3) が推奨される API です. ですか ら, 時間があるときには, アプリケーションを getaddrinfo(3) を使うように書き換えるべきです.

外部に出ていく接続を行うアプリケーションを書くときに, も し AF_INET と AF_INET6 とを完全に別々のアドレスファミリとして 取り扱うのならば, 話は非常に単純になります. {set,get}sockopt の問題は単純になり, DNS の問題も単純になるでしょう. IPv4 射影 アドレスに依存する手法は推薦できません.

25.3.1.12.1. tcp と inpcb の統合コード

FreeBSD 4.x では, tcp に関しては IPv4 と IPv6 でコード を共有しています (sys/netinet/tcp* で). そして udp4/6 では別々 のコードです. 統合した inpcb 構造体を使っています.

このプラットフォームは IPv4 射影アドレスをサポートする ように設定できます. カーネルの設定は以下のようにまとめられま す:

  • デフォルトでは, AF_INET6 ソケットはある条件下では IPv4 接続をハンドリングできます. そして IPv4 射影の IPv6 アドレス中に入っている IPv4 の終点へ向けて接続を開始する ことができます.

  • 以下のように sysctl を使ってシステム全体でそれを無 効にできます.

    sysctl -w net.inet6.ip6.mapped_addr=0

25.3.1.12.1.1. 待ち受け側

各ソケットは特別な AF_INET6 ワイルドカードバインドを サポートするように設定できます (デフォルトで有効です). 以 下のように, ソケット毎に setsockopt(2) を使ってこれを 無効にできます.

    	int on;
    
    	setsockopt(s, IPPROTO_IPV6, IPV6_BINDV6ONLY,
    		   (char *)&on, sizeof (on)) < 0));
    	

ワイルドカード AF_INET6 ソケットは, 以下の条件が成り 立つときのみ, IPv4 接続をハンドリングできます:

  • その IPv4 接続にマッチする AF_INET ソケットが存 在しない

  • その AF_INET6 ソケットは IPv4 通信を受け付けるよ うに設定されている, すなわち getsockopt(IPV6_BINDV6ONLY) が 0 を返す.

open/close の順番は問題となりません.

25.3.1.12.1.2. 開始側

FreeBSD 4.x では, ノードが IPv4 射影アドレスをサポー トするように設定されているときには, IPv4 射影アドレス (::ffff:10.1.1.1) へ向けての接続がサポートされています.

25.3.1.13. sockaddr_storage

RFC2553 が最後の仕上げにかかっている頃, sockaddr_storage 構造体のメンバにどのように名前を付けるかという議論がありました. 一つの提案は, それがいじってはいけないものであるのだから, メン バ名の前に "__" を付ける ("__ss_len" のように), というものでし た. 他の提案は, それらのメンバを直接操作する必要があるのだから, なにも付けない ("ss_len" のように), というものでした. この件に 関する明確な合意は得られませんでした.

その結果として, RFC2553 では sockaddr_storage 構造体は以 下のように定義されました:

    	struct sockaddr_storage {
    		u_char	__ss_len;	/* address length */
    		u_char	__ss_family;	/* address family */
    		/* and bunch of padding */
    	};
    	

これに反して, XNET ドラフトでは以下のように定義されまし た:

    	struct sockaddr_storage {
    		u_char	ss_len;		/* address length */
    		u_char	ss_family;	/* address family */
    		/* and bunch of padding */
    	};
    	

1999 年 12 月に, RFC2553bis では後者 (XNET) の定義を採用 することで合意がなされました.

現在の実装は, RFC2553bis の議論の結果, XNET の定義に適合 するようになっています.

複数の IPv6 実装を調べたならば, 両方の定義を見ることにな るでしょう. ユーザランドのプログラマとして, この件に対応するもっ とも移植性が高い方法は:

  1. GNU autoconf を使って, ss_family と/または ss_len がこのプラットフォームで利用可能であることを確かめる,

  2. -Dss_family=__ss_family として (ヘッダファイルも含め て) 全てを __ss_family に統合してしまう, または

  3. __ss_family には絶対に手を出さない. sockaddr * へキャ ストして, 以下の例のように sa_family を使う:

        	struct sockaddr_storage ss;
        	family = ((struct sockaddr *)&ss)->sa_family
        	    

25.3.2. ネットワークドライバ

ここで, 以下の二項目を標準的なドライバでサポートすることが必須 となります:

  1. mbuf クラスタリングが要求されます. この安定版リリース においては, 全てのドライバが期待通りに動くように, 全てのオペ レーティングシステムにおいて MINCLSIZE を MHLEN+1 に変更しま した.

  2. マルチキャスト. もしあるインタフェースについて ifmcstat(8) が一つもマルチキャストグループを示さないな ら, そのインタフェースは修正が必要です.

もしあるドライバが上記要求をサポートしないなら, そのドラ イバでは IPv6 と/または IPsec 通信には使えません. もしあなた のカードで IPv6/IPsec の使用に関して何か問題を見つけたなら, 是 非それを に報告してくだ さい.

(注: かつて, 全ての PCMCIA ドライバに in6_ifattach() を呼 ぶことを要求したことがありました. 現在では, もはやこの要求は 取り下げています)

25.3.3. トランスレータ

ここでは IPv4/IPv6 トランスレータを四つに分類します:

分類 A のための TCP 中継トランスレータはサポートされてい ます. これは "FAITH" と呼ばれます. 分類 A のための IP ヘッダト ランスレータも提供しています. (後者は FreeBSD 4.x ではまだ取り 込まれていません.)

25.3.3.1. FAITH TCP 中継トランスレータ

FAITH システムはカーネルの助けを借りた faithd(8) と 呼ばれる TCP 中継デーモンを利用します. FAITH は IPv6 アドレス プリフィックスを一つ予約し, そのプリフィックスに向かう TCP 接 続を IPv4 終点に向けて中継します.

たとえば, 予約された IPv6 プリフィックスが 3ffe:0501:0200:ffff:: で, TCP 接続の IPv6 終点が 3ffe:0501:0200:ffff::163.221.202.12 であるならば, その接続は 163.221.202.12 という IPv4 終点に向けて中継されます.

    	終点 IPv4 ノード (163.221.202.12)
    	  ^
    	  | 163.221.202.12 へ向けた IPv4 tcp
    	FAITH-中継 二重スタックノード
    	  ^
    	  | 3ffe:0501:0200:ffff::163.221.202.12 へ向けた IPv6 TCP
    	始点 IPv6 ノード
    	

FAITH-中継 二重スタックノードでは faithd(8) を起動 しておく必要があります.

より詳細な情報は, src/usr.sbin/faithd/README をご覧ください.

25.3.4. IPsec

IPsec は主に三つの構成要素からなります.

  1. ポリシ管理

  2. 鍵管理

  3. AH と ESP のハンドリング

25.3.4.1. ポリシ管理

現在のカーネルには実験的なポリシ管理コードが実装されてい ます. セキュリティポリシを管理するには二つの方法があります. 一 つは, setsockopt(2) を使ってソケット一つずつにポリシを設 定する方法です. この場合のポリシ設定は ipsec_set_policy(3) で説明されています. もう一つの方法は, setkey(8) によって PF_KEY インタフェース経由でカーネル内 のパケットフィルタをもとにしたポリシを設定する方法です.

ポリシエントリはその番号によって並び替えられることはない ので, エントリを追加するときの順番がとても重要になります.

25.3.4.2. 鍵管理

このキットで実装されている鍵管理コード (sys/netkey) は, 自家製の PFKEY v2 実装です. これは RFC2367 に準処しています.

自家製の IKE デーモンである "racoon" がこのキットに含ま れています (kame/kame/racoon). 基本的に, racoon はデーモンとし て走らせる必要があり, それから鍵を要求するポリシをセットアップ します (たとえば, ping -P 'out ipsec esp/transport//use' というように). カーネルは鍵を交 換するために, 必要に応じて racoon デーモンにアクセスします.

25.3.4.3. AH と ESP のハンドリング

IPsec のモジュールは, 標準の IPv4/IPv6 処理中の "フック" として実装されています. パケットを送信するときに, ip{,6}_output() は 一致する SPD (Security Policy Database: セ キュリティポリシデータベース) があるかどうかをチェックして ESP/AH 処理が必要かどうかを判断します. もし ESP/AH が必要なら, {esp,ah}{4,6}_output() が呼ばれ, mbuf が適切に更新されます. パ ケットを受信したときは, プロトコル番号に従って, すなわち (*inetsw[proto])() という形で {esp,ah}4_input() が呼ばれます. {esp,ah}4_input() はそのパケットの認証情報を解読 / 試験し, そ して数珠繋ぎのヘッダと ESP/AH のためのパディングを取り除きます. パケット受信時に ESP/AH ヘッダを取り除いてしまっても安全です. なぜなら受信したパケットを "あるがまま" の形で使うことは絶対に ないからです.

ESP/AH を使うことによって, TCP4/6 における実効データセグ メント長は ESP/AH によって挿入される数珠繋ぎのヘッダの増加分だ け影響を受けます. わたしたちのコードはこの場合を考慮に入れています.

基本的な暗号機能は "sys/crypto" ディレクトリの中にありま す. ESP/AH 変換は wrapper 関数と一緒に {esp,ah}_core.c に記述され ています. もしアルゴリズムを追加したかったら, wrapper 関数を {esp,ah}_core.c に追加し, そして追加する暗号アルゴリズムを実装 したコードを src/crypto に追加してください.

このリリースでは, トンネルモードは以下の制限と共に部分的 にサポートされています:

  • IPsec トンネルは GIF による包括的トンネリングインタ フェースと結合されていません. ip_output() と tunnelifp->if_output() の間で無限ループを構成してしまうか もしれないので, 非常に注意深く作業する必要があります. 統合 した方がよいか, よくないか, 意見はいろいろ出ています.

  • MTU と 分割禁止ビット (IPv4) についての考慮はさらな るチェックを必要としています, が, 基本的にはうまく動いてい ます.

  • AH トンネルのための認証モデルは再考する必要があるで しょう. 今後, ポリシ管理エンジンを改良する必要が出てくると 思われます.

25.3.4.4. RFC と ID への準処

カーネル内の IPsec コードは以下の標準に準処しています (もしくは, 準処しようと努力しています):

rfc182[5-9].txt で文書化されている "old IPsec" 仕様

rfc240[1-6].txt と, rfc241[01].txt, rfc2451.txt, draft-mcdonald-simple-ipsec-api-01.txt (このドラフトは期限切れですが, ftp://ftp.kame.net/pub/internet-drafts/ から入手できま す) で文書化されている "new IPsec" 仕様. (注: IKE 仕様, rfc241[7-9].txt はユーザラ ンドの "racoon" IKE デーモンとして実装されています)

現在サポートしているアルゴリズムは:

  • old IPsec AH

    • 空の暗号チェックサム (文書化されていません. デ バッグのためだけのものです)

    • 128 ビットの暗号チェックサムと鍵付き MD5 (rfc1828.txt)

    • 128 ビットの暗号チェックサムと鍵付き SHA1 (文書化されていません)

    • 128 ビットの暗号チェックサムと HMAC MD5 (rfc2085.txt)

    • 128 ビットの暗号チェックサムと HMAC SHA1 (文書化されていません)

  • old IPsec ESP

    • 空の暗号化 (文書化されていません, rfc2410.txt と似たものです)

    • DES-CBC モード (rfc1829.txt)

  • new IPsec AH

    • 空の暗号チェックサム (文書化されていません. デ バッグのためだけのものです)

    • 96 ビットの暗号チェックサムと鍵付き MD5 (文書化されていません)

    • 96 ビットの暗号チェックサムと鍵付き SHA1 (文書化されていません)

    • 96 ビットの暗号チェックサムと HMAC MD5 (rfc2403.txt)

    • 96 ビットの暗号チェックサムと HMAC SHA1 (rfc2404.txt)

  • new IPsec ESP

    • 空の暗号化 (rfc2410.txt)

    • DES-CBC with derived IV (draft-ietf-ipsec-ciph-des-derived-01.txt, draft expired)

    • DES-CBC with explicit IV (rfc2405.txt)

    • 3DES-CBC with explicit IV (rfc2451.txt)

    • BLOWFISH CBC (rfc2451.txt)

    • CAST128 CBC (rfc2451.txt)

    • RC5 CBC (rfc2451.txt)

    • 上記のそれぞれは, 以下と結合可能:

      • HMAC-MD5(96 ビット) による ESP 認証

      • HMAC-SHA1(96 ビット) による ESP 認証

以下のアルゴリズムはサポートされて *いません*:

  • old IPsec AH

    • 128 ビットの暗号チェックサムと HMAC MD5 + 64 ビット の再送攻撃防止 (rfc2085.txt)

    • 160 ビット暗号チェックサムと鍵付き SHA1 + 32 ビッ トのパディング (rfc1852.txt)

IPsec (カーネル内) と IKE (ユーザランドの "racoon") は, 何回もの相互接続性試験イベントで試験されていて, そこでの結果とし て, 多くの他の実装とうまく相互接続可能であることがわかっていま す. また, 現在の IPsec 実装は, RFC に記述された IPsec 暗号ア ルゴリズムを非常に広くカバーしています (知的所有権の問題がない アルゴリズムに限ってカバーしています).

25.3.4.5. IPsec トンネルにおける ECN の考察

ECN と親和性のある IPsec トンネルは, draft-ipsec-ecn-00.txt で述べられている方 法を用いてサポートされています.

通常の IPsec トンネルは RFC2401 で記述されています. カプ セル化されるときに, 内側の IP ヘッダの IPv4 TOS フィールド (ま たは, IPv6 トラフィッククラスフィールド) が外側の IP ヘッダに コピーされます. カプセル解放の時には外側の IP ヘッダは単に削ら れるだけです. 外側の IP ヘッダの TOS / トラフィッククラスフィー ルド中の ECN ビットが失われてしまうため, このカプセル解放規則 は ECN と互換性がありません.

IPsec トンネルを ECN と親和性があるようにするために, カ プセル化手順とカプセル解放手順を変更する必要がありました. これ については, http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt の 3 章で記述されています.

net.inet.ipsec.ecn (または net.inet6.ipsec6.ecn) に設定 する値によって, IPsec トンネルの実装は三通りの動作を行います:

  • RFC2401: ECN を考慮しない (sysctl の値が -1 の時)

  • ECN 禁止 (sysctl の値が 0 の時)

  • ECN 許可 (sysctl の値が 1 の時)

この振る舞いはノード毎に設定可能であり SA 毎ではないこ とに注意してください (draft-ipsec-ecn-00 では SA 毎の設定を要 求していますが, それは大変すぎます).

ここで述べた動作をまとめると以下のようになります (より詳 しくはソースコードをご覧ください):

             カプセル化                       カプセル解放
             ---                              ---
    RFC2401  内側から外側へ                   外側の TOS ビットを落とす
             全ての TOS ビットをコピー.       (内側の TOS ビットをそのまま使う)
    
    ECN 禁止 内側から外側へ ECN ビット以外    外側の TOS ビットを落とす
             (0xfc でマスク) の TOS ビット    (内側の TOS ビットをそのまま使う)
             をコピー. ECN ビットを 0 に.
    
    ECN 許可 内側から外側へ ECN CE 以外       内側の TOS ビットを変更して使う.
             (0xfe でマスク) の TOS ビット    もし外側の ECN CE ビットが 1 な
             をコピー. ECN CE ビットを 0 に.  ら, 内側の ECN CE ビットを有効に.
    	

設定方法に関する一般的な戦略は以下のようになります:

  • もし IPsec トンネルの両端が ECN に親和性がある動作を するのなら, その両方を "ECN 許可" と設定した方がよいでしょ う (sysctl の値を 1 に設定).

  • もし反対側の端が TOS ビットに関して非常に厳密に動作 するなら, "RFC2401" を使ってください (sysctl の値を -1 に 設定).

  • その他の場合, "ECN 禁止" (sysctl の値を 0 に設定).

デフォルトの動作は, "ECN 禁止" (sysctl の値が 0) です.

より詳しくは, 以下を参照してください:

http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt, RFC2481 (Explicit Congestion Notification: 明示的輻輳通知), src/sys/netinet6/{ah,esp}_input.c

(詳しい分析をしてくれた, 長 健二朗 氏 に感謝します)

25.3.4.6. 相互接続性

以下に, これまでに KAME と IPsec/IKE の相互接続性試験を 行ったプラットフォーム (の一部) を挙げます. これらのプラット フォームも KAME も, 試験以降に何らかの実装の変更を行っているで しょうから, 以下のリストは参考にとどめてください.

Altiga, Ashley-laurent (vpcom.com), Data Fellows (F-Secure), Ericsson ACC, FreeS/WAN, HITACHI, IBM AIX, IIJ, Intel, Microsoft WinNT, NIST (linux IPsec + plutoplus), Netscreen, OpenBSD, RedCreek, Routerware, SSH, Secure Computing, Soliton, Toshiba, VPNet, Yamaha RT100i