Mímisbrunnr知恵の泉

← コンピュータネットワーク 一覧

🎓 レベル:標準 | 重要度:A(必須) 📎 前提:IPアドレスの基礎(IPv4)

要点(BLUF)

なぜNATが要るのか

プライベートアドレス(10.x192.168.x等)はインターネットでは一意でないため、そのままでは外部と通信できません。グローバルIPは希少で高価。そこで出口のルータで、内側の私設IPを外向きのグローバルIPに付け替え、戻りは逆変換します。これでグローバルIPを節約しつつ全端末が外へ出られます。

NATの種類

種類変換用途
静的NAT1対1固定公開サーバ(外から特定IPで届かせたい)
動的NATプールから1対1で動的グローバルIPが複数あるとき
PAT(オーバーロード)多対1(ポートで区別)一般家庭/企業の出口・最頻出

PAT:1つのグローバルIPに集約

PATは、複数の内部端末の通信を、送信元ポートを付け替えて1つのグローバルIPにまとめます。戻りパケットはポート番号で「どの内部端末宛か」を引き当てます。

graph LR
  A["PC-A 192.168.1.10:51514"]
  B["PC-B 192.168.1.11:51515"]
  R["NATルータ(変換表を保持)"]
  N["インターネット(宛先 203.0.113.9:443)"]
  A --> R
  B --> R
  R -->|"203.0.113.1:40001 など"| N

変換表のイメージをPythonで作ります(言語明示)。

# PAT: (内部IP, 内部ポート) を 1つのグローバルIP + 一意な外部ポート へ写像
inside = [("192.168.1.10", 51514), ("192.168.1.11", 51515),
          ("192.168.1.10", 51520)]
global_ip = "203.0.113.1"
table = {}
next_port = 40001
for ip, port in inside:
    table[(ip, port)] = (global_ip, next_port)
    next_port += 1
for k, v in table.items():
    print(f"inside {k[0]}:{k[1]}  ->  outside {v[0]}:{v[1]}")
print("使用グローバルIP数:", len({v[0] for v in table.values()}))

実行結果:

inside 192.168.1.10:51514  ->  outside 203.0.113.1:40001
inside 192.168.1.11:51515  ->  outside 203.0.113.1:40002
inside 192.168.1.10:51520  ->  outside 203.0.113.1:40003
使用グローバルIP数: 1

3つの内部フローが、たった1つのグローバルIPに、別々の外部ポートで同居しています。同じPC-Aの2フローも外部ポートが違うので区別できます。

設定例(Cisco IOS・PAT)

! 内部/外部インターフェースを宣言
Router(config)# interface Gi0/1
Router(config-if)# ip nat inside
Router(config)# interface Gi0/0
Router(config-if)# ip nat outside

! 変換対象をACLで指定し、外部インターフェースのIPへオーバーロード
Router(config)# access-list 1 permit 192.168.1.0 0.0.0.255
Router(config)# ip nat inside source list 1 interface Gi0/0 overload

確認:

Router# show ip nat translations

他層との関係と限界

PATはL4のポートを使ってL3の不足を補う、層をまたいだ工夫です。代償として:

なぜポートで多重化できるのか(設計の直観)

1つのグローバルIPでも、ポート番号は約6万5千通りあります。**「IPは1つでも、IP:ポートの組なら膨大に作れる」**ため、各内部フローに一意な外部ポートを割り当てれば衝突せず集約できます。トランスポート層の多重化([[04-03_ポートとソケット]])を、アドレス節約に転用したのがPATです。

⚠️ よくある誤解

対応 lab

関連