>トップ
ちょっとした LAN で組まれたシステムを IPv6 化したときの覚え書きです。センシティブな情報とかを削って再構成したもの
インターネットにつなげない構成を考慮したりしているので、若干一般的でない記述があります
ソフトウェアのバージョン、RFC のステータス等は基本的に 2008 年 11 月頃のものです(気がついたものについては更新等していますが、網羅的にメンテナンスはしていません)
コメント等ありましたらプロファイルにあるメイルアドレス等までお願いします
2011 年 6 月 8 日に、World IPv6 Day が開かれました。「サービスの提供者が一斉にある1日(24時間)だけ自社のサービスをIPv6対応にして、影響を探ってみようという試み」でした。
詳細な実施期間は、UTC(いわゆるグリニッヂ標準時)が 8 日である 24 時間、JST では 8 日 9 時 00 分から 9 日 8 時 59 分の間でした。
参考リンク集
2010 年 7 月 13 日までヘッダ長に誤記がありました
スウィッチングハブ等の L2 機器は,基本的にそのまま使用できる.IPv4 との混在も問題ない.
IPv6 では、ネットワークの設定は、特にクライアントでは,ルータから配信される RA (Router Advertisement) という情報に従って設定するのが基本となっている。IPv6 に対応したルータを導入し、v6 アドレスを設定するか、変則的な設定となるが、LAN 内のマシンで RA を配信する daemon (radvd/rtadvd,router advertisement daemon) を走らせるなどする.
(Linux では radvd が標準(でないディストリビューションがあったら教えてください).*BSD では、ベースシステムに rtadvd があり、パッケージシステムに radvd もある)
これをしない場合、手動での設定となる.
Windows XP では、IPv6 の設定において、従来の IPv4 のような GUI によるアドレス等の設定はできない.リンクローカルでないアドレスを設定するには以下の方法がある.
具体的なコマンドは以下のようになる.
netsh interface ipv6 add address "ローカル エリア接続" 2001:db8::2
※日本語版 Windows で,LAN が「ローカル エリア接続」という名前の場合.
※2001:db8:〜 というアドレスは文書での例示のために予約されているアドレス(RFC 3849)
それぞれの手順に従って有効化する
IPv4 で多用されていた NAT を利用した環境では,ノードを外部のインターネットから直接見ることができないことにより,一定の安全が確保されていた.グローバルアドレスによる End 2 End の環境が普遍化する IPv6 では,ルータがファイヤウォールとして正しく設定され機能すること,ノード自体がパケットフィルタなどを備えること,などが求められるだろう.
参考 RFC 4291, 5156 他
なお RFC 5156 では、以上の表記法にある揺れの可能性を抑えるため、以下のようなルールを示している。
参考 RFC 2460 他
IPv4 には,孤立したネットワークや NAT により隔離されたネットワークで利用するためのプライベートアドレス空間があった.IPv6 には,代替になるものとして,リンク (サブネット (セグメント)) 内でのみ一意とされるリンクローカルアドレスと,グローバルで一意になるように工夫されたユニークローカルアドレスがある.サイトローカルアドレスというものもあったが deprecated である
ある範囲からランダムで選んだ値は、誕生日パラドックスにより、直感よりもかなり衝突が起きやすい。が、ユニークローカルアドレスは 40 ビットの空間があるので、適切な生成のしかたをする限りにおいては衝突は非常にまれであろう.
参考 RFC 4007 sec.11
IPv4 にはなかった概念であるので要注意.
リンクローカルアドレスのような,グローバルでないアドレスでノードを指定する場合,IP(v6)アドレスだけではなく,リンクも指定する必要がある.具体的に考えてみよう.複数のインタフェースを持つホストから,あるリンクローカルアドレスに ping を飛ばしたいとする.リンクローカルアドレスは,どちらのインタフェースにも同じプレフィックス fe80::/64 で付いており,アドレスからではどちらのインタフェースに向けて ping を飛ばさなければならないのかわからない (リンクローカルアドレスはリンク内にのみ有効である.両方のリンクに同じアドレスをもつ別々のノードがあることさえ考えられる) .
従って,リンクローカルアドレスでノードを指定する場合は,"%" を挟んでゾーン ID (Windows ではインタフェースに与えられるインデックス値,Unix ではインタフェース名) を付加しなければならない.特に,実験的環境などの構築の際,リンクローカルアドレスを使って ping などで導通を確認する場合にこれを忘れるとうまくいかないので注意が必要である.
手動で route コマンドでデフォルトルートを設定する場合などでも必要なことがある.
Linux の場合の注意
Linux では,アドレスに % をセパレータとして付加するのではなく,-I (Interface) オプションで,ping6 -I eth0 fe80::1 のように指定する.
リンクローカルアドレスは,一種のゼロコンフィギュレーションネットワーキングのためのアドレスとして使用される.さらに IPv6 では,ルータからの Router Advertisement という情報にもとづいて自動的にグローバルアドレスを設定できる (cf. IPv4 では DHCP サーバが必要である) .DNS サーバの設定のためには DHCPv6 を使う.
参考 RFC 4291 app.A
IPv6 アドレスのインタフェース ID 部分は,ふつう 64 ビットである.この 64 ビットに使う値をネットワークインタフェースの MAC アドレスから生成する方法が定められている (この方法で生成しなければならないというわけではない) .
具体的には,48 ビットの MAC アドレスを前半と後半の 24 ビットずつに分け,その間にパターン 0xfffe を挟み,先頭オクテットに 0x02 を or (ビット 1 (LSB をビット 0 とする) を立てる) する.最後のビット操作の理由は,EUI-64 と IPv6 で,スコープのローカル/グローバルを示すビットの値が逆に設定されているためである (詳細略) .
(サイト takagi-hiromitsu.jp の画像を直接利用しています)
参考 高木浩光@自宅の日記 - MacユーザはIPv6を切るかnet.inet6.ip6.use_tempaddr=1の設定を
MAC アドレスはグローバルにユニークな識別子で,これをインターネットアドレスに使用することは,個人を特定し追跡することを容易にする,というプライバシー的問題がある.
この問題を解決するため,RFC 4941 で,乱数等をベースに一時的にアドレスを生成し利用する方法が提案されている.各 OS における対応状況を示す.
sudo sysctl net.inet6.ip6.use_tempaddr=1
sudo sysctl net.inet6.ip6.prefer_tempaddr=1
IPV6_PRIVACY=rfc3041
という記述を追加OCN IPv6 のIPv6通信確認サイト
参考 RFC 3986
従来,URL のホスト部において,IP アドレス記述とドメイン名記述は特に区別されていなかった.しかし,IPv6 アドレスはコロンを含むため,ポート部を区切るコロンと文法的に衝突する.このため,URL では IPv6 アドレスを "[" "]" で括る.
なお,RFC ではゾーン ID をサポート外としている.
IPv6 ではパケットの断片化が禁止されたため、パケットサイズを大きくするためには目的ノードまでの経路における最大転送単位(MTU)を知る必要があり、Path MTU Discovery をおこなうが、途中のノードで ICMP パケットが全て落とされるなどするとこれができないという問題がある.
6to4 などは 固定 v4 アドレスが必要.
Teredo は (v4 な) NAT の内側のホストから v6 な The Internet に繋げることができる.
2011 年の春ごろ,手元の FreeBSD と Miredo という実装で teredo.ipv6.microsoft.com を Teredo サーバとしてやってみたところ,実験程度には使えた(調子が悪くなることも多く常用は無理だった).
コマンドラインからの方法 (SP1 未満ではこちらのみ可能)
GUIからの方法 (SP1 以降で可能)
(参考 http://www.atmarkit.co.jp/fnetwork/tanpatsu/10winxpv6/winxpv602.html )
Mac OS X で IPv6 を有効化するには,以下のようにする.
参考 http://lists.freebsd.org/pipermail/freebsd-net/2007-June/014498.html
URL の解釈部分を IPv6 に対応させる (前述) .
参考 http://ja.wikipedia.org/wiki/IPv6
従来のプログラムではソケットを以下のように作成していた
s = socket(AF_INET, SOCK_STREAM, 0);
これのアドレスファミリ部を AF_INET から AF_INET6 に書き換えれば IPv6 を利用することになる.しかし,それでは IPv4 への対応がなくなってしまうので,以下のように getaddrinfo を使った,プロトコル独立なコーディングが望ましい.
int error, s; struct addrinfo hints, *res, *res0; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; /* TCPの場合 */ if ((error = getaddrinfo("ホスト名", "サービス名", &hints, &res0))) return (-1); for (res = res0; res; res = res->ai_next) { if ((s = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) continue; if (connect(s, res->ai_addr, res->ai_addrlen) == 0) break; close(s); s = -1; } freeaddrinfo(res0); if (s < 0) { /* Could not connect */ } else { /* Success */ }
参考 http://docs.hp.com/ja/5991-0704/ch15s05.html
クライアントのプログラムと同様に,getaddrinfo を使う.
struct addrinfo *ainfo, *res; struct addrinfo hints; /* zero-out the hints before assignment */ memset (&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; hints.ai_flags = AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(NULL, "example", &hints, &res); if (error != 0) { fprintf(stderr, "%s: %s for service 'example'\n", argv[0], gai_strerror(error)); exit(1); } /* Create the listen socket. */ ls = socket (res->ai_family, res->ai_socktype, res->ai_protocol); if (ls == -1) { perror(argv[0]); fprintf(stderr, "%s: unable to create socket\n", argv[0]); exit(1); } /* Bind the listen address to the socket. */ if (bind(ls, res->ai_addr, res->ai_addrlen) == -1) { perror(argv[0]); fprintf(stderr, "%s: unable to bind address\n", argv[0]); close(ls); exit(1); } /* Initiate the listen on the socket so remote users * can connect. The listen backlog is set to 5, which * is within the supported range of 1 to 20. */ if (listen(ls, 5) == -1) { perror(argv[0]); fprintf(stderr, "%s: unable to listen on socket\n", argv[0]); close(ls); exit(1); }
サーバをデュアルスタック対応にするために,一般には,IPv4( INADDR_ANY )と IPv6( in6addr_any )の両方を listen する必要がある.しかし,RFC 3493 の§3.7 で,IPv4-mapped addresses を使用して,IPv4 アドレスを IPv6 にマップして接続する方法が示されており,それが利用できれば IPv6 の listen のみでデュアルスタック対応になる.
ソケットの IPV6_V6ONLY というオプション(RFC 3493 §5.3)をセットすると,IPv6 ノードにしか接続しなくなる.
Linux では net.ipv6.bindv6only 、FreeBSD では net.inet6.ip6.v6only という sysctl 値があり,これを 1 にすると IPV6_V6ONLY がセットされているのがデフォルトになる.FreeBSD では 5.x の途中頃から 1 に,Linux カーネルのデフォルトは 0 のようだが,Debian では squeeze から 1 がデフォルトとしてセットされるようになっている.
id:metanest:20100628#1277709770 に ruby でのサンプルがある.
DNS の IPv6 対応には,2種類ある.DNS に IPv6 関係の情報を載せる IPv6 対応と,DNS による名前解決自体の IPv6 通信対応である.
IPv6 アドレスは,DNS に IN クラスの AAAA (クワッド・エー) 型のレコードとして登録される.AAAA の他に A6 も検討されたが Experimental ステータスになっている.逆引きは,4 ビットずつ 16 進表記で逆順に並べて .ip6.arpa. というサフィックスを付け,PTR レコードで登録する (逆引きの存続については検討中である) .
既存の DNS サーバの IPv6 リソース・レコードへの対応は,単にこれらのレコードを登録すればよい (DNS は任意のデータを入れられるように設計されている) .
IPv6 による通信への対応はさらに,クライアント - DNS サーバ間の IPv6 化と,DNS サーバ同士の IPv6 化がある.代表的な DNS の実装である BIND は,8.4 以降で対応している.2008 年 2 月に,DNS ルートゾーン (ルートサーバのアドレス) に IPv6 アドレスが登録され,DNS の IPv6 化のひとつの峠を越した. (全ての DNS サーバが IPv6 に対応するまでは,IPv4 にも対応するデュアルスタックである必要があり,IPv6 シングルスタック化が可能になるまでにはまだだいぶ時間がかかるものと思われる) .
プログラムからの名前解決で IPv6 が使われるかどうかは,libc に含まれるリゾルバのコードによって決まるが,これは各 OS で (glibc を使う Linux では glibc で) IPv6 対応している.
システムがデュアルスタック対応であれば,従来の IP アドレスのフィールドに,IPv6 アドレスを記述するだけでよい.
3.x の場合の情報 http://yu.vinelinux.org/~yamamoto/vine-ipv6.html
Firefox2 は IPv6 アクセスに対応しているが,ゾーン id の付いたリテラル IPv6 アドレスに対応していない.
Firefox3 は ゾーン id の付いたリテラル IPv6 アドレスにも対応したが,Apache httpd でエラーになる (後述) .
Bugzilla エントリは Bugzilla@Mozilla Bug 464162 – Apache does not accept IPv6 addresses with a scope id in the Host: header Bugzilla-jp bug 6426 - HostヘッダにおけるリテラルIPv6アドレスに付加されたスコープIDの扱い .
Apache で IPv6 のコネクションを扱うには設定ファイルの Listen ディレクティブを使う.参照 http://httpd.apache.org/docs/2.0/ja/bind.html#ipv6
Linux では v4 マッピングにより,普通に Listen すれば v6 も有効になっている.
Firefox3 から,ゾーン ID の付いたリテラル IPv6 アドレスでアクセスすると,400 Bad Request になる.
Apache の Bugzilla にこの問題が報告されている ASF Bugzilla - Bug 35122 – Apache does not accept IPv6 addresses with a scope id in the Host: header .
ゾーン ID は,クライアントでのみ意味のあるものだから,HTTP の Host ヘッダには含まれるべきでない,との判断で,NEEDINFO ステータスで保留されている.Konqueror ではそうなっているらしい.
Vine の qpopper は VinePlus で提供されている.
Source RPM は qpopper-4.0.9-0vl5.src.rpm
Source RPM の qpopper.spec を見たところ,IPv6 パッチは当てていない.
IPv6 有効版 qpopper のビルド手順 (rpmのビルドディレクトリが ./rpm にあるとしている)
IPv6 化のためには,データリンク層の機器は IPv6 を利用可能な規格のものである必要がある.イーサネットは IPv6 を利用可能である.同じネットワーク (セグメント) に IPv4 と混在することは原理上問題ない.プロトコル ID を見て動作を変えるスウィッチングハブ等があり,運用で問題になった例はあるようだが,IPv6 の普及にともない現在ではそのような機器はなくなっている.基本的に従来の機器をそのまま使い続けて問題ない.
IPv4 における、ARP や ICMP に代わり、ICMP for IPv6 (ICMPv6) を用いる。前述の Router Advertisement など。
( IPv6 より前の)TCP や UDP は チェックサムの計算に IPv4 を前提として決め打ちしている部分があるため、IPv6 対応のために修正が必要である。具体的な修正方法については RFC 1883 の 8 節にある。次節の仮想環境等でもややこしい問題だったようだ。
VMware をはじめとする仮想機械では,ゲスト環境とネットワークインタフェースとの間の通信に解析・介入をおこない,仮想機械がホスト環境のネットワークインタフェースとの間で NAT またはブリッジとして機能することにより,ゲスト環境にネットワーク環境を提供している.従ってゲスト環境で IPv6 を利用するには,仮想機械による IPv6 のサポートが必須である.
以下に Macintosh で使われる各仮想機械における IPv6 のサポート状況を示す.