4-6 NAT/PAT — プライベートとグローバルを変換する仕組み
inside と outside の向きでアドレスを変換する NAT を扱う。static/dynamic/PAT の 3 方式と、変換テーブルに現れる 4 象限 (inside local/global・outside local/global) を csr1000v で検証し、変換後・変換前の両方に戻り経路が要る勘所を実機で確かめる。
1. 前節の振り返りと本節の内容
前節 4-5 ZBF では、インターフェースをゾーンにまとめ、ゾーン間の通信をゾーンペアの向きでステートフルに制御する Zone-Based Firewall を扱いました。inside から outside へ出た通信をセッションとして記憶し、その戻りを自動で許可する一方、outside 発の新規通信は既定 deny で遮断する、という 向き と 状態 (セッション) の考え方が中心でした。
本節で扱う NAT (Network Address Translation) も、この 2 つの考え方を引き継ぎます。NAT は、内部で使うプライベートアドレスと、外部で使うグローバルアドレスを 変換 する仕組みです。ここでも inside と outside という向き が中心になります。内部から外部へ出る通信では送信元アドレスを内部の実アドレスから変換後のアドレスへ書き換え、外部から戻ってくる通信では宛先アドレスを逆に書き換えて内部へ戻します。ZBF がセッションを記憶して戻りを通したのと同じように、NAT も変換の対応を 変換テーブル に記憶し、戻りの通信を逆変換します。
NAT が生まれた背景には、IPv4 アドレスの枯渇があります。世界中の機器に一意のグローバルアドレスを配るには IPv4 の 32 ビットは足りず、組織内ではプライベートアドレス (RFC1918 の 10.0.0.0/8 / 172.16.0.0/12 / 192.168.0.0/16) を使い、外部と通信するときだけ限られたグローバルアドレスに変換する、という運用が広まりました。本節では csr1000v 3 台を使い、Static NAT (1:1 の固定変換)・Dynamic NAT (プールからの動的割り当て)・PAT (1 つのグローバルアドレスをポート番号で多重化) の 3 方式を、実機の show ip nat translations の出力とともに検証します。あわせて、外部から内部の特定サービスを公開する Static PAT (ポートフォワーディング)、プールを使い切ったときの挙動、そして NAT で最も嵌まりやすい 戻り経路 の設計を扱います。
2. なぜ変換が要るのか — プライベートアドレスと inside/outside/local/global
NAT を理解する第一歩は、同じ 1 台のホストが、見る場所によって違うアドレスで呼ばれる ことを受け入れることです。内部から見た内部ホストのアドレスと、外部から見た同じホストのアドレスは異なります。NAT はこの「場所による呼び名の違い」を管理する仕組みで、Cisco はこれを inside/outside (内部か外部か) と local/global (変換前か変換後か) の 2 軸、計 4 象限で整理します。
- Inside Local — 内部から見た内部ホストの実アドレス。組織内で実際に設定されているプライベートアドレスです。
- Inside Global — 外部から見た内部ホストのアドレス。NAT で変換された後のグローバルアドレスで、外部にはこのアドレスとして見えます。
- Outside Local — 内部から見た外部ホストのアドレス。
- Outside Global — 外部から見た外部ホストの実アドレス。
本節のラボでは外部ホスト (R3) 側は変換しないため、Outside Local と Outside Global は同じ値になります。観察の焦点は左 2 象限、すなわち Inside Local (内部の実アドレス) が Inside Global (変換後のアドレス) にどう変換されるか に集約されます。この 2 象限の対応が show ip nat translations に 1 行ずつ現れる様子を、本節を通じて追いかけます。
用語で注意したいのは、local と global は「プライベート/パブリック」と必ずしも一致しない ことです。local は「変換前 (NAT の内側から見た値)」、global は「変換後 (NAT の外側から見た値)」を指す相対的な呼び名であり、アドレスが RFC1918 かどうかとは別の概念です。本節では教材として分かりやすくするため、Inside Local に RFC1918 のプライベートアドレス、Inside Global にグローバルアドレスを割り当てますが、この対応は「そう設定したから」であって、local/global の定義そのものではない点を押さえておきます。
3. ラボトポロジ
本節の検証で使うトポロジを示します。csr1000v 3 台を直列につなぎ、中央の R2 に NAT を適用します。
トポロジの構成は以下のとおりです。
- R1 (内部ホスト) — Loopback10 に
192.168.10.1、Loopback11 に192.168.11.11、Loopback12 に192.168.12.12を持ちます。いずれも RFC1918 のプライベートアドレスで、Inside Local を表す内部ホストの代わりです。R2 への Gi2 に10.12.0.1を持ちます。 - R2 (NAT ルータ) — R1 への Gi2 に
10.12.0.2を持ち、これをip nat insideに指定します。R3 への Gi3 に10.23.0.1を持ち、これをip nat outsideに指定します。この 2 つのインターフェースが「変換の境界」になります。 - R3 (外部サーバ) — Loopback20 に
198.51.100.1を持ち、ip http serverで TCP80 を待ち受けます。外部の通信相手 (宛先) を表します。
アドレスは、内部プライベートに RFC1918 の 192.168.x.0/24 を、変換後のグローバルと外部サーバの見立てには RFC5737 のドキュメント用ブロック (203.0.113.0/24 = TEST-NET-3 を変換後のグローバル、198.51.100.0/24 = TEST-NET-2 を外部サーバ) を割り当てています。CML は実インターネットではないため、これらはすべて同じラボ内のアドレスで、「グローバルに見立てている」だけです。この点は §5 の戻り経路の設計で重要になります。
R1・R2・R3 のリンクと Loopback0 は OSPF area 0 で相互に広告し、透過的な疎通の土台を作っています。ただし後述するように、R1 の 192.168.x.0/24 は意図的に OSPF で広告しません。これが NAT の前提を作ります。R3 が学習している経路を確認します。
show ip route
10.0.0.0/8 is variably subnetted, 6 subnets, 2 masks
O 10.0.1.1/32 [110/3] via 10.23.0.1, 00:03:50, GigabitEthernet2
O 10.0.2.1/32 [110/2] via 10.23.0.1, 00:03:50, GigabitEthernet2
C 10.0.3.1/32 is directly connected, Loopback0
O 10.12.0.0/30 [110/2] via 10.23.0.1, 00:03:50, GigabitEthernet2
C 10.23.0.0/30 is directly connected, GigabitEthernet2
L 10.23.0.2/32 is directly connected, GigabitEthernet2R3 は R1・R2 の Loopback0 やリンク (10.x) を OSPF で学習していますが、R1 の内部プライベート 192.168.x.0/24 はここに現れません。R3 から見て、内部ホストの実アドレスは存在しないのと同じです。この状態が NAT の出発点になります。
4. NAT なしでは届かない — 変換の動機
NAT を設定する前に、内部ホストから外部サーバへ ping を撃ってみます。R1 の Loopback10 (192.168.10.1) を送信元にして、R3 の 198.51.100.1 へ ping します。
ping 198.51.100.1 source Loopback10 repeat 5
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 198.51.100.1, timeout is 2 seconds:
Packet sent with a source address of 192.168.10.1
.....
Success rate is 0 percent (0/5)..... (ドット 5 つ) で、成功率は 0 パーセントです。届きません。理由は §3 で確認したとおり、R3 が送信元の 192.168.10.1 への戻り経路を持たない ためです。R1 が送った ICMP echo は R3 まで届きますが、R3 が返そうとする echo reply は宛先が 192.168.10.1 であり、R3 はこのプライベートアドレスへの経路を知りません。行きは届いても帰りが返せない、という状態です。
これが NAT の動機です。プライベートアドレスをそのまま外部に出しても、外部はその実アドレスへの戻り方を知りません。そこで、外部と通信するときだけ送信元をグローバルアドレスに変換し、外部からはそのグローバルアドレスとしてやりとりする必要があります。以降、この変換を 3 つの方式で構築していきます。
5. 戻り経路の設計 — 変換後と変換前の両方に経路が要る
NAT の設定に入る前に、最も嵌まりやすい 戻り経路 を先に押さえます。NAT は送信元・宛先を書き換えるため、パケットの往復が異なるアドレスで評価されます。このため、変換後のアドレス と 変換前のアドレス の両方に、それぞれ戻る経路が必要になります。
内部ホスト 192.168.10.1 からの通信を、R2 が 203.0.113.5 (グローバル) に変換して外へ出すとします。このとき戻りのために必要な経路は 2 本です。
- R3 (外部) に、変換後アドレス
203.0.113.0/24への経路 — R3 が受け取るパケットの送信元は203.0.113.5です。R3 が応答を返すには、この203.0.113.0/24を R2 (Gi3 =10.23.0.1) へ向ける経路が要ります。 - R2 に、変換前アドレス
192.168.x.0/24への経路 — R2 は外部から戻ってきた203.0.113.5宛のパケットを192.168.10.1に逆変換した後、内部へ送る必要があります。ところが §3 で192.168.x.0/24を OSPF で広告しないようにしたため、R2 自身もこのプライベート網への経路を失います。そこで R2 に、変換前アドレスへの経路を明示的に用意します。
本ラボでは、この 2 本を static route で作ります。R2 には変換前アドレス (内部プライベート 3 網) への経路を、R3 には変換後アドレス (グローバルプール) への経路を置きます。
! R2: 逆変換後に内部プライベートへ戻すための経路 (R1 = 10.12.0.1 向き)
ip route 192.168.10.0 255.255.255.0 10.12.0.1
ip route 192.168.11.0 255.255.255.0 10.12.0.1
ip route 192.168.12.0 255.255.255.0 10.12.0.1! R3: 変換後アドレス宛の応答を R2 へ返すための経路 (R2 = 10.23.0.1 向き)
ip route 203.0.113.0 255.255.255.0 10.23.0.1R2 の 3 本の static route は R2 のローカルな経路であり、OSPF で R3 に広告されません。したがって R3 は内部プライベートを知らないまま (NAT の前提を保ったまま)、R2 だけが逆変換後の戻り先を知っている状態になります。
NAT の設定を入れても通信が成立しないとき、多くの場合この戻り経路が原因です。変換テーブルには行が載る (変換自体は起きている) のに ping だけが返らない という症状が出たら、show ip route で変換後アドレスと変換前アドレスの両方に経路があるかを確認するのが定石です。この「往復で異なるアドレスに経路が要る」ことこそ、NAT がステートレスなルーティングと決定的に違う点です。
6. Static NAT — 1 対 1 の固定変換
最初の方式は Static NAT です。1 つの内部アドレスを 1 つのグローバルアドレスに固定で対応づけます。R2 に次の 1 行を設定します。
ip nat inside source static 192.168.10.1 203.0.113.5ip nat inside source static <内部> <グローバル> は、内部から外部へ出る通信 (inside source) の送信元を、192.168.10.1 から 203.0.113.5 へ静的に変換する、という意味です。設定した瞬間から、この対応は変換テーブルに常設されます。同じ ping をもう一度撃ってみます。
ping 198.51.100.1 source Loopback10 repeat 5
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 198.51.100.1, timeout is 2 seconds:
Packet sent with a source address of 192.168.10.1
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/1/2 ms!!!!! (感嘆符 5 つ) で成功率 100 パーセントです。§4 で 0 パーセントだった同じ ping が、Static NAT を 1 行入れただけで通るようになりました。R1 が送る送信元 192.168.10.1 が R2 で 203.0.113.5 に変換され、R3 は 203.0.113.5 を送信元として受け取ります。R3 が 203.0.113.5 宛に返す応答は、§5 で用意した戻り経路を通って R2 に戻り、R2 が宛先を 192.168.10.1 に逆変換して R1 へ届けます。この 0 パーセントから 100 パーセントへの反転が、NAT が何をしているかを最も端的に示しています。
変換テーブルを確認します。
show ip nat translations
Pro Inside global Inside local Outside local Outside global
--- 203.0.113.5 192.168.10.1 --- ---
icmp 203.0.113.5:1 192.168.10.1:1 198.51.100.1:1 198.51.100.1:1
Total number of translations: 22 行あります。1 行目は Pro 列が --- で、Inside global = 203.0.113.5 と Inside local = 192.168.10.1 の対応だけを示し、Outside 列は --- です。これは Static NAT の常設マッピング で、通信の有無に関わらず設定した時点から存在します。2 行目は Pro = icmp で、実際に流れた ICMP のフローを表す動的なエントリです。こちらは Outside 列に相手の 198.51.100.1 が入り、送信元・宛先の 4 象限がすべて埋まっています。「--- 行 = 常設の対応」「プロトコル行 = 実際に流れたフローのセッション」という 2 種類のエントリの違いを、この出力で押さえておきます。
7. Dynamic NAT — プールから動的に割り当てる
Static NAT は 1 対 1 の固定対応でしたが、内部ホストが多いと 1 つずつ静的に書くのは現実的ではありません。Dynamic NAT は、グローバルアドレスの プール (pool) を用意し、内部ホストが通信を始めたときに空いているアドレスを動的に割り当てます。R2 に次のように設定します。
ip access-list standard NAT-INSIDE
permit 192.168.0.0 0.0.255.255
!
ip nat pool GLOBALPOOL 203.0.113.20 203.0.113.29 netmask 255.255.255.0
!
ip nat inside source list NAT-INSIDE pool GLOBALPOOLまず、変換対象の内部アドレスを ACL NAT-INSIDE で指定します。ここでは 3 つの内部網 (192.168.10/11/12.0/24) をまとめて 192.168.0.0 0.0.255.255 で拾っています。NAT が参照する ACL は permit した範囲を「変換する」 という意味で、ACL のようにトラフィックを遮断するわけではない点に注意します。次に ip nat pool で変換後に使うグローバルアドレスの範囲 (203.0.113.20〜203.0.113.29 の 10 個) を定義します。最後の ip nat inside source list <ACL> pool <プール名> が、「ACL にマッチした内部アドレスを、プールから割り当てたグローバルアドレスに変換する」という指定です。
Static NAT と違い、Dynamic NAT の対応は 通信が始まるまで存在しません。設定直後の変換テーブルを見ます。
show ip nat translations
Total number of translations: 0空です。ここで R1 の Loopback10 (192.168.10.1) と Loopback11 (192.168.11.11) から順に ping を撃ち、もう一度テーブルを見ます。
show ip nat translations
Pro Inside global Inside local Outside local Outside global
--- 203.0.113.20 192.168.10.1 --- ---
--- 203.0.113.21 192.168.11.11 --- ---
icmp 203.0.113.20:2 192.168.10.1:2 198.51.100.1:2 198.51.100.1:2
icmp 203.0.113.21:3 192.168.11.11:3 198.51.100.1:3 198.51.100.1:3
Total number of translations: 4通信を始めた 2 つの内部ホストに、プールの先頭から順に 203.0.113.20・203.0.113.21 が割り当てられました。ここが Dynamic NAT の要点で、overload を付けていないこの設定では、内部ホスト 1 つにつきグローバルアドレスを 1 つ、1 対 1 で割り当てます。3 台目の内部ホストが通信を始めればプールの 3 番目 203.0.113.22 が割り当てられ、プールを使い切ると次のホストは変換できなくなります (この限界は §9 で確認します)。
プールの使用状況は show ip nat statistics で確認できます。
show ip nat statistics
Total active translations: 4 (0 static, 4 dynamic; 2 extended)
...
Dynamic mappings:
-- Inside Source
[Id: 1] access-list NAT-INSIDE pool GLOBALPOOL refcount 4
pool GLOBALPOOL: id 1, netmask 255.255.255.0
start 203.0.113.20 end 203.0.113.29
type generic, total addresses 10, allocated 2 (20%), misses 0pool GLOBALPOOL の行に total addresses 10, allocated 2 (20%) とあり、10 個中 2 個 (20 パーセント) を割り当て済みと分かります。プールの消費状況を把握する重要な出力です。
8. PAT — 1 つのアドレスをポート番号で多重化する
Dynamic NAT は内部ホスト 1 つにグローバル 1 つを割り当てるため、同時に通信できる内部ホスト数がプールのアドレス数で頭打ちになります。これでは IPv4 の節約という目的を十分には果たせません。そこで登場するのが PAT (Port Address Translation) です。PAT は、1 つのグローバルアドレスを、送信元ポート番号で多重化 することで、多数の内部ホストを 1 つのアドレスに集約します。Cisco の設定では overload キーワードで有効化するため、NAT overload とも呼ばれます。
最も実務的な設定は、変換後アドレスに 出口インターフェースのアドレスをそのまま使う 形です。R2 に次のように設定します。
ip nat inside source list NAT-INSIDE interface GigabitEthernet3 overloadinterface GigabitEthernet3 overload は、「ACL にマッチした内部アドレスを、Gi3 のアドレス (10.23.0.1) に変換し、ポート番号で多重化する」という指定です。プールを別途用意する必要がなく、ルータが外部に持つ 1 つのアドレスだけで内部の多数を賄えます。R1 の Loopback10・Loopback11 の両方から ping と TCP80 への接続を行い、変換テーブルを見ます。
show ip nat translations
Pro Inside global Inside local Outside local Outside global
tcp 10.23.0.1:5063 192.168.11.11:11266 198.51.100.1:80 198.51.100.1:80
tcp 10.23.0.1:5062 192.168.10.1:37889 198.51.100.1:80 198.51.100.1:80
icmp 10.23.0.1:11 192.168.11.11:11 198.51.100.1:11 198.51.100.1:11
icmp 10.23.0.1:10 192.168.10.1:10 198.51.100.1:10 198.51.100.1:10すべての Inside global が 同じ 10.23.0.1 になっています。そして各行はポート番号 (または ICMP の識別子) が異なります。2 つの内部ホスト 192.168.10.1 と 192.168.11.11 が、どちらも 10.23.0.1 に変換されつつ、TCP なら送信元ポート (5062 と 5063)、ICMP なら識別子 (10 と 11) で区別されています。これが PAT の多重化です。1 つのグローバルアドレスに、理論上はポート番号の数だけフローを載せられます。
ここで TCP のポート番号が書き換えられている ことに注目します。1 行目の TCP は内部側が 192.168.11.11:11266 で、変換後が 10.23.0.1:5063 です。アドレスだけでなく ポート番号も 11266 から 5063 へ書き換わっています。PAT は、複数の内部ホストが偶然同じ送信元ポートを使っても衝突しないように、変換後のポートを付け替えます。多重化を成立させるための仕組みです。
3 つのプロトコルの追跡 — ICMP は識別子で区別する
PAT が扱うのは TCP だけではありません。TCP・UDP・ICMP の 3 つを同時に流したときの変換テーブルを見ます。
show ip nat translations
Pro Inside global Inside local Outside local Outside global
tcp 10.23.0.1:5062 192.168.10.1:23042 198.51.100.1:80 198.51.100.1:80
udp 10.23.0.1:5063 192.168.10.1:49162 198.51.100.1:33437 198.51.100.1:33437
icmp 10.23.0.1:12 192.168.10.1:12 198.51.100.1:12 198.51.100.1:12
udp 10.23.0.1:5062 192.168.10.1:49161 198.51.100.1:33436 198.51.100.1:33436TCP と UDP は、それぞれの ポート番号 で多重化されます (TCP の 23042 が 5062 に、UDP の 49161 が 5062 に、というように書き換わります)。一方、ICMP にはポート番号がありません。ping (ICMP echo) はポートを使わないため、PAT は ICMP パケットの Identifier フィールド を擬似的なポートとして使い、フローを区別します。この例では icmp 10.23.0.1:12 の 12 が Identifier で、内部側の 192.168.10.1:12 の 12 と一致していますが、これはポート番号ではなく識別子である点に注意します。PAT はプロトコルごとに「何を使ってフローを区別するか」を変えており、ポートを持たない ICMP では識別子で代用しているわけです。
9. プールを使い切ると — Dynamic NAT の限界
§7 の Dynamic NAT (overload なし) は内部ホストとグローバルアドレスを 1 対 1 で割り当てるため、プールを使い切ると次のホストは変換できません。これを実際に起こしてみます。プールを 2 個だけ (203.0.113.20〜203.0.113.21) に絞り、overload なしで、内部ホスト 3 台から順に通信を始めます。
! 1 台目 (192.168.10.1) → 203.0.113.20 が割り当てられる
Success rate is 100 percent (3/3), round-trip min/avg/max = 1/1/2 ms
! 2 台目 (192.168.11.11) → 203.0.113.21 が割り当てられる
Success rate is 100 percent (3/3), round-trip min/avg/max = 1/1/2 ms
! 3 台目 (192.168.12.12) → プールが空でない
Success rate is 0 percent (0/3)1 台目・2 台目は成功しますが、3 台目は 0 パーセントで失敗 します。プールの 2 個をすでに使い切っているため、3 台目に割り当てるグローバルアドレスが無く、変換できずに通信が成立しません。show ip nat statistics で状況を確認します。
show ip nat statistics
Hits: 10 Misses: 2
...
[Id: 1] access-list NAT-INSIDE pool GLOBALPOOL refcount 4
pool GLOBALPOOL: id 1, netmask 255.255.255.0
type generic, total addresses 2, allocated 2 (100%), misses 3
In-to-out drops: 0 Out-to-in drops: 0pool GLOBALPOOL の行が total addresses 2, allocated 2 (100%) となっています。プールの 2 個をすべて割り当て済み (100 パーセント) で、これが枯渇の直接の証拠です。あわせて misses 3 は、変換しようとしたが割り当てられなかった回数を示します。プールが枯渇したとき、Cisco は専用の派手なログを出すわけではなく、静かに変換に失敗して通信が落ちる だけです。だからこそ、allocated (100%) を主な手がかりとして把握することが運用上重要になります。この限界を解くのが、§8 の PAT (ポートで多重化) だったわけです。
10. Static PAT — 外から内の特定サービスを公開する
ここまでは内部から外部への通信 (inside から outside) を扱いました。逆に、外部から内部の特定のサービスへアクセスさせたい 場合があります。内部の Web サーバを外部に公開する、といったケースです。これを実現するのが Static PAT (ポートフォワーディング) です。特定のグローバルアドレスの特定ポート宛の通信を、内部の特定ホストの特定ポートへ転送します。R2 に次のように設定します。
ip nat inside source static tcp 192.168.10.1 80 203.0.113.10 80 extendableip nat inside source static tcp <内部> <内部ポート> <グローバル> <グローバルポート> は、「外部から 203.0.113.10 の TCP80 宛に来た通信を、内部の 192.168.10.1 の TCP80 へ転送する」という指定です。末尾の extendable は、同じグローバルアドレスを複数のポートフォワードで共有できるようにするオプションです。この設定も Static NAT と同様、通信の前から変換テーブルに常設されます。
show ip nat translations
Pro Inside global Inside local Outside local Outside global
tcp 203.0.113.10:80 192.168.10.1:80 --- ---
Total number of translations: 1tcp 203.0.113.10:80 ← 192.168.10.1:80 の対応が、通信の前から 1 行載っています。ここで外部の R3 から、公開アドレス 203.0.113.10 の TCP80 へ接続してみます。
Trying 203.0.113.10, 80 ... Open
Server: openrestyOpen となり、TCP セッションが確立しました。外部の R3 が 203.0.113.10:80 へ送った通信が、R2 で 192.168.10.1:80 に変換され、内部の Web サーバに到達しています。一方、公開していない別のポート (たとえば TCP23) へ接続しようとすると、変換テーブルに対応が無いため到達しません。Static PAT は「公開したポートだけ」を外部に開ける仕組みで、それ以外は内部に届かないという点が、セキュリティ上も重要です。
なお、これは outside から inside への通信であり、NAT の変換順序が内部発とは逆になります。内部発 (inside → outside) では「ルーティングで出口を決めてから送信元を変換」しますが、外部発 (outside → inside) では「宛先を先に変換してから内部へルーティング」します。Static PAT が成立するのは、外部から届いた宛先 203.0.113.10 を、ルーティングの前に 192.168.10.1 へ変換できるからです。
11. NAT の変換をアニメーションで追う
Static NAT の変換と戻りの逆変換を、時間を追って可視化します。
PAT の多重化も同様に追います。
12. NAT の位置づけ — セキュリティ機能ではない
本章のここまでで扱った ACL・ZBF はトラフィックを許可・拒否するセキュリティ機能でした。NAT はそれらと同じ第 4 章に置いていますが、NAT の一次的な目的はセキュリティではなくアドレスの変換 (IPv4 の節約と接続性の確保) です。この違いを整理します。
| 項目 | ACL | ZBF | NAT/PAT |
|---|---|---|---|
| 一次目的 | トラフィックの許可・拒否 | ステートフルな境界防御 | アドレス変換 (枯渇対策・接続性) |
| 状態を持つか | 持たない (ステートレス) | 持つ (セッション) | 持つ (変換テーブル) |
| 「向き」の定義 | インターフェース + 方向 (in/out) | ゾーン間 (zone-pair の向き) | inside / outside の向き |
| セキュリティ機能か | ○ | ○ | × (副次的な効果はある) |
NAT には、内部のプライベートアドレスを外部から隠す アドレス隠蔽 の副次効果があります。外部からは変換後のグローバルアドレスしか見えず、内部の構成が直接は分かりません。しかしこれをセキュリティの主軸にするのは危険です。第一に、Static NAT や Static PAT で外部に穴を開けた瞬間、その隠蔽効果は消えます (§10 で 203.0.113.10:80 を公開したとおりです)。第二に、内部発の通信に便乗する戻りは通してしまい、ペイロードの中身は検査しません。したがって「NAT があるからファイアウォールは要らない」という考えは誤りです。境界の防御は ACL や ZBF の仕事であり、NAT はアドレス変換の仕事です。両者は同じ R2 の上で役割を分けて共存します。
第 4 章を通じて、4-1 ACL の in/out、4-5 ZBF の zone-pair、そして本節の inside/outside と、通信を制御する 向き の概念が繰り返し現れました。ZBF のセッションテーブルと NAT の変換テーブルは、どちらも「往きを覚えて戻りを扱う」状態機械であるという点でも共通しています。制御するもの (通信の可否か、アドレスの変換か) は違っても、向きと状態でネットワークを設計する考え方は一貫しています。
13. 次節
本節では、プライベートアドレスとグローバルアドレスを変換する NAT を扱いました。NAT なしでは内部プライベートが外部に届かないこと (§4)、Static NAT が 1 対 1 の固定変換を常設マッピングとして持つこと (§6)、Dynamic NAT がプールから 1 対 1 で動的に割り当てること (§7)、PAT が 1 つのグローバルアドレスをポート番号で多重化すること (§8)、プールを使い切ると静かに変換に失敗すること (§9)、Static PAT が外部から内部の特定サービスを公開すること (§10) を、csr1000v の show ip nat translations の出力で確認しました。とりわけ、NAT は変換後・変換前の両方のアドレスへの戻り経路が要る (§5) という点が、ステートレスなルーティングと NAT を分ける勘所です。
次節 4-7 IPsec 基礎 では、通信を暗号化して保護する IPsec を扱います。ここで NAT が伏線になります。IPsec は経路上でパケットのヘッダを守るため、NAT が経路の途中でヘッダ (アドレスやポート) を書き換えると、IPsec の検証が壊れてしまいます。この矛盾を解く NAT-T (NAT Traversal) の仕組みを含め、NAT と暗号化がどう両立するかを次節以降で見ていきます。
10.0.0.0/8 / 172.16.0.0/12 / 192.168.0.0/16)を使って、外と通信するときだけ限られたグローバルアドレスに変換する ── これが広まったんだ。192.168.x の RFC1918)、R3 が外部サーバ(198.51.100.1)。R2 の Gi2(R1 方向)を ip nat inside、Gi3(R3 方向)を ip nat outside に指定する。この 2 つが「変換の境界」だ。ここで大事な仕込みが 1 つ ── R1 の 192.168.x.0/24 は意図的に OSPF で広告しない。これが NAT の前提を作る。NAT を入れる前に、R1 の 192.168.10.1 から R3 の 198.51.100.1 へ ping すると……
ping 198.51.100.1 source Loopback10 repeat 5
Sending 5, 100-byte ICMP Echos to 198.51.100.1, timeout is 2 seconds:
.....
Success rate is 0 percent (0/5)0%。届かない。理由は ── R1 が送った ICMP は R3 まで届くんだが、R3 が返そうとする応答の宛先は 192.168.10.1 で、R3 はこのプライベートアドレスへの戻り方を知らない。行きは届いても帰りが返せないんだ。
192.168.10.1 を 203.0.113.5 に変換して外へ出すとする。① R3 に、変換後 203.0.113.0/24 への経路 ── R3 が受け取るパケットの送信元は 203.0.113.5 だから、応答を返すにはこの網を R2 へ向ける経路が要る。② R2 に、変換前 192.168.x.0/24 への経路 ── R2 は外から戻ってきた 203.0.113.5 宛を 192.168.10.1 に逆変換して内部へ送る。ところが 192.168.x を OSPF で広告しなくしたから、R2 自身もこの網への経路を失ってる。だから明示的に static route を置く。show ip route で変換後と変換前の両方に経路があるか確認するのが定石だ。この「往復で違うアドレスに経路が要る」ことが、NAT がふつうのステートレスなルーティングと決定的に違う点なんだ。じゃあ変換方式を 3 つ、順に組んでいくぞ。Static NAT ── 1 つの内部アドレスを 1 つのグローバルに固定で対応づける。R2 に 1 行だ。
ip nat inside source static 192.168.10.1 203.0.113.5これで、さっき 0% だった同じ ping が 100% で通る。R1 の送信元 192.168.10.1 が R2 で 203.0.113.5 に化けて、R3 は 203.0.113.5 を送信元として受け取る。R3 の応答は戻り経路を通って R2 に戻り、R2 が宛先を 192.168.10.1 に逆変換して R1 へ届ける。0% → 100% のこの反転が、NAT が何をしてるかを一番端的に示してる。
2 行出る。
show ip nat translations
Pro Inside global Inside local Outside local Outside global
--- 203.0.113.5 192.168.10.1 --- ---
icmp 203.0.113.5:1 192.168.10.1:1 198.51.100.1:1 198.51.100.1:11 行目は Pro 列が --- で、Inside global ↔ Inside local の対応だけ ── これが Static NAT の常設マッピングで、通信の有無に関わらず設定した時点から存在する。2 行目は Pro = icmp で、実際に流れた ICMP フローの動的エントリで 4 象限が全部埋まってる。「--- 行 = 常設の対応」「プロトコル行 = 実際に流れたフローのセッション」の 2 種類がある、と押さえろ。
ip nat pool でグローバルの範囲を定義し、ip nat inside source list <ACL> pool <プール名> で結ぶ。1 個注意 ── NAT が参照する ACL は permit した範囲を「変換する」という意味で、遮断するわけじゃないぞ。Total number of translations: 0 で空だ。R1 の 2 つの Loopback から ping を撃つと、プールの先頭から 203.0.113.20・203.0.113.21 が順に割り当たる。ここが Dynamic の要点で ── overload を付けてないこの設定は、内部ホスト 1 つにつきグローバル 1 つ、1 対 1 で割り当てる。3 台目は 3 番目のアドレス、そしてプールを使い切ると次のホストは変換できなくなる。それを実際に起こしてみよう。プールを 2 個だけに絞って、内部ホスト 3 台から順に通信すると ── 1 台目・2 台目は 100%、3 台目は 0% で失敗する。統計を見ると……
show ip nat statistics
[Id: 1] pool GLOBALPOOL: total addresses 2, allocated 2 (100%), misses 3allocated 2 (100%) ── プールを使い切ってる。これが枯渇の直接の証拠だ。misses 3 は変換しようとして割り当てられなかった回数。ここが怖い ── Cisco は派手なログを出すわけじゃなく、静かに変換に失敗して通信が落ちるだけなんだ。
allocated (100%) を主な手がかりにして把握する。で、この 1 対 1 の頭打ちを解くのが 3 つ目 ── PAT(Port Address Translation)だ。1 つのグローバルアドレスを、送信元ポート番号で多重化して、多数の内部ホストを 1 つのアドレスに集約する。Cisco では overload キーワードで有効化するから NAT overload とも呼ぶ。実務的なのは、変換後に出口インターフェースのアドレスをそのまま使う形だ。
ip nat inside source list NAT-INSIDE interface GigabitEthernet3 overloadGi3 のアドレス(10.23.0.1)に変換してポート多重化する。プールを別に用意する必要すらない。2 つの内部ホストから ping と TCP80 を流して変換テーブルを見ると、全部の Inside global が同じ 10.23.0.1 で、各行のポート番号だけが違う。
tcp 10.23.0.1:5063 192.168.11.11:11266 198.51.100.1:80 198.51.100.1:80
tcp 10.23.0.1:5062 192.168.10.1:37889 198.51.100.1:80 198.51.100.1:80192.168.11.11:11266 なのに変換後が 10.23.0.1:5063 りん。ポート番号も 11266 から 5063 に書き換わってるりん?icmp 10.23.0.1:12 の 12 が Identifier だ。ポート番号じゃなく識別子だぞ。TCP/UDP はポート、ICMP は Identifier ── PAT はプロトコルごとに「何でフローを区別するか」を変えてる。ポートを持たない ICMP では識別子で代用してるわけだ。Static PAT(ポートフォワーディング)だ。内部の Web サーバを外部に公開する、みたいなケースだな。特定のグローバルアドレスの特定ポート宛を、内部の特定ホストの特定ポートへ転送する。
ip nat inside source static tcp 192.168.10.1 80 203.0.113.10 80 extendable「外部から 203.0.113.10 の TCP80 宛に来たら、内部の 192.168.10.1 の TCP80 へ転送」だ。これも常設マッピングで、通信の前からテーブルに載る。外の R3 から 203.0.113.10:80 へ接続すると Open になる。公開してない別のポート(例えば 23 番)は対応が無いから届かない ── これがセキュリティ上も重要で、Static PAT は「公開したポートだけ」開ける仕組みなんだ。
203.0.113.10 を、ルーティングの前に 192.168.10.1 へ変換できるからだ。順序が逆なんだ。203.0.113.10:80 を公開したろ、あれで内部の存在が外から見えてる。第二に、内部発の通信に便乗する戻りは通してしまうし、ペイロードの中身は検査しない。だから「NAT があるからファイアウォールは要らない」は誤りだ。境界の防御は ACL や ZBF の仕事、NAT はアドレス変換の仕事。両者は同じ R2 の上で役割を分けて共存するんだ。