ざっくり詳解 - NAT64とDNS64

   このエントリをはてなブックマークに登録    2017/2/23-1

2016年6月から、iOSアプリの審査基準としてIPv4に依存するコードの禁止が追加され、IPv6対応がiOSアプリの義務なったことからも、IPv6に関する知識が必須となったエンジニアも多いのではないかと思います(Appleの発表)。

Appleのサイトでは、IPv4アドレス在庫枯渇の発生とともに、ユーザに対してIPv6のみによるインターネット接続性を提供するNAT64(「なっとろくよん」です。ろくじゅうよんではないです。)とDNS64という技術が、エンタープライズ網や携帯電話網で採用されることが増えているとあります。

iOSアプリ開発者は、このNAT64とDNS64環境でもアプリが正しく動作することを求められています。 Appleのサイトでは、NAT64とDNS64はOS X 10.11から標準搭載されるようになっているので、Macを使ってiOSアプリの動作確認をすることを推奨しています。

NAT64とDNS64とは何か?

でも、このNAT64とDNS64とは何なのでしょうか? 名前からNATとDNSが関連しそうな感じはしますが、あまり中身は気にせず使っている方々も多いと思います。

NAT64とDNS64とは、ユーザが利用するホストに対してIPv6のみを提供しつつ、そのIPv6ネットワークからIPv4インターネットとの通信も行えるようにするための要素技術です。 たとえば、スマホに対して提供されるネットワークがNAT64+DNS64で運用されていた場合、そのスマホを利用するユーザはIPv6しか使わなくなります。

NAT64は、IPv6ヘッダをIPv4ヘッダに変換、IPv4ヘッダをIPv6ヘッダに変換、IPv4 ICMPパケットをICMPv6に変換、必要に応じてTCPやUDPヘッダを書き換え、場合によってはFTPなどの対応(Application Level Gateway)などを行います。DNS64は、IPv4のみで運用されている「名前」をIPv6で通信できるように変換するための仕組みです。

今回は、NAT64とDNS64が何なのかを「ざっくり紹介」するというつもりで文章を書き始めましたが、書いているうちに徐々にマニアックになった部分もあるので「ざっくり詳解」というタイトルに変更しました。あくまで「ざっくり」とした全体像を述べたものですが、ところどころが「詳解」になっています。とはいえ、個々の詳細には入りすぎないように気をつけてはいるつもりです(てへぺろ)。

でも、この「ざっくり詳解」という表現は、私がこれまで書いてきた文章の傾向のような気もしていて、結構気に入ってます。

IPv6導入は増えている

まず最初に。あまり実感がわかない方々も多いと思いますが、実は、IPv6を利用した通信を行えるユーザ環境は、どんどん増えているのです。

「IPv6」という単語が日本で話題になり始めたのは2000年頃です。 2002年には、森首相の演説で「IPバージョン6」という単語が入ったりしました(外務省:ダボス会議における森総理大臣のスピーチ)。 当時を知っている方々は、「IPv6って昔から話題になってるけど全然普及しないよね」という感想を持っていることが多いです。

しかし、2011年にIPv4アドレス在庫枯渇が現実のものとなり、IPv6を推進する動きが活発化しました。

モバイル機器に対してインターネット接続性を提供するサービスで、ユーザに意識させずに自動的にIPv6が利用されるようになる環境も世界中で増えつつあり、IPv6による通信も急激に増えています。 日本でも2017年度中にNTTドコモ、KDDI、ソフトバンクの大手モバイルキャリア3社すべてがスマートフォンユーザに対するIPv6サービスを行うようになります(参考)。

IPv4とIPv6による「2つのインターネット」

NAT64とDNS64の説明に入る前に、大前提としてIPv4とIPv6は全く異なるプロトコルであるという点を理解する必要があります。

IPv6は、単純にIPアドレス長が32ビットから128ビットへと大きくなっただけではなく、新たに生み出されたIPv4とは似て非なるプロトコルなのです。 「IPv4インターネット」と「IPv6インターネット」という互いに直接的な互換性がない2つのインターネットが別々に運用されているような状態です。

インターネットをレイヤー分けして考えると、これまでのIPv4だけのインターネットは、次の図のように表現できます。IPを表す第3層(ネットワーク層)だけプロトコルが単一で、それ以外はすべて複数のプロトコルが存在しています。 IPv6が登場する前は、IPv4一択だったのです。IPv4考案当初はコンピュータも今よりもはるかに非力で、32ビットが表す空間は当時としては無限のような大きさであったのだろうと思います。

しかし、インターネットが普及し、1人で何個ものIPアドレスを利用するような使い方が当たり前になったのでIPv4のアドレスが足りなくなってしまいました。そこでIPアドレス空間が広いIPv6が提案されました。 今までは単一であることが前提であった「IP」が1つから2つへと変わったのです。

IPv6の登場によって「IP」の部分が2種類に増えたものの、「IP部分はIPv4だけ」という前提で設計されているソフトウェアや環境は世界中に溢れていることもあり、いきなり世界中のすべてをIPv6へと移行させることはできません。また、IPv4用に既にある物理回線と並行して、IPv6専用の物理回線を世界中に敷設するのは現実的ではありません。

そこで、IPv4とIPv6の両方を同時に運用するという設計になりました。 IPv4とIPv6は同じ物理回線を共有することができます。 同じ物理回線上にIPv4のパケットと、IPv6のパケットを両方流すことができるように設定すれば、ひとつの物理接続でIPv4とIPv6の両方同時に使えます。 「www.example.com」といった名前空間も、IPv4とIPv6で同じものが共有されます。

たとえば、「www.example.com」WebサーバをIPv4とIPv6の両方で運用するとき、WebサーバはIPv4のTCPポートと、IPv6のTCPポートの両方でユーザからのリクエストを待つ事になります。 これは、IPv4とIPv6が別々のプロトコルだからです。

IPv4/IPv6共存技術(移行技術)

IPv4とIPv6は全く別のプロトコルであることがNAT64とDNS64などの技術が生まれた背景にあります。 IPv4とIPv6の間には、直接的な互換性がないのですが、何とかして同時に使いたいという要望があり、IPv4とIPv6の共存技術というものが作られました。

最初の方に作られたのは、IPv4を経由してIPv6インターネットに接続するための技術でした。

IPv6の標準が作られた当初は、IPv6インターネットは非常に小規模でした。 その当時、IPv4インターネットが世界中に急速に拡大する一方で、IPv6インターネットは「島」のように点在するIPv6ネットワークをつないだような状態でした。 それぞれの「IPv6島」をつなぐのに使われていたのがIPv4トンネルです。 IPv4パケットの中にIPv6パケットをカプセル化し、IPv4トンネルを経由してIPv6ネットワークへとつなぐという手法です。 いまでは利用が推奨されないものもありますが、IPv4トンネルを経由してIPv6インターネットへと接続する技術として、6to4、Teredo、ISATAP、6rdなどの技術があります。

IPv6インターネットへと接続する環境が整っていくと、IPv4とIPv6を同時に運用するときにコストを削減する方法をどのように実現するのかという議論が活発になりました。 その代表的なものとしてあげられるのが、米国Comcastで使われているDS-Lite(Dual Stack Lite)です。 DS-Liteは、基幹ネットワークをIPv6のみで構成しつつ、IPv4のためのIPv6トンネルを使うことで、ユーザに対してIPv4とIPv6の両方を提供できるというものです。

DS-Liteは、ユーザに対してIPv4ネットワークを提供しますが、ユーザに対してIPv6だけを提供しつつもIPv4インターネットと通信を行える方法も作られました。 IPv6パケットをIPv4パケットへと変換して通信できるようにするNAT64などの技術です。

NAT64、SIIT、DNS64

IPv6インターネットは急速な勢いで拡大していますが、この文章を執筆している時点ではIPv4インターネットの方が規模が大きく、IPv6でアクセス可能なサーバよりもIPv6でアクセスできないサーバの方が多いです。 そのため、IPv6インターネットへのアクセスだけでは、いわゆる「インターネット」を利用できているとは言い難いともいえます。

そこで考えられたのが、ユーザに対してIPv6だけを提供しつつ、IPv6とIPv4を変換することでIPv4インターネットとの通信も同時に実現するという方法です。 IPv6とIPv4の変換が必要になるのは、IPv4とIPv6が全く異なるプロトコルであるためです。

もともとは、NAT-PT(Network Address Translation - Protocol Translation)という方式がRFC化されていましたが、NAT-PTは様々な問題点を抱えていたため2007年に廃止されました。NAT-PTに変わって標準化されたのがNAT64、SIIT(Stateless IP/ICMP Translation Algorithm)、DNS64です。

NAT64、SIIT、DNS64を使うためのフレームワークは、RFC 6144(Framework for IPv4/IPv6 Translation)で解説されていますが、そこでは、IPv4とIPv6の変換を、IPv6移行のための戦略であると書かれています。 さらに、IPv6を利用しつつも、既存のIPv4インターネットに接続された機器との通信を行える環境を実現するとあります。

RFC 6144には、IPv4ネットワーク、IPv4インターネット、IPv6ネットワーク、IPv6インターネットの組み合わせで以下の8つのシナリオが記載されています。

  • シナリオ1: IPv6ネットワークからIPv4インターネットへ
  • シナリオ2: IPv4インターネットからIPv6ネットワークへ
  • シナリオ3: IPv6インターネットからIPv4ネットワークへ
  • シナリオ4: IPv4ネットワークからIPv6インターネットへ
  • シナリオ5: IPv6ネットワークからIPv4ネットワークへ
  • シナリオ6: IPv4ネットワークからIPv6ネットワークへ
  • シナリオ7: IPv6インターネットからIPv4インターネットへ
  • シナリオ8: IPv4インターネットからIPv6インターネットへ

iOSアプリなどの開発や、世界各地の携帯電話サービスなどで使われるのは、この中のシナリオ1です。

シナリオ1は、IPv4アドレス在庫枯渇に伴ってユーザが利用するホストに対してIPv6 onlyなネットワークを提供しつつ、そのIPv6ネットワークからIPv4インターネットとの通信も行えるようにするというものです。

シナリオ1では、IPv6とIPv4のプロトコル変換を行いつつ、名前解決にはDNS64が使われます。 IPv4パケットとIPv6パケットのIPヘッダを変換するための手法がSIITです。

各通信セッションのステート(state/状態)を保持しつつプロトコル変換を行うときには、NAT64が使われます。 NAT64は、SIITを使ってIPヘッダのプロトコル変換を行いつつ、IPv4 NATのようにステートを管理します。

IPv4 NATのおさらい

IPv4とIPv6のプロトコル変換というコンテキストで「ステートフル」や「ステートレス」といったときに、ステートフルというのは、複数のパケットをフロー(flow)として扱い、各フローに関する情報をステート(状態)として保持するというものです。フローの識別には、TCP、UDP、ICMPなどのヘッダが使われることが多いです。

ステートレスというのは、複数のパケットをフローとして扱わず、流れてくるパケットを識別せずに機械的に扱う方式です。

NAT64は、家庭用SOHOルータなどで行われているIPv4 NATと同様にステートフルな方式です。 NAT64の話に入る前に、まずはIPv4 NATのおさらいをしましょう。

IPv4 NATは、家庭内にあるプライベートIPv4アドレスのLAN内で流れるパケットを、グローバルIPv4アドレスで運用されるIPv4インターネット用に変換しています。IPv4からIPv4への変換です。

日本で一般向けの商用インターネット接続サービスが開始された1990年代前半頃は、今のようにNATを使っていませんでした。コンピュータに接続されたモデムを通じてアクセスポイントまで電話をかけると、インターネットに接続できるダイアルアップ接続が主流だったので、1つの電話回線で同時にインターネットにつなげるパソコンは1台だけというのが普通でした。

パソコンもインターネットとともに普及しました。インターネットが普及し始めた当初は、一家に1台パソコンがあれば最先端な家庭でしたが、そのあと、複数台のパソコンを家庭内で使いたいという要求が増えていきました。従量課金の電話ではなく、ISDNやADSLなどによるインターネットへの常時接続サービスが増えていったという背景もあります。

しかし、特別な契約をしない限り、ISPがユーザに対して提供するIPアドレスは1つだけです。そしてIPv4アドレスが1つだけだと、インターネットに直接つなぐことができる機器は1つだけです。

そこで登場するのが、NAT機能を持ったルータです。家庭用の簡易なNATルータは「SOHOルータ」と呼ばれたりしています。NATルータは、1つのIPアドレスで複数の機器をインターネットと通信可能にします。本来ならば1台しかつなげないところを、NATルータが仲介することによって複数の機器が通信できるようになるのです。

一般的に、NATルータのLAN側でプライベートIPv4アドレスによるネットワークが運用されますが、プライベートIPv4アドレスをパケットの送信元もしくは宛先にしたパケットをインターネットで転送することはできません。 プライベートIPv4アドレスというのは、あくまでプライベートな空間だけで利用されるものであり、インターネットで扱ってはならないのです。

そこで、NATルータは、IPv4パケットに含まれるヘッダを書き換えて、あたかも一台の機器がインターネットにつながっているように見せかけます。

一般的な家庭用NATルータが書き換えるのは、IPv4ヘッダだけではありません。 TCPやUDPのヘッダも書き換えます。TCPやUDPなどのトランスポート層プロトコルに属するヘッダも書き換えるのは、利用されるグローバルIPv4アドレスがひとつだけだからです。 たとえば、家庭内LANで10.0.0.11というプライベートIPv4アドレスと、10.0.0.22というプライベートIPv4アドレスの2台の機器が繋がれていたとします。それらの機器が同時に203.0.113.99というグローバルIPv4アドレスで運用されたWebサーバとTCPで通信したときに、10.0.0.11と10.0.0.22の送信元TCPポート番号が両方とも11111になったときに、NATルータが変換するのがIPv4ヘッダだけだと、LAN内の2台の機器のうちのどちらのTCPセッションであるか区別ができなくなってしまいます。

このような理由から、NATルータはIPv4ヘッダだけではなく、TCPやUDPヘッダも書き換えます。 さらに、場合によってはパケットが運ぶデータの中身を変更することもあります。 たとえば、FTP(File Transfer Protocol)は通信を行うときにIPv4アドレスをサーバに対して申告します。 NATルータは、LAN内の機器がインターネット側にある機器とFTPを行えるようにするために、TCPセッションの中身も書き換えるのです。 そういったNATの機能は、ALG(Application Level Gateway)と呼ばれています。(NAT64に関連するALGに関してはRFC 6384をご覧ください:An FTP Application Layer Gateway (ALG) for IPv6-to-IPv4 Translation)

SIIT

NAT64は、SIITを利用しています。

SIITでは、IPv4とIPv6の変換を行う機器をXLATと呼んでいます。

SIITは、IPv4ヘッダやIPv6ヘッダに含まれるフィールドを解説しつつ、変換を行うときの対応付けを定義しています。 IPv4とIPv6は全く異なるプロトコルなのであるため、IPv4-IPv6変換は、IPv4とIPv6プロトコルの差異を考慮しつつ、IPヘッダの変換を行う必要があります。

変換時に、IPv4とIPv6のプロトコルの違いがあるフィールドもあります。 たとえば、IPv4のTotal LengthフィールドはIPv4ヘッダとオプションを含む長さですが、 IPv6のPayload LengthはIPv6ヘッダを含みません。 こういった差異を吸収しつつ、変換が可能な方法をSIITは定義しているのです。

ICMPの扱いも、SIITの大きな要素です。 ただし、IPv4のICMPとIPv6のICMPv6は仕組みが異なるため、変換することが不可能なものもあります。 また、IPv4ではIGMPであったものがIPv6ではICMPv6に含まれるなどの違いもあります。

NAT64

SIITは、IPとICMPのフィールドをどのように対応付けるかを解説しただけです。 そのため、IPv4 NATと同じようなことをIPv4とIPv6の変換で行おうと思ったときには、SIITを行いつつも、各セッションのステートを管理することが必要になります。

そういったことを行う方法を規定しているのがNAT64です。

NAT64を行うトランスレータ(XLAT)は、IPv4のネットワークインターフェースとIPv6のネットワークインターフェースを持ちます。 IPv4側から受け取ったパケットはIPv6へと変換され、IPv6側から受け取ったパケットはIPv4へと変換されます。

NAT64トランスレータは、変換を行うためにIPv4アドレスプールとIPv6アドレスプールを持っています。 RFC 6144のシナリオ1に記載された用途では、IPv4側のアドレスプールとしてグローバルIPv4アドレスが利用され、IPv6側のアドレスプールとしてはNAT64トランスレータ用のIPv6プレフィックスが使われます。

NAT64トランスレータ用のIPv6プレフィックスとしてのデフォルト値は、RFC 6052に記載されている「64:ff9b::/96」が利用されます。(他のIPv6プレフィックスを設定することもできます。)

このようにすることで、NAT64トランスレータ用のIPv6プレフィックスを宛先とするIPv6パケットはNAT64トランスレータに転送され、他のIPv6アドレス宛のパケットは通常のIPv6ルータに転送されるようなネットワークを構築できます。

NAT64トランスレータはIPヘッダに含まれるIPv4アドレスをIPv6アドレスに変換する必要があります。 その変換方法は、RFC 6052に規定されています。

「64:ff9b::/96」が利用される場合、IPv6アドレスのIID(Interface Identifier)部分となる残りの32ビットに通信相手のIPv4アドレスが埋め込まれます。 たとえば、「192.0.2.33」というグローバルIPv4アドレスを持つ相手と通信を行う場合、IPv6ネットワーク側では「192.0.2.33」が埋め込まれた「64:ff9b::192.0.2.33」というIPv6アドレスが利用されます。

DNS64

NAT64+DNS64は、ユーザ側の環境に変更を行わずにIPv6のみでIPv4機器と通信を行えることが大きな特徴です。 それを実現するために、DNSに細工をしているのがDNS64です。

IPv4とIPv6は名前空間を共有しているため、DNSに細工をしつつNAT64を利用することで、IPv6のみを使いつつもIPv4と通信を行える仕組みが実現できています。

「インターネットはひとつである」という考え方もあるために、「名前」に関してはIPv4とIPv6をあえて混ぜた状態で設計されています。このように、ふたつなのだけどひとつであり、別物であると同時に同じものであるという非常にややこしくもあります。

そういった「ふたつであるがひとつである」部分を仮想的に実現しているのがDNSです。 たとえば、www.example.comという名前に対してIPv4とIPv6の両方を登録することができます。

Webでの通信を例として考えると、http://www.example.com/ というURLとの通信を行うときに、IPv4で通信をしているのか、それともIPv6で通信をしているのかに関わらず、ユーザが見たいのはwww.example.comのWebページなのです。

NAT64+DNS64が提供されているIPv6ネットワークのユーザは、キャッシュDNSサーバとしてDNS64機器を設定します。 DNS64機器は、ユーザからのリクエストに応じて名前解決を行いますが、IPv6アドレスを示すAAAAレコードがある場合にはそのままそれを返し、IPv4アドレスを示すAレコードしか存在しない場合にはRFC 6052で定義されている方法でIPv4アドレスが埋め込まれたIPv6アドレスを返します。

DNS64機器がAAAAレコードを返すので、IPv6環境のみを持つユーザは、そのAAAAレコードで示されるIPv6アドレスに向けた通信を開始します。 これにより、IPv4のみで運用されているWebサイトもNAT64を経由してIPv6でブラウズできるようになります。

NAT64+DNS64は、ユーザが使う機器に対して特別な設定は必要ありませんが、NAT64+DNS64の環境でIPv6のみを利用するユーザが、IPv4インターネットに接続された機器と通信を行うには、DNS64を経由する名前解決が必要なのです。

IPv6対応が行われている一般的なユーザ環境では、通信相手の名前を解決する作業が行われ(getaddrinfo)、その結果に応じてIPv4で通信を行うのか、それともIPv6で通信を行うのかを個々のアプリケーションが判断します。 たとえば、http://192.0.2.33/ のようにIPv4アドレスがそのまま埋め込まれている場合には、DNS64を経由せずにIPv4アドレスが得られてしまうため、IPv6のみで運用されているネットワークでNAT64を経由してIPv4インターネットと通信を行うことができなくなってしまいます。

2015年に行われたAppleのWWDC 15で、IPv4環境のみで動作するようなコードが含まれるアプリケーションが、NAT64+DNS64環境で動作しないのは、IPv6のみの環境でIPv4ソケットを通じた通信が行えないことと同時に、DNS64を利用せずにIPv4ソケットを選択してしまうという要素もあります。

Webサーバ側はNAT64+DNS64に対応するためにどうすればいいの?

この記事を最初に書こうと思ったのは、NAT64+DNS64に関連して、Webサーバ側で何をどうすれば良いのかという疑問を持った知り合いがいたからです。

まず、NAT64+DNS64を利用しているユーザとの通信を行うために、Webサーバ側が何か特別なことをする必要はありません。 NAT64+DNS64は、IPv4で運営されている機器に対してIPv6 onlyな環境から通信できるようにするための仕組みなので、IPv4で運営されているWebサーバが何もしなくても通信は行えるのです。

ただし、IPv4とIPv6は直接の互換性がない異なるプロトコルなので、環境や設定によってはNAT64+DNS64を利用して通信を実現できないことも発生します。

そういった問題が発生したときに、Webサーバ側がIPv6対応を行えば、NAT64+DNS64を経由せずにIPv6でユーザと直接通信を行えるようになるという回避手段として考えられます。NAT64+DNS64は、IPv6で通信できない相手と通信するための手段なので、IPv6と通信できる相手とはIPv6で直接通信を行うためです。(凄く後ろ向きですが、どうしてもNAT64+DNS64ユーザとうまく通信できない場合の回避手段として考えられるということで。)

以上、NAT64+DNS64について書いてみました。ざっくりしている部分と細かい部分の差が多少激しい文章になってしまいましたが、足りない部分などがあれば、また違った記事として文章を書くかも知れません。

NAT64+DNS64の限界

NAT64+DNS64は、NATの一種なので、NATが抱える問題点をそのまま抱えています。 また、IPv4とIPv6の差異もあるため、フラグメンテーションに関連するパケットや、IPv6ヘッダオプションが付属したものなど変換できないものもあります。

あくまで無理矢理IPv6環境でIPv4インターネットに接続する方式だと思った方が良さそうです。

おまけ

(*1) DS-Liteという名前は任天堂DS Liteと同じで紛らわしいのですが、その名前の考案者は私がインタビューで質問するまで気がついてませんでした。 (参考)

(*2) DS-Liteが作られた後に、MAP-E(Mapping of Address and Port with Encapsulation)、MAP-T(Mapping of Address and Port using Translation)、464XLATなどの技術も開発されています(ただし、464XLATはNAT64などの既存技術を組み合わせたものです)。

(*3) 拙著「ポートとソケットがわかればインターネットがわかる」の9章でIPv6の紹介をしていますが、今回書いているNAT64やDNS64の話は書籍中に含まれていません。

   このエントリをはてなブックマークに登録