December 2008

December 15, 2008

このエントリーをはてなブックマークに追加
先日、一般や企業向けに IPv6 対応を支援をする、EDGE Co.Lab v6 というのを始めました。
これを始めるにあたって、弊社情報環境技術研究室の伊勢さんから、「なんかウチでやってるコンテンツで、どれか IPv6 対応しようよ」と、いきなり言われました。

実は IPv6 って何年も前からよく耳にするけど、特にインフラまわりの知識が拙いし、何だかんだ身の回りのほとんどが IPv4 で、それでまぁウマくいってるからよくわからないし、別にどうでもいい…と、IPv6 に対して「現実味がない。時期尚早なのでは?」みたいな勝手な印象を抱いて、毛嫌いしてました。

伊勢さんは 2ch の IPv6 板とかを立ち上げたらしく、IPv6 でアクセスすると、トップページのひろゆきが踊って表示されるそうです。
IPv6 と IPv4 の差って、ひろゆきが踊るか踊らないかの差だけ?とか、そうじゃないのをわかってながら変に牽制しつつ、対応しようとか言われても、IPv6 の何がいいのかよくわからんーとか思って、ボンヤリと引き受けました。

で、その話の中で IPv4 枯渇時計というものを教えてもらって、衝撃を受けました。



実は IPv4 アドレスの枯渇 (予測) が意外に間近に迫っていて、今現在、良い悪いだ議論してようが、毛嫌いをしていようが、近い将来、この業界で働いている限りは免れることの出来ない現実だと感じました。
なのでこれを機に、実験的に fixdap を IPv6 化することにしました。

しかし、何をもって「IPv6 化」と言うのかわからず、何となく調べながら、ちょこちょこいじって、とりあえずは IPv6 対応が完了しました。
2ch の IPv6 板と同様に、IPv6 でアクセスした場合はロゴが変わるようになってます。

IPv4:
fixdap IPv4

IPv6:
fixdap IPv6

実際に見てみたい方はこちらにアクセスしてみてください。
どうでしたか?あなたの環境は IPv6 でしたか?

ちなみに、ロゴが違う以外は、特に違いはありません。もちろん、違いをつけることももちろん可能です (その予定はないです) が。

プロトコルの差異とかは、特に気にはしてない…というか、実はちゃんと理解出来てませんが、実際にやってみると、IPv6 に対応するのはそんなに難しいことでもありませんでした。
今後避けて通れない IPv6 対応をする際、どういうところを注意すれば良いか、要点をまとめてみました。

  1. クライアントとサーバの終端装置が IPv6 対応していないとダメ
  2. 実は、どちらも終端側が IPv6 対応じゃないと IPv6 が利用出来ないみたいです。
    IPv4 と IPv6 のデュアルスタックの構成にする場合は、テストする際には当然 IPv6 が優先されていないとダメです。
    意外にも、インターネットの間口となっているルータやら、サーバ側に設置したエンタープライズのロードバランサ製品とかが IPv6 に対応していない…なんてのは、珍しくなかったりします。
    ただし、クライアント側のルータが IPv6 に対応していなかったとしても、IPv6 の HTTP proxy を立てることによって、一応の検証作業は行なえます。

  3. サーバ ID (SSL 証明書) は IPv4 だろうが IPv6 だろうが関係ないよ
  4. 元々 fixdap は SSL も利用しているので、IPv6 用に新規にサーバ ID を追加したのですが、中間 CA 局に発行してもらう際には IPv4 と同様の手続と、同様の証明書を利用することが出来ます。「IPv6 用の証明書」とか、雰囲気的にありそうですが、そういうものは別にありません。
    IPv4 と IPv6 のどちらでもアクセスできる環境がある方は、SSL ページの証明書の情報を見てみてください。
    IPv4 と IPv6 で、同じ CA 発行ではありますが、別のサーバ ID を使用していることがわかると思います。

  5. Apache の設定は、そんなに難しくないよ
  6. Apache は 2.0 以降、Apache Portable Runtime (APR) が IPv6 をサポートしているシステムで IPv6 のソケットを listen 出来るようになっています。
    IP アドレスとポート番号を指定出来る各ディレクティブでは、IPv6 アドレスは [] (bracket というか角括弧というか大括弧) で囲む必要があります。恐らく IP アドレスとポート番号の区切り文字である ":" (コロン) と、IPv6 アドレスの 16bit ごとの区切り文字とを混同しないためだと思います。
    Listen [2001:db8:bad:feed::dead:beef:cafe]:80
    NameVirtualHost [2001:db8::babe:face]:80
    <VirtualHost [2001:db8::babe:face]:80>
      ServerName babe-face.example.com
        :
        :
    </VirtualHost>
    違う場所はそのぐらいで、あとは通常通りでイケます。
    ただ、ポート番号を記述しない Allow や Deny 等のディレクティブは、IPv6 アドレスを [] で囲まずにそのまま書きます。
    Allow from 2001:db8:c0:ffee::/64
    IPv4 と IPv6 の場合の設定で違う場所はこのぐらいです。
    あとは、いつも通りの設定をすれば良いだけです。

  7. 疎通確認は ping や traceroute ではないよ
  8. 最初、ping やら traceroute の引数に IPv6 アドレスを指定しても、unknown host と怒られちゃうので、どうやって ICMP を送りつけるのかなーと思ったのですが、IPv6 の場合は、コマンドの後ろに 6 が付く、ping6 や traceroute6 コマンドを使うようです。
    % ping6 2001:db8:bad:face::dead
    % traceroute6 2001:db8:bad:face::dead
    言うまでもありませんが、Windows の場合は traceroute6 は、tracert6 です。

  9. DNS 登録は A レコードではないからね
  10. 名前解決の時に IPv6 アドレスを返すように DNS に登録するのに登録するレコードは、A レコードではなく、AAAA (クアッド A) レコードにする必要があるようです。
    AAAA レコードを引かない環境では A レコードが解決されるので、その場合は IPv4 でのアクセスになるようです。

  11. IPv6 か IPv4 かの判別はどうすればいいのかな
  12. web アプリケーション側で、IPv4 からのアクセスなのか、IPv6 からのアクセスなのかを判別するのはどうすれば良いかと言うと、ホスト名をかえている場合はそれで簡単に判断出来ると思いますが、心情的には同じホスト名でアクセスさせたいところ (2ch や fixdap はそうしています)。
    その場合、単純に接続元のアドレスが IPv4 なのか IPv6 なのかを見れば済みます。
    $ENV{REMOTE_ADDR} やら、mod_perl 環境とかだと $r->connection->remote_ip やらが接続元になると思います。
    そんなに厳密にやらなくても良いなら、数字とドットだけで構成されていたら IPv4、数字と a-f のアルファベット、コロンとドットで構成されていれば IPv6 と判断してもいいぐらいのカジュアルさでも良いと思います。
    また、IPv6 で Listen しているサーバを reverse proxy にしている場合は、mod_headers を利用して、リクエストヘッダに、IP のバージョンヘッダとかを追加してあげれば、proxy される側のアプリケーションでそれを参照するだけで済むので、実装が楽になると思います。
    以下は、簡単な一例です。
    Listen 80
    
    # IP-based virtual hosting
    <VirtualHost [2001:db8::babe:face]:80>
      ServerName babe-face.example.com
      RewriteEngine On
        :
        :
      RequestHeader set X-IP-Version 6
    </VirtualHost>
    
    <VirtualHost 192.0.2.1:80>
      ServerName babe-face.example.com
      RewriteEngine On
        :
        :
      RequestHeader set X-IP-Version 4
    </VirtualHost>
    これが恐らく最も手軽です。
    アプリケーション側で、$ENV{HTTP_X_IP_VERSION} やら、mod_perl 環境であれば $r->header_in('X-IP-Version') なんかを参照することによって、判別することが可能です。

  13. IP アドレスを保存するカラムとかの長さは足りてるかな
  14. web アプリケーション側でデータベースに保存する際、アクセス元の IP アドレスを保存しているカラムとかがあると、罠にハマります。
    文字列として IPv4 アドレスを保存する場合は、
    |255.255.255.255|
    +----5----0----5+
    15 バイトのカラムを確保すれば済みますが、IPv6 の場合は、もっと長い必要があります。
    で、実際どれぐらい長ければいいのかわかってないのですが、どっかで IPv4 互換アドレスというのを見た記憶があります。それを一番冗長に書くと
    |0000:0000:0000:0000:0000:0000:255.255.255.255|
    +----5----0----5----0----5----0----5----0----5+
    とかなので、実際、REMOTE_ADDR がこういう形式で入ってくるかわからないし、0000:0000:0000:0000:0000:0000:0:0:0:0:0:0::: と略せるそうなので、こんな長いアドレスは保存されないとは思います。
    でも念の為に 45 バイトぐらいはあったほうが心強いような気がします。
    そのあたりは識者にうかがいたいぐらいです。
    あとは、IPv4 アドレスを 8bit x 4 として扱って、4 バイトのバイナリデータにしている場合は IPv6 の場合は 16 バイト入るようにカラムの長さを確保しておく必要があります。

  15. アクセス解析がちゃんと出来るかな
  16. アクセスログを解析する場合、アクセスログの parser が、行頭を IPv4 アドレスだと決め打ちにしていたら、IPv6 アドレスはマッチングせずに parse 出来ません。
    parse 出来ないなら、parser を改修するか別のものに置き換える必要があります。


以上が注意すべき 8 つのポイントです。

とは言え、実際には IPv4 が枯渇しそうな今の次点でも、IPv6 環境が構築できるような環境がなかなか無いのが実情です。
しかし、来るべき IPv4 枯渇時代に備えて、これらの知識を今のうちに知っておくのは有益なのではないかなと思います。

正直、自分は、環境を提供してもらって、作ったってだけなので、IPv6 化するという基本的なスタート地点より先が未だによくわかってませんが。。。
(これからちゃんと本とか読んで勉強したいと思います)

実際に、環境が整えられないが、IPv6 環境を構築したり、その環境下で検証等をしてみたいという方は、EDGE Co.Lab v6 に応募されてみてはいかがでしょうか。






nipotan at 20:14 | Comments(6) | 技術 
このエントリーをはてなブックマークに追加