なぜVPNは「ポート4500」を必要とするのか?:NATトラバーサルの泥臭い仕組みと実務デバッグ
ネットワークエンジニアとして現場を渡り歩いていると、避けて通れないのが「NAT(Network Address Translation)の壁」です。自宅のルーターや会社のファイアウォール。これらはプライベートIPアドレスをグローバルIPアドレスに変換し、限られたIP資源をやりくりする現代のインフラの功労者ですが、セキュリティの文脈において、時としてVPNトンネルの最大の破壊者となります。
特に、インターネット経由で本社と拠点、あるいはリモートワーカーと社内ネットワークを安全に結ぶIPsec VPNにおいて、NATは致命的な問題を引き起こしてきました。
「あれ、SA(Security Association)のネゴシエーションは成功するのに、いざESP(Encapsulating Security Payload)パケットが流れると通信がブラックホールに消える……」
そんな現場のトラブルシューティングで、あなたを幾度となく救ってきたのが、今回スポットを当てる UDPポート4500番、すなわち NATトラバーサル(NAT-T) の仕組みです。
今回は、パケットがNATルーターをどのようにすり抜けていくのか、そのカプセル化の裏側と、実務で役立つデバッグの勘所を徹底的に解説していきます。
—
1. なぜIPsecはNAT環境で壊れてしまうのか?
根本的な原因を理解するために、まずはIPsecの標準的な動作(NATがない世界)を思い出してください。
IPsecは、レイヤー3(ネットワーク層)で動作するセキュリティプロトコルです。主に以下の2つのプロトコルを組み合わせて使います。
- IKE (Internet Key Exchange): UDPポート500を使い、暗号化鍵の交換や認証を行う(コントロールプレーン)。
- ESP (Encapsulating Security Payload): プロトコル番号50を使い、実際のデータ本体を暗号化してカプセル化する(データプレーン)。
ここで問題になるのが ESP(プロトコル番号50) です。TCPやUDPのような「ポート番号」という概念がESPには存在しません。そのため、一般的な家庭用ルーターや安価なブロードバンドルーターのNAPT(Network Address Port Translation)機能は、パケットのペイロード内にあるIPアドレスやポート書き換えを行おうとした際、ESPパケットを正しくハンドリングできず、捨ててしまうか、変換テーブルの維持に失敗するのです。
さらに、IKEの初期ネゴシエーション(Main Mode / Aggressive Mode)において、パケット(ISAKMP)のペイロード内に送信元の「プライベートIPアドレス」がそのまま書き込まれてしまいます。NATルーターを通過すると、宛先サーバー側には「ルーターのグローバルIP」が見えるのに、パケットの中身には「192.168.x.x」というルーティング不可能なプライベートIPが記載されているという矛盾が生じ、SAの確立すら頓挫することになります。
この絶望的な状況を打破するために設計されたのが、UDPポート4500番を用いたNATトラバーサル(NAT-T) です。
—
2. UDPポート4500番とNAT-Tの仕組み:カプセル化の正体
NAT-Tがやっていることは、一言で言えば「ESPパケットをUDPパケットで包み込む(カプセル化する)」ということです。
ルーターが解釈できないプロトコル番号50(ESP)のままだからいけないのであって、どのルーターでも喜んでフォワーディングしてくれる「UDPパケット」の姿に偽装してしまおう、というわけです。
通信の全体像とポートの遷移
1. IKEフェーズ1 / フェーズ2の初期段階(UDP 500)
通信の最初期は、標準通り UDPポート500 でIKEのネゴシエーションを行います。この時、パケットのやり取りの中で、通信経路のどこかにNATが存在するかどうかを双方が検出します(NAT Discovery)。
2. NATの検出とポートの切り替え(UDP 4500)
NATが存在することが判明すると、通信当事者(イニシエーターとレスポンダー)は、以降のIKEメッセージおよびデータ通信のポートを UDPポート4500番 へ切り替えることに合意します。
3. UDPカプセル化されたESPの送受信
データ通信が始まると、IPsecのESPパケットの外側に、さらに UDPヘッダー(送信元・宛先ともに4500番) と UDP-Encapsulation-Header(4バイトのゼロパディング) が付与され、その外側に通常のIPヘッダーが乗る形になります。
+-------------------------------------------------+
| Outer IP Header (グローバルIPアドレス) |
+-------------------------------------------------+
| UDP Header (Src Port: 4500, Dst Port: 4500) | <-- ★ここが肝!ルーターがNATできる
+-------------------------------------------------+
| UDP-Encapsulation-Header (4バイトの「0」) | <-- IKEとESPを識別するための目印
+-------------------------------------------------+
| Original ESP Packet (SPI, 認証データなど) |
+-------------------------------------------------+
| Inner IP Header (プライベートIPアドレス) |
+-------------------------------------------------+
| Payload (暗号化された実データ) |
+-------------------------------------------------+
この構造により、途中のNATルーターは「なんだ、普通のUDP 4500番の通信か」と勘違いして、ポート番号の変換(NAPT)とステートフルのセッション管理を完璧にこなしてくれます。パケットは無事に海を渡り、対向のVPNゲートウェイに到達できるというわけです。
—
3. 実務で役立つ設定例とパラメータ解説
では、実際のインフラ構築や設定において、このNAT-T(UDP 4500)がどのように扱われているのかを見てみましょう。ここでは、実務でよく使われるLinuxの強力なIPsec実装である StrongSwan の設定ファイル(ipsec.conf)を例に取ります。
StrongSwanの設定例 (/etc/ipsec.conf)
config setup
# プラグインのロードや全体設定
strictcrlpolicy = no
uniqueids = yes
conn %default
# 共通の暗号化アルゴリズムやライフタイムの設定
keyexchange = ikev2
ike = aes256gcm16-prfsha512-ecp384!
esp = aes256gcm16-ecp384!
ikelifetime = 24h
salifetime = 8h
dpddelay = 30s
dpdaction = restart
conn corporate-vpn-nat-t
type = tunnel
authby = pubkey
# 自拠点の識別子(NAT配下のため、グローバルIPではなくFQDNやIDを指定することが多い)
left = %defaultroute
leftid = @client.example.com
leftcert = client_cert.pem
# 本社VPNゲートウェイのグローバルIP
right = 203.0.113.195
rightid = @vpn.example.com
rightsubnet = 10.100.0.0/16
# NAT-Tを強制、あるいは自動検知させるパラメータ
# 強制的にUDP 4500を使う場合は "forceencaps=yes" を指定することもある
auto = start
実務で知っておくべき重要パラメータ
forceencaps=yes:
通常、StrongSwanなどのIKEv2実装はNATの存在を自動検知(NAT-D)して動的にUDP 4500へ切り替えますが、厳格なステートフルファイアウォールやプロキシが前面にいる環境では、検知がうまくいかないことがあります。そんな時はこのパラメータを有効にし、最初から強制的にUDP 4500でカプセル化させることで、無用なネゴシエーションのタイムアウトを防ぐことができます。
- Keepalive(キープアライブ):
NATルーターには、一定時間通信がないとセッションテーブルのエントリを削除する「UDPタイムアウト」の仕様(通常30秒〜1分程度)があります。NAT-T環境下では、VPNのデータが流れていない間も、UDP 4500番を使って定期的にダミーパケット(Keepalive)を送信し、ルーターのNATセッションを維持し続ける必要があります(多くのモダンなIPsec実装ではデフォルトで有効になっています)。
—
4. 現場のトラブルシューティング:パケットキャプチャとデバッグの極意
「設定は入った、証明書も正しい。なのにトンネルが上がらない、あるいはデータが流れない」
そんな修羅場でエンジニアが取るべき具体的なデバッグ手順を授けましょう。
ステップ1: tcpdump でパケットの生死を確認する
まずは、VPNゲートウェイやクライアント端末のインターフェースでパケットをキャプチャします。UDP 500とUDP 4500が正しく流れているかを確認するのが鉄則です。
# インターフェース(例: eth0)でIKE(500)とNAT-T(4500)のトラフィックをキャプチャする
sudo tcpdump -nnvv -i eth0 "port 500 or port 4500"
- チェックポイント:
- IKEフェーズ1のパケット(ISAKMP)がUDP 500で飛んでいるか?
- ネゴシエーションの途中で、ポートが
4500に切り替わっているか? - 相手からの返答(レスポンス)が返ってきているか?(ここで返ってきていない場合、途中のファイアウォール(FW)でUDP 4500がブロックされている可能性が極めて高いです)。
ステップ2: ファイアウォールとセキュリティグループの確認
クラウド環境(AWSのSecurity GroupやAzureのNSG、GCPのファイアウォールルールなど)でインフラを構築している場合、よくあるミスが「UDP 500だけ許可して、UDP 4500を空け忘れていた」というケースです。
- 必須で許可すべきインバウンドルール:
- プロトコル:
UDP - ポート範囲:
500(IKE用) - ポート範囲:
4500(NAT-T用)
※AWSのEC2などでIPsecサーバーを立てる場合、インスタンスの「送信元/宛先チェック(Source/Destination Check)」を無効化し忘れて通信がデバッグできない、というのも古典的かつ頻出の罠なので合わせて確認してください。
ステップ3: デーモンのログを詳細に出力する
StrongSwanなどのログレベルを上げて、NAT-D(NAT Detection)がどのように判定を下したかを確認します。
# StrongSwanのログレベルを一時的に最大にする(syslogやjournalctlで確認)
sudo swanctl --log --level 2
ログの中に NAT-T検出 や peer is behind NAT といったキーワードが出現していれば、システムは正しくNAT環境を認識し、UDP 4500への移行を試みています。逆にここでエラーが出ている場合は、アイデンティティ(ID)の設定ミスの可能性が高いです。
—
まとめ
VPNの裏側で静かに、しかし確実仕事をこなしている UDPポート4500番(NAT-T)。
「なぜポートが500から4500に変わるのか」
「なぜESPをわざわざUDPで包み直す必要があるのか」
この物理的・論理的なパケットの挙動さえ頭にインプットされていれば、いざ現場で「トンネルが張れない」という悪夢のようなアラートを受け取った時でも、迷いなく tcpdump を叩き、ファイアウォールの穴を見つけ出し、スマートに問題を解決できるはずです。
ゼロトラスト時代の現代においても、安全な拠点間接続やレガシーシステムとの統合においてIPsecの重要性は揺るぎません。泥臭いネットワークの基礎知識を武器に、堅牢なインフラを守り抜きましょう。
コメント