VPNの話題を書いたときにNATについて少し触れましたが、もう少し詳しくNATについて解説します。
なぜ、NATにこだわっているかというと、手持ちのスマートホンと知人のスマートホンの間でどこのサーバにも接続せずに直接ピアツーピアで情報のやり取りがしたいからです。
さらにインターネット上のサーバを経由しないとなれば、例えば移動中の車同士で最新の情報を最小遅延で交換できることになるので、自動運転への貢献も出来るかも知れない。
また、サーバを介さずに通信できるとなれば当該端末上以外に痕跡が残らないので安心して内緒話ができるので、かの某スノーデンさんも亡命せずに済んだかもしれない(勿論、キャリア網内、基地局までの無線区間(特に無料WiFiスポット等)で盗聴されてもいいように暗号化は必要ですが)。
NATの種類
NATとは Network Address Translation の略です。
プライベートIPアドレスを持った端末からインターネットに送信する際にグローバルIPアドレスに変換(またはその逆)する技術のことです。
NATの基本的な知識はウィキペディア等で解説されていますので、そちらも参照してください。
動的NATはNAPTとかNAT-PTとか呼ばれる(何とも味気ない名称。
別名のIP Masqueradeの方が哀愁があってよいですね)方式には Cone 型と Symmetric 型の2種類があります。
1. Cone 型
内部から送信されたパケットのIPアドレスとポート番号はインターネット上のどのサーバに送信しても同じポート番号に置換する。
src 192.168.1.101:12345 | ➡ | src 200.200.200.200:59123 |
dst 1.1.1.1:53 | ➡ | dst 1.1.1.1:53 |
src 192.168.1.101:12345 | ➡ | src 200.200.200.200:59123 |
dst 8.8.8.8:53 | ➡ | dst 8.8.8.8:53 |
2. Symmetric 型
内部から送信されたパケットのIPアドレスとポート番号はインターネット上の
サーバ毎に異なるポート番号に変換する。
src 192.168.1.101:12345 | ➡ | src 200.200.200.200:40515 |
dst 1.1.1.1:53 | ➡ | dst 1.1.1.1:53 |
src 192.168.1.101:12345 | ➡ | src 200.200.200.200:38913 |
dst 8.8.8.8:53 | ➡ | dst 8.8.8.8:53 |
Cone 型についてはインターネット側から受信したときの振る舞い(フィルタリング)に3通りの実装方式があります。
- Full Cone NAT
受信したパケットの宛先ポート番号がNAPTにより変換したポート番号に一致するパケットであれば、全て内部の送信元のアドレスにフォワードする。
- Restrict Cone NAT
受信したパケットの宛先ポート番号がNAPTにより変換したポート番号に一致するパケットで、且つ内部から送信した相手のアドレスからであれば(ポート番号が異なっていてもよい)全て内部の送信元のアドレスにフォワードする。
- Port Restrict Cone NAT
受信したパケットの宛先ポート番号がNAPTにより変換したポート番号に一致するパケットで、且つ内部から送信した相手のアドレスとポートが一致すれば、全て内部の送信元のアドレスにフォワードする。
これらの分類はインターネット業界での便宜上の分類であり厳密には、ポート番号変換方式と受信時のフィルタリング方式の組み合わせで分類するのが正しいでしょう。
実装面で少し補足するとポート番号変換は概ねランダム化されていますが、UDPパケットなどは変換後のポート番号は概ね奇数番号になります。
これはIP電話やビデオ会議などで使用しているプロトコルの RTP (Real Time Protocol) がデータ送信用に奇数番号を用い、制御用に +1 した偶数番号を用いていることに起因しています。
ちなみに Linux PC であれば、簡単に上記のどの NAT 装置も作ることができます。
例えば、Symmetric NAT を作る場合、社内LANが eth0 でインターネット側が eth1 であれば以下のコマンドでOKです。
# iptables -A FORWARD -i eth1 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
# iptables -t nat -A PREROUTING -o eth1 -s 192.168.1.0/24 -j MASQUERADE --random
世の中的には Symmetric 型が1,2割で残りはほぼ Full Cone と Port Restrict Cone 型のどちらかです。
NATはファイアウォール的な役割も担っているのですが、セキュリティ強度的には
(低) Full Cone < Restrict Cone < Port Restrict Cone < Symmetric (高)
ですね。
ping パケットにはポート番号がないのにちゃんと送信元に応答が返ってくるのはどうしている?
これは ICMP ECHO REQUEST ヘッダ内の ID フィールド(8ビット)を送信元毎に変換しているので ping先から受信した ICMP ECHO RESPONSE の ID フィールドに対応する送信元に転送できるわけです( 8ビットしかないので同時256台の制限がありますが支障はないでしょう)。
P2Pの壁
基本的にNAT配下の端末(スマートホン)同士がピアツーピアで通信する場合の手順は概ね以下のシーケンスになり、やっと、9 の時点でNAT配下同士の端末間でハンドシェイクできるようになります。
WebRTC や Nx Cloud でも P2P のために似たようなことを行っています。
(解説)
GWはインターネット上に設置し、STUNサーバの役割とP2P接続のお手伝いをするサーバ
1,2,3,4 は STUN サーバに対してNAT変換後のIPアドレス:ポートを取得する流れ
5,6はAさんからBさんに対してAが待ち受けているアドレス:ポートを連絡する流れ
7はBさんからのパケットを受けるためにダミーのパケットを送信する流れ
8,9 でAさんとBさんの間でダイレクトにパケットの交換ができる
双方のNAPTの種別の組合せによってはこの方式で接続できないケースが2つあります。
- ①Symmetric NAT vs Symmetric NAT
- ②Symmetric NAT vs Port Restrict Cone
基本的にNAT配下の端末(スマートホン)同士がピアツーピアで通信する場合、TCPプロトコルではNATを越えることはできません(TCPは3-Hand shake方式のため、Hole Punchingができない)ので、UDP通信になります。
どうしてもTCP接続したい場合はNAT装置に対してUPnPを使って動的にポートフォワード設定を行うか、もしくはNAT装置の設定画面からポートフォワード設定を追加する必要がありますが、不正アクセスに対する防御設定も必要なるのでお勧めしません。
NAT装置はポート番号変換テーブルを持っていますが、変換したポート番号の寿命がプロトコルによって違います。
UDPパケットの場合はTCPパケットより寿命が短いので、折角UDPで通信していても、しばらくパケットを送信しないと変換テーブルが削除されてしまうので相手からのパケットは破棄されてしまいます。
そのため、同じ相手と長くUDP通信したい場合はキープアライブ的なダミーパケットを送る必要があります。
何に使える?
サーバがなくてもスマホ同士で囲碁・将棋・オセロ等ができるし、情報交換もできるので、作ってみようかな。ガチャしたい人は見向きもしないけどね。