NAT/NAPTについて(書きかけ)

定義

 広義のNAT(ナット; Network Address Translation; ネットワークアドレス変換)の説明としては、RFC 2663(3. What is NAT?)に次のような記述がある。

ネットワークアドレス変換は、種々のホストに対して透過的ルーティングを提供するときに、種々のIPアドレスが、一方のアドレス領域からもう一方へと対応付けられる方法である。様々なアプリケーションに対して適切にアドレス変換を行う多くの変種が存在するが、NAT機器に分類されるものは、すべからく次のような性質を持っているべきである。

a) 透過的にアドレスを割り当てる。
b) アドレス変換により透過的にルーティングを行う(ここでいうルーティングは、パケットを転送することをいい、経路情報を交換することをいうのではない)。
c) ICMPエラーパケットの積荷(payloads)の変換を行う。

 ここに挙げた最初の文(「ネットワークアドレス変換は…方法である。」)が広義のNATの定義だともとれるが、少々漠然としていてわかりづらい。
 なかなか単純に定義しにくい概念ではあるが、この説明も踏まえて、広義のNATとは、一応

  1. NAT機器によりパケットが転送されるときに
  2. ホストから見て自動的(透過的)に行われる
  3. パケット中のIPアドレスの書き換え処理であって
  4. ローカルアドレスをグローバルアドレスで表現する形のもの

のことと定義しておく。

 NAPT(ナプト; Network Address Port Translation; ネットワークアドレスポート変換)は、広義のNATであって、IPアドレスだけでなく、TCP/UDPのポート番号(TU ports)も書き換えることにより、複数のローカルIPアドレスを一つのグローバルIPアドレスに書き換えられるようにしたものをいう。
 NAPTという用語は、RFC 2663で導入されたものだが、Linuxの動的NAPT相当機能であるIPマスカレード(IP masquerade)が比較的早い時期に普及していたことと、おそらくはNAPTという言葉の語呂が相対的に悪いことから、思ったほど普及しておらず、IPマスカレードとか、単にNATとかと呼ばれることも多い。その他にも、ENAT、NAT+、PAT、Port-level NAT、NAT overloadなど様々な呼称がある。本稿ではNAPTという用語を使う。

 狭義のNATは、広義のNATのうち、IPアドレスのみを書き換えるもの(チェックサムなどの付随的書き換えを除く)、特に、NAPTと異なりポート番号を書き換えないものをいう。本稿では、特に断らない限り、NATという用語を狭義のNATの意味で使い、広義のNATはNAT/NAPTと表す。ただし、複合語となった場合には、RFC 2663などの用例に従いNAT/NAPTを単にNATと表すこともある。

 なお、NAT機器(a Network Address Translator, a NAT device/box)という意味でNATという略語が用いられる場合があるが(例えばRFC 1631)、本稿ではそのような用法を採らない。ちなみに、英語ではおおむね、可算名詞としてのNATはNAT機器を、不可算名詞としてのNATは変換機能としてのNATを指すから、比較的容易に区別が可能であるが、日本語では曖昧になりがちである。

 NAT-PT(Network Address Translation - Protocol Translation)は、広義のNATの拡張であり、IPv6アドレスとIPv4アドレスの間でアドレス(及びプロトコル)の変換を行うものであるが、本稿では触れない(RFC 2766で定義されている)。

内部・外部とローカル・グローバル

 NAT/NAPT機器が、2つのネットワークに接続してそれらの間でNAT/NAPTを行う場合、ユーザは、一方のネットワークを内部ネットワーク(an inside network)又は内側ネットワーク(an inner network)、もう一方のネットワークを外部ネットワーク(an outside network)又は外側ネットワーク(an outer network)と定義しなければならない。
  本稿では、NAT/NAPTのうち、内部ネットワークのアドレスを書き換えるものを内部NAT/NAPT、外部ネットワークのアドレスを書き換えるものを外部NAT/NAPTということにする。また、本稿では、内部NAT/NAPTのみを行うNAT/NAPTを単純NAT/NAPTと呼び、外部NAT/NAPTのみを行うNAT/NAPTを逆NAT/NAPTと呼ぶことにする。 内部NAT/NAPTと外部NAT/NAPTを同時に行うものは一般に両変換NAT(twice NAT)という。多くのNAT/NAPT実装は単純NAT/NAPTのみをサポートする。

 内部ネットワーク内で使われるアドレス体系に従ったアドレスをローカルアドレス(a local address)といい、外部ネットワーク内で使われるアドレス体系に従ったアドレスをグローバルアドレス(a global address)という。あるアドレス体系に従うとは、そのアドレス体系に従うもの同士ではアドレスの重複が起こらないことが保証されていることをいう。なお、ここでいうグローバルアドレスという用語は、一般に使われるのと異なり、NIC(a Network Information Center)から割り当てられた、インターネット(the Internet)上で利用可能なアドレスという意味ではない点に注意する。
 単純NAT/NAPTでは、さらに個々の内部ネットワークから見てローカルアドレスとグローバルアドレスとが同一のアドレス体系に従わなければならないが、この種のNAT/NAPTでは外部ネットワークに対してローカルアドレスが隠蔽されるので、独立した複数の内部ネットワークがそれぞれNAT/NAPT機器により外部ネットワークに接続されているとき、それらの内部ネットワークのローカルアドレス同士では同一のアドレス体系に従う必要がない。外部ネットワークに対してローカルアドレスが隠蔽されるということは、外部ネットワーク内のホストでは、パケットの処理にあたり、ローカルアドレスの存在を考慮する必要がないことを意味する。内部ネットワークが独立しているとは、他の内部ネットワークとの間で通信を行うことがないことをいう。
 両変換NATでは、ローカルアドレスとグローバルアドレスとが同一のアドレス体系に従う必要はない。つまり、両変換NATは重複するアドレスを持つネッワーク間でNAT/NAPTを行える。

  内部ネットワーク内にあるホスト(正確にはそのインタフェースだが、以下では一々断らない)のローカルアドレスを内部ローカルアドレスといい、外部ネットワーク内にあるホストのグローバルアドレスを外部グローバルアドレスという。
 また、内部NAT/NAPTにより内部ネットワーク内のホストの内部ローカルアドレスがグローバルアドレスに書き換えられたとき、それを内部ネットワーク内のホストをグローバルアドレスで表現したものと考えて内部グローバルアドレスといい、同様に外部NAT/NAPTにより外部ネットワーク内のホストの外部グローバルアドレスがローカルアドレスに書き換えられたとき、それを外部ネットワーク内のホストをローカルアドレスで表現したものと考えて外部ローカルアドレスという。
 TCP/UDPのポート番号に関しても、同様に内部ローカルポート番号外部グローバルポート番号内部グローバルポート番号及び外部ローカルポート番号を定義することができる。さらに、アドレスとポート番号の組を一般にソケット(a socket)といい(RFC 793)、内部ローカルアドレスと内部ローカルポート番号の組を内部ローカルソケット、外部グローバルアドレスと外部グローバルポート番号の組を外部グローバルソケットなどと同様に定義していくことができる。

 内部・外部とローカル・グローバルの区別に関する以上の用法は、Ciscoの定義に従っている。一般には、この「シスコ用法」でいう内部と同じ意味で、内部とか内側とかプライベートとかローカルとかスタブとかという言葉を区別せずに用い、またシスコ用法でいう外部と同じ意味で、外部とか外側とかグローバルとかという言葉を区別せずに用いることが多い(RFC 2663でもそのように使っている)。しかし、これらを区別した方が便利なことがあるので、本稿ではシスコ用法に従う。

 二つのネットワークの間で単純NAT/NAPTを用いるとき、どちらを内部ネットワークとし、外部ネットワークとするかにより生じる差異は次の通りである。

 逆NAT/NAPTではこの関係が逆になる。両変換NAT/NAPTでは、両方のアドレスが隠蔽され、動的NAT/NAPTはないから、内部ネットワークと外部ネットワークとの間に本質的な差異は生じない。

NAT/NAPTの類型

 NAT/NAPTは内部ネットワークと外部ネットワークの両方に接続するNAT/NAPT機器があることが前提となり、このNAT/NAPT機器の上で処理が行われる。NAT/NAPT機器はNAT/NAPTルータ(a NAT/NAPT router)とも呼ばれる。なお、いわゆる素人が、NAT/NAPT機器という意味でルータという用語を用いることがあるが、本来の意味のルータと紛らわしいので、このような用法は望ましくない。
 NAPTはNATの拡張であり、また、両変換NATは単純NATの拡張だから、まず単純NATの動作の概略に触れる。

単純NAT

単純NATの基本動作

 NAT/NAPT機器は、手持ちグローバルアドレス(a global address pool)とアドレス変換表(an address translation table)という二つのデータ構造を持っている。手持ちグローバルアドレスにはグローバルアドレスを0または1つ以上、アドレス変換表にはアドレスの組を0又は1つ以上登録することができる。アドレス変換表の組には、少なくとも内部ローカルアドレスと内部グローバルアドレスが含まれ、これらの項目から構成される組を重複がない限りいくらでも登録することができる。

  1. NATを利用する前に、まずNATに利用する空きのグローバルアドレスを1つ以上定義して、手持ちグローバルアドレスに登録しなければならない。本稿では、これらのアドレスが、NAT機器の直接接続する外部ネットワークに属するアドレスのときは、それを直接接続型といい、それ以外の場合には、それをルーティング型という。一般には、直接接続型のグローバルアドレスを手持ちグローバルアドレスに登録することが多い。
  2. NATを利用する前に、内部ローカルアドレスと内部グローバルアドレスとからなる組を、アドレス変換表に登録してもよい。このようにして、予めこれらのアドレスの対応をアドレス変換表に登録し、それに従ってアドレスの書き換えを行うNATを静的NAT(static NAT)という。
  3. 内部ネットワーク内のホストが外部ネットワークのホストと通信を開始する。このホストから送信されるとき、パケットヘッダの始点アドレス欄には始点ホストの内部ローカルアドレスが、終点アドレス欄には終点ホストの外部ローカルアドレスがセットされる。単純NATでは、外部ローカルアドレスと外部グローバルアドレスは等しい。従って、外部ネットワークのDNSサーバなどから得たアドレスをそのまま利用して外部ネットワークのホストにアクセスできるという利点が得られる。
  4. 送信されたパケットは、通常のルーティング過程に従ってNAT機器に辿り着く(そうなるように内部ネットワーク内の各機器の経路情報が設定されていなければならない)。
  5. NAT機器は、ユーザが予め設定した条件に従って、そのパケットがNAT対象かどうかを判定する。具体的な方法は実装によって違いがあり得るが、ルーティング処理で決まった出力インタフェースといわゆるアクセスリストを基準として判定することが多い。ただし、Cisco IOSのNATやヤマハRTシリーズのNATディスクリプタは、入力インタフェースとアクセスリストを基準にする。
  6. NAT機器は、NAT対象のパケットのヘッダの始点アドレスを内部ローカルアドレスとして含む組が既にアドレス変換表に登録されているか調べる。それが存在するときは、始点アドレスをその組に含まれる内部グローバルアドレスに書き換える。存在しないときは、手持ちグローバルアドレスから、アドレス変換表にまだ登録されていないものをどれか一つ選び、それを内部グローバルアドレスとして、また、そのパケットの始点アドレスを内部ローカルアドレスとして含む組をアドレス変換表に新しく追加し、その上でパケットの始点アドレスをそのグローバルアドレスに書き換えてもよい。このように、アドレス変換表にない内部ローカルアドレスに対して自動的にグローバルアドレスとの対応を定義してアドレス変換表に追加するNATを動的NAT(dynamic NAT)という。静的NATと動的NATはそれぞれ単独で使用することもできるし、併用することも可能である。
    NAT機器が動的NATの機能を持たない場合には、アドレス変換表にない始点アドレスを持つパケットはNATが不可能となる。また、動的NATの機能を持つ場合でも、手持ちグローバルアドレス中にアドレス変換表にまだ登録されていないものが残っていないときは、やはりNATが不可能となる。これらの場合には、パケットを廃棄し、始点アドレスに向けてICMP Host Unreachableエラーメッセージを送信する。
  7. ルーティング処理で決定される出力インタフェースからパケットを送信する。送信されたパケットは、通常のルーティング過程に従って終点ホストに届く。なお、ルーティングは原則として始点アドレスに拠らないので、実際にはルーティングとNAT処理の前後関係は実装に依存する。
  8. 多くのアプリケーションでは、終点ホストは、届いたパケットへの応答として、新たなパケットを送信する。この新たなパケットの始点アドレス欄には元のパケットの終点アドレス欄のアドレスが、終点アドレス欄には元の始点アドレス欄のアドレスがコピーされる。後者のアドレスはNAT機器の手持ちグローバルアドレスに含まれるアドレスである。
  9. 送信されたパケットは、通常のルーティング過程に従ってNAT機器に辿り着く(そうなるように外部ネットワーク内の各機器の手持ちグローバルアドレスに対する経路情報が設定されていなければならない)。
  10. NAT機器は、受信したパケットの終点アドレス欄にあるアドレスを内部グローバルアドレスとして含む組がアドレス変換表にあるか調べ、もしあれば、そのパケットの終点アドレスをその組の中の内部ローカルアドレスに書き換える。そのような組がないときは、そのパケットはNATの対象にならず、通常は廃棄される。
  11. パケットは通常のルーティング処理に回され、それにより決定された出力インタフェースから内部ネットワークへ送信されて、最終的な宛先である内部ネットワーク内のホストに届く。

 この説明では内部ネットワーク側から通信を始める例を用いたが、静的NATによる場合は、外部ネットワーク側から通信を始めてもなんら問題なくNAT処理を行うことができる。このように、どちらからでも通信が開始されうる単純NAT/NAPTを双方向NAT(bi-directinal NAT, two-way NAT)という。一方、もっぱら内部ネットワーク側から通信を始めるような単純NAT/NAPTは伝統的NATとか旧式NAT(traditional NAT)あるいは外向きNAT(outbound NAT)などという(RFC 3022に詳しい)。また、狭義のNATである旧式NATは基本NAT(basic NAT)という。ちなみに、これらはRFC 2663で定義された用語だが、機能ないし能力を表すものか、使われ方ないし運用形態を表すものかははっきりしない。本稿では機能ないし能力を表すものとする。
 なお、RFC 1631(RFC 3022で廃止になったが)で紹介された初期のNATは、狭義のNATかつ静的な双方向NATであるものであり、最狭義のNATはこれを指す(もっとも、このRFCではトンネリングもNAT機器の機能に含めている)。

 静的旧式NATに類似する機能である住友電工のGapNATは、プライベートネットワークのセグメントにNAT機器と同じグローバルアドレスを持つホストを置き、後述のNAT/NAPT共用機能同様に、未知の接続に属する外部ネットワークからのパケットをそのホストに転送するというアイデアに基づくものであるが、この処理自体はアドレスの書き換えを行わないから、本稿でいうNATとは異なる。NATに関する限り、GapNATは広義のNATを利用する際に併用してそれを回避する機能である。

単純NATの利用例

 NATとNAPTは併用が可能であり、単純NATは単純NAPTとともに補助的に使われることが多い。

単純NAPT

単純NAPTの基本動作

 動作の流れは単純NATと同様なので、単純NATの項を参照されたい。単純NATとの差異は、手持ちグローバルアドレスの代わりに、単なるアドレスではなくソケットを登録する手持ちグローバルソケットが使われ、アドレス変換表の項目もソケットに対するものになるという点である(厳密には、この他にポート番号がどのプロトコルに対するものかも定義する必要がある)。この対応を予めアドレス変換表に登録しておくのは静的NAPT(static NAPT)である。双方向NATである静的NAPTは、静的IPマスカレードとかport forwardingなどとも呼ばれる。内部ネットワークから受け取ったパケットヘッダの始点ソケットを内部ローカルソケットとして持つ組がアドレス変換表に存在しない場合に、NAPT機器が自動的に手持ちグローバルソケット中のグローバルソケットとの対応を定義してアドレス変換表に登録するNAPTは動的NAPT(dynamic NAPT)と呼ばれる。パケットの書き換えは、これらの登録内容に従い、アドレスだけでなくポート番号に対しても行われる。
 狭義のNAPTは旧式NATである単純NAPTを指す。

 NAPTの特長は、一つのグローバルアドレスに対して利用可能な複数のポートを組み合わせてできた組をそれぞれ手持ちグローバルソケットに登録することで、複数の内部ローカルアドレスを一つのグローバルアドレスに多重化し、これによりグローバルアドレスを節約することができることである。一つのグローバルアドレスに多重化できるローカルアドレスの最大数は、プロトコルあたりポート数である216となる。

接続追跡型NAT/NAPT

 現実の実装では、セキュリティの確保や、アドレスの共用(後述)を実現するなどの理由で、狭義のNAPTのアドレス変換表の組は、内部グローバルソケットと内部ローカルソケットの他に、通信の相手方を表す外部グローバルソケットを含むことが多い。この場合、NAPT処理は次のように変更される。

 これらの処理は、本質的には、接続の追跡(connection tracking)を行って、それにより存在が確認されている接続についてのみ外部ネットワークからのパケットの転送を行うことと等しい。従って、本稿ではこれらを接続追跡型NAT/NAPTと呼ぶ。同様にして、これらの処理をNATについて行うことも可能であるが、そうすると静的NATであっても双方向NATにはならない点に注意する。
 なお、ここでいう接続は広義の接続であり、両端ホストのソケットからなるいわゆるソケットペアを指す。

単純NAPTの利用例

 おそらく、現在広義のNATの中で最も広く利用されている類型が単純NAPTである。

アドレスの共用

 多くの実装では、NAPT機器自体の通信のために外部ネットワーク側インタフェースに割り当てられているグローバルアドレスをそのままNAPTの手持ちグローバルソケット中の(直接接続型)グローバルアドレスとして利用できる。これは、インタフェースのアドレスとNAPTのアドレスを共用できることを意味する。具体的には、そのアドレスと全てのポートとの組み合わせを手持ちグローバルソケットに登録し、NAT機器自体の通信にポートが必要となったときは、随時手持ちグローバルソケットから未定義のグローバルソケットを取り除いて、そのポートをその通信に利用するようにすればよい。

 また、単純NATを単純NAPTと併用する場合、手持ちグローバルアドレスはNAT用とNAPT用で分けるのが通常だが、アドレス変換表の組に、前述のように外部グローバルソケットの項目を含んでいれば(つまりNAPTの接続の追跡を行っていれば)、外から内へのパケットについては、既知の接続に属するパケットのみNAPTを、それ以外はNATを行うようにすることで、ここでもアドレスを共用することが可能である(いわゆるDMZ機能の一環として実装される例が多いが、本稿ではNAT/NAPT共用機能という)。外部グローバルソケットと内部グローバルソケットにより接続が追跡されているから、あるポートがNAPTで使用中であっても、外部ネットワークの無関係なホストからのそのポートへのパケットは正しくNATされ、NAPTを利用中の内部ネットワークのホストに誤着信することは避けられる。このアルゴリズムを、NAT/NAPT機器自体の通信のために同一のグローバルアドレスを共用する場合に拡張することは容易であり、結局一つのアドレスを三重に共用することができることになる。
 ただし、動的NAPTにより通信を行っている外部ネットワークのホストからは、その接続で利用中の内部グローバルポートについてはNATを利用することができなくなるという制約が存在する。例えば、外部ネットワークにUDPを使ったストリーミングサーバOsが、内部ネットワークにクライアントIcとDNSサーバIsが、それらネットワークの間にNAT/NAPT機器Nが存在するとする。NではグローバルアドレスGとIsのローカルアドレスLとの組をNAT用のアドレス変換表に登録して双方向の静的NATを行う一方、Gと利用可能な全てのポートとの組み合わせを手持ちグローバルソケットに登録して動的NAPTを行う。まず、IcがOsのストリーミングポートに送信を要求するUDPパケットを送信する。このとき、たまたまNにおいて動的に割り当てられた内部グローバルポートは53番であったとしよう。Osは接続してきたIcのホスト名を確認しようとしたとする。そこでOsのストリーミングサーバプロセスは、同じソケットを利用してIsのUDP53番ポート(DNS)に問い合わせのパケットを送信しようとする。ところが、IsのグローバルアドレスとIcのグローバルアドレスは同じであり、ポートもUDP53番で同じであるために(そして、Osのグローバルソケットも同じであるために)、この問い合わせパケットはNに辿り着いた後、IsでなくNAPTによってIcへ送られてしまう。この例では、GとUDP53番とからなるソケットを予め手持ちグローバルソケットから除いておくことにより不都合を避けることができるが、Isでパケットを受ける必要のあるポートが常に事前にわかるわけではない。

両変換NAT

(今後書く…かも)

 

直接接続型アドレス

 NAT/NAPT機器は、ネットワーク間でパケット転送を行うものだから、ルータの一種だということができる。ただ、単純NAT/NAPTにおいて、直接接続型アドレスが手持ちグローバルアドレスに登録され、それが内部グローバルアドレスとして使われている場合、内部ネットワークへのパケットが外部ネットワークからNAT/NAPT機器に転送される仕組みは、通常のルータと少々異なる。
 通常のルータにおけるルーティングでは、パケット上にルータのアドレスが現れることは原則としてなく、直前のホップのホストが、自身の持つ経路情報中のゲートウェイアドレスに従ってルータにパケットを転送する。NAT/NAPT機器は、そのゲートウェイアドレス(NAT/NAPT機器自体のインタフェースに振られたアドレス)に対してARP応答する。一方、NAT/NAPT対象のパケットのNAT/NAPT機器へのルーティングでは、パケットの宛先に手持ちグローバルアドレス/ソケット中のアドレスが書き込まれ、その宛先に従ってNAT/NAPT機器にパケットが転送される。NAT/NAPT機器は手持ちグローバルアドレス/ソケット中のアドレスに対してARP応答する(代理ARPに似ている)。従って、外部ネットワークからは、NAT/NAPT機器は、そのようなアドレスを持ったホストないしは一種のブリッジのように見える。

 一方、ルーティング型アドレスが使われているときは、NAT/NAPT機器へは通常のルータと同様にルーティングされる。この場合、内部グローバルアドレスはNAT/NAPT機器が接続されているネットワークとは無関係なアドレスブロックに属することになる。これは比較的まれな運用形態と言えるであろう。

IPヘッダ以外の書き換え

 

(未完)