NAT は奥が深い
ここ数年 NAT をがっつり使用するルータの構築案件を何件か対応してきましたが、その対応の中で NAT 設定は奥が深いことが分かりました。
Web 上で検索しただけでは見つけることができない重要なナレッジも得ることができたためこのページにそれらのナレッジを随時まとめていくことにします。
NAT 基礎知識

- Local 領域/Inside 領域
ip nat inside
設定をしたインターフェース側にあるセグメント
- Global 領域/Outside 領域
ip nat outside
設定をしたインターフェース側にあるセグメント
- inside local
- local 領域側で見た inside 側端末の IP アドレス
- outside local
- local 領域側で見た outeside 側端末の IP アドレス
- inside global
- global 領域側で見た inside 側端末の IP アドレス
- outside global
- global 領域側で見た outside 側端末の IP アドレス
以下の inside source NAT 設定をしていた場合、
ip nat inside source static 192.168.100.100 10.1.1.100
NAT テーブルには以下のように登録されます。
Pro Inside global Inside local Outside local Outside global
--- 10.1.1.100 192.168.100.100 --- ---
また以下の outside source NAT 設定をしていた場合、
ip nat outside source static 10.30.40.100 172.168.20.100
NAT テーブルには以下のように登録されます。
Pro Inside global Inside local Outside local Outside global
--- --- --- 172.168.20.100 10.30.40.100
注意すべき inside NAT と outside NAT の機能差分
ip nat inside ~ と ip nat outside ~ とでは全く同じ設定ができると考えている人がいるかもしれませんが、ip nat outside ~ ではできないことがいくつかあったり、機能差分があったりするため注意してください。
- outside NAT を設定した際の、inside から outside への通信に対しては宛先 NAT よりもルーティングが先に実行される
- outside NAT では以下のオプションを使用できない
- overload(ip nat outside source list ~ 設定時)
- route-map(ip nat outside source route-map は使える)
ip nat pool での netmask(prefix)の意味
ip nat pool での netmask(prefix)は、アドレスプールのネットワークセグメントの特定のために使用され、特定されたセグメントのネットワークアドレスとブロードキャストアドレスはアドレスプールから除外されます。
以下画像の環境において、端末A から端末B へ通信する際の送信元アドレス変換を、PAT によって行うことを考えます。

192.168.100.3 に変換する場合、アドレスプール設定は以下のようになります。
ip nat pool POOL 192.168.100.3 192.168.100.3 netmask 255.255.255.0
PAT 設定と source list に使用するアクセスリストは以下のように設定するとします。
ip nat inside source list 10 pool POOL overload
access-list 10 permit 10.10.10.0 0.0.0.255
この設定をした場合、問題無くアドレス変換されます。
Router#show ip nat translations
Pro Inside global Inside local Outside local Outside global
icmp 192.168.100.3:1 10.10.10.100:1 192.168.100.100:1 192.168.100.100:1
ここで、アドレスプールの netmask を 255.255.255.252 に変更してみます。
ip nat pool POOL 192.168.100.3 192.168.100.3 netmask 255.255.255.252
この上で端末A から端末B への通信を発生させると、ルータにおいて以下のようにエラーが発生します。
*Oct 22 06:40:04.463: NAT: translation failed (A), dropping packet s=10.10.10.100 d=192.168.100.100
192.168.100.3 はセグメント 192.168.100.0/255.255.255.252 におけるブロードキャストアドレスのため、ルータによってアドレスプールから除外されて、その結果アドレスプール内で使用できる IP が無くなってしまったためにエラーになったと考えられます。
add-route オプション
ip nat outside が設定されている場合に、inside 側の outside global アドレス宛に通信があった場合、ルータでは NAT よりも先にルーティングが行われます。そのため、変換前の宛先アドレスに対して、変換後の宛先アドレスにルーティングされるようなルーティング設定が必要になります。
このとき、手動でスタティックルートを設定する方法以外に、ip nat outside 設定に add-route オプションを付ける方法があります。add-route オプションを付けることで、必要なスタティックルートが自動で設定されます。
以下の構成を考えます。

outside 側の端末B のアドレス 192.168.100.100 を 10.10.10.20 に変換する場合を考えます。
この時のスタティック NAT 設定は以下のようになります。ルーティングのことも考えて add-route オプションを付けています。
ip nat outside source static 192.168.100.100 10.10.10.20 add-route
この場合、add-route オプションによって以下のようなスタティックルートが追加されます。
S 10.10.10.20/32 [1/0] via 192.168.100.100
宛先が outside local アドレス、ネクストホップが outside global アドレスになっています。
この例では、outside local アドレスがルータのコネクトセグメントのため、手動のスタティックルートを設定してもコネクトルートが優先されてしまいルーティングテーブルに反映されません。一方で add-route オプションであればルーティングテーブルに反映されます。そのためこの場合では add-route オプションが必須となります。
extendable オプション
extendable オプションについては、以下の2パターンの使い方があります。
スタティック NAPT を設定する場合
IP アドレスだけでなく、tcp/udp ポート番号を指定したスタティック NAPT を設定する場合、extendable オプションが自動で付与されます。extendable を付けない形で設定しても extendable は自動で付きます。
Router(config)# ip nat inside source static tcp 10.20.30.40 5000 20.30.40.50 6000
Router(config)# do show run | inc ip nat inside source
ip nat inside source static tcp 10.20.30.40 5000 20.30.40.50 6000 extendable
このことから、スタティック NAPT を設定する場合は extendable オプションが必須であることを推し量ることができます。
異なる inside global を同一の inside local に割り当てる
以下の構成を考えます。

以下の要件を考えます。
- 端末Bから 192.168.100.10 宛てにアクセスすると端末A(10.20.30.100)にアクセスできるようにする
- 端末Cから 192.168.200.20 宛てにアクセスすると端末A(10.20.30.100)にアクセスできるようにする
この場合、以下の inside source NAT を設定することが考えられます。
ip nat inside source static 10.20.30.100 192.168.100.10
ip nat inside source static 10.20.30.100 192.168.200.10
ですが、実際に設定すると以下のエラーになり、2行目の設定はできません。
Router(config)#ip nat inside source static 10.20.30.100 192.168.100.10
Router(config)#ip nat inside source static 10.20.30.100 192.168.200.10
% 10.20.30.100 already mapped (10.20.30.100 -> 192.168.100.10)
inside local アドレスが重複していることが原因です。
このとき、以下のように extendable
オプションを使用することで設定が可能となります。
ip nat inside source static 10.20.30.100 192.168.100.10 extendable
ip nat inside source static 10.20.30.100 192.168.200.10 extendable
上記設定を設定後の NAT テーブルは以下のようになります。
Pro Inside global Inside local Outside local Outside global
--- 192.168.100.10 10.20.30.100 --- ---
--- 192.168.200.10 10.20.30.100 --- ---
これで要件を満たすことができます。
宛先を限定して NAT を行う
【PAT】source list に拡張 ACL を使用する
以下の構成で inside 側の端末A から outeside 側の端末B へ通信を行う際に、
- 宛先アドレスが 192.168.100.100 の場合は送信元変換を行う
- 宛先アドレスが 192.168.100.101 の場合は送信元変換を行わない
ように NAT 設定することを考えます。なお、端末B から通信を開始することは考えません。

この場合、ip nat source list に拡張 ACL を指定することで、宛先を限定して PAT をすることができます。
ここでは以下のような拡張 ACL を使用して、PAT 設定を行うこととします。
access-list 100 permit ip 10.10.10.0 0.0.0.255 host 192.168.100.100
アドレスプールと PAT 設定は以下とします。
ip nat pool POOL 192.168.100.10 192.168.100.10 netmask 255.255.255.0
ip nat inside source list 100 pool POOL overload
この設定によって、宛先が 192.168.100.100 の場合のみ送信元変換を行うことができます。
Router#show ip nat translations
Pro Inside global Inside local Outside local Outside global
icmp 192.168.100.10:1 10.10.10.100:1 192.168.100.100:1 192.168.100.100:1
ip nat outside 設定では拡張 ACL は使用不可
上記の source list に拡張 ACL を使用する方法は、ip nat inside 設定においては正常に動作しますが、ip nat outside 設定においては正常に動作しないため注意してください。
以下構成のように、inside と outside を入れ替えて設定を行った場合を考えます。

この場合の PAT 用の設定は以下の通りです。
ip nat pool POOL 192.168.100.10 192.168.100.10 netmask 255.255.255.0
ip nat outside source list 100 pool POOL add-route
access-list 100 permit ip 10.10.10.0 0.0.0.255 host 192.168.100.100
まず、端末A から 192.168.100.100 宛に通信すると想定通り送信元変換されます。このとき NAT テーブルには以下のように動的エントリが登録されます。
Pro Inside global Inside local Outside local Outside global
--- --- --- 192.168.100.10 10.10.10.100
icmp 192.168.100.100:1 192.168.100.100:1 192.168.100.10:1 10.10.10.100:11
次に NAT テーブルに上記の動的エントリが残っている状態で端末A から 192.168.100.101 宛に通信すると、送信元変換されないことが期待されるのですが、実際には送信元変換されてしまいます。
Pro Inside global Inside local Outside local Outside global
--- --- --- 192.168.100.10 10.10.10.100
icmp 192.168.100.100:1 192.168.100.100:1 192.168.100.10:1 10.10.10.100:1
icmp 192.168.100.101:1 192.168.100.101:1 192.168.100.10:1 10.10.10.100:1
ip nat outside source list で指定した拡張 ACL による判定よりも NAT テーブルの動的エントリによる判定が優先されてしまうためこのような事象が起こるようです。
このため ip nat outside source list に拡張 ACL を使用するような設計は避けることを推奨します。
【PAT】source route-map を使用する
これは source list に拡張 ACL を使用して宛先を限定して NAT する方法に対する別の方法です。
source list の代わりに source route-map を使用します。
以下の構成で、端末A から端末B へ通信する際に、宛先が 192.168.100.100 の場合のみ送信元 NAT することを考えます。

まず、NAT 対象通信を定義する route-map を作成します。
route-map RMap1 permit 10
match ip address 100
!
access-list 100 permit ip 10.10.10.0 0.0.0.255 host 192.168.100.100
PAT で使用するアドレスプールの定義と、作成した route-map をソースとして使用した inside source NAT を設定します。
ip nat pool POOL 192.168.100.10 192.168.100.10 netmask 255.255.255.0
ip nat inside source route-map RMap1 pool POOL overload
設定は以上です。
端末A から 192.168.100.100 宛に通信をした後の NAT テーブルは以下の通りです。
Pro Inside global Inside local Outside local Outside global
icmp 192.168.100.10:1 10.10.10.100:1 192.168.100.100:1 192.168.100.100:1
想定通り送信元が変換されています。端末A から 192.168.100.101 宛に通信をした場合は、route-map に合致しないので、送信元変換は行われません。
【スタティック NAT】route-map を使用して宛先別に NAT
以下の構成で、inside 側の端末A から outside 側の端末B・端末C へ通信する際に、
- 端末B 宛の場合は送信元を 192.168.100.10 に変換する
- 端末C 宛の場合は送信元を 192.168.100.11 に変換する
ような NAT 設定をすることを考えます。

この場合、スタティック NAT 設定に route-map オプションを付けることで実現できます。
まず、NAT 対象通信を定義する route-map を作成します。
route-map RMap1 permit 10
match ip address 100
!
route-map RMap2 permit 10
match ip address 101
!
access-list 100 permit ip 10.10.10.0 0.0.0.255 host 192.168.100.100
access-list 101 permit ip 10.10.10.0 0.0.0.255 host 192.168.100.101
作成した route-map を NAT 設定に適用します。
ip nat inside source static 10.10.10.100 192.168.100.10 route-map RMap1
ip nat inside source static 10.10.10.100 192.168.100.11 route-map RMap2
これで設定は完了です。
この設定をした場合の NAT テーブルは以下のようになっています。
Pro Inside global Inside local Outside local Outside global
--- 192.168.100.10 10.10.10.100 --- ---
--- 192.168.100.11 10.10.10.100 --- ---
端末A から端末B (192.168.100.100)、端末C (192.168.100.101) それぞれに通信した後の NAT テーブルは以下の通りです。
Pro Inside global Inside local Outside local Outside global
icmp 192.168.100.10:1 10.10.10.100:1 192.168.100.100:1 192.168.100.100:1
icmp 192.168.100.11:1 10.10.10.100:1 192.168.100.101:1 192.168.100.101:1
--- 192.168.100.10 10.10.10.100 --- ---
--- 192.168.100.11 10.10.10.100 --- ---
宛先別に変換後の送信元アドレスが変わっていることを確認できます。
逆に outside 側の端末B (192.168.100.100) から端末A の outside 側でのアドレスである 192.168.100.10 及び 192.168.100.11 宛に通信した際の NAT テーブルは以下です。
Pro Inside global Inside local Outside local Outside global
icmp 192.168.100.10:7 10.10.10.100:7 192.168.100.100:7 192.168.100.100:7
icmp 192.168.100.11:8 10.10.10.100:8 192.168.100.100:8 192.168.100.100:8
--- 192.168.100.10 10.10.10.100 --- ---
--- 192.168.100.11 10.10.10.100 --- ---
192.168.100.10 及び 192.168.100.11 のどちら宛に通信しても 10.10.10.100 に変換されていることが分かります。
スタティック NAT と NAPT の設定順序の制約
inside global が同じであるスタティック NAT と NAPT を共存させる場合は、設定順序に制約があります。
例えば以下の2つの設定をする場合を考えます。
ip nat inside source static tcp 10.100.10.20 1000 192.168.10.20 2000 extendable
ip nat inside source static 10.20.30.40 192.168.10.20
スタティック NAT を先に設定した場合、NAPT の方を設定しようとするとエラーになります。
Router(config)# ip nat inside source static 10.20.30.40 192.168.10.20
Router(config)# ip nat inside source static tcp 10.100.10.20 1000 192.168.10.20 2000 extendable
% similar static entry (10.20.30.40 -> 192.168.10.20) already exists
この場合、NAPT 設定の方を先に設定すれば設定することが可能です。
outside local が同じであるスタティック NAT と NAPT を共存させる場合も同様の設定順序の制約があります。
Router(config)# ip nat outside source static 20.30.40.50 100.1.1.1
Router(config)# ip nat outside source static tcp 20.30.40.51 199 100.1.1.1 200 extendable
% similar static entry (100.1.1.1 -> 20.30.40.50) already exists
HSRP 環境での NAT【redundancy オプション】
以下のような、ルータで HSRP を構成している場合に NAT を使用することを考えます。

inside 側にいる端末A のアドレス 10.10.10.100 を 192.168.100.20 に変換することを考えます。この場合 HSRP を構成する2台のルータの両方に NAT 設定を行うことになります。単純に考えると以下のようなスタティック NAT を設定することが考えられます。
ip nat inside source static 10.10.10.100 192.168.100.20
この NAT を設定した場合、ルータでは outside 側のインターフェースで 192.168.100.20 に対する ARP リクエスト(ブロードキャスト) に対して応答するようになります。HSRP 構成の場合、Active と Standby の両方のルータが ARP 応答してしまうため、192.168.100.20 宛の通信が不安定になる可能性があります。
ここで、HSRP の Active ルータのみを ARP 応答させるようにするために NAT 設定の redundancy
オプションを使用することができます。
redundancy オプションは「redundancy <standby name>
」の形で指定します。
上記の構成例の場合は以下のように設定します。
ip nat inside source static 10.10.10.100 192.168.100.20 redundancy IF2
※standby name が IF2 の場合
この設定によって、グループ名が IF2 のスタンバイグループで Active になっているルータのみが 192.168.100.20 に対する ARP リクエストに応答するようになります。
HSRP 構成でも redundancy オプションが必要ない場合
上記の例では、NAT IP がルータのコネクトセグメントの IP だったため redundancy オプションが必要でしたが、NAT IP がルータのコネクトではないセグメントの場合は redundancy オプションは必要ありません。
NAT IP がルータのコネクトでないセグメントの場合は、その NAT IP 宛のパケットは通常 HSRP の VIP に対してルーティングされるためです。VIP に対してルーティングされる場合は VIP に対して ARP リクエストが発生しますが、この場合は HSRP の仕様に従い Active ルータが ARP 応答するためです。
VRF 環境での NAT 設定
VRF を設定しているルータで NAT をする場合は、NAT 設定で vrf オプションを付ける必要がある場合があります。

端末A と 端末B 間で通信する際に、端末Aのアドレス 10.10.10.100 を 192.168.100.20 に変換する場合は、対象通信の入出力インターフェースが vrf の VRF-A に所属しているため、以下のように vrf VRF-A
オプションを NAT 設定に付与する必要があります。
ip nat inside source static 10.10.10.100 192.168.100.20 vrf VRF-A
show ip nat translations
コマンドの出力では、VRF に関わらずすべてのエントリが表示されますが、各エントリがどの VRF のものなのかは識別できません。
Router#show ip nat translations
Pro Inside global Inside local Outside local Outside global
--- 192.168.50.20 172.16.100.20 --- ---
--- 192.168.100.20 10.10.10.100 --- ---
show ip nat translations verbose
コマンドを実行すると、各エントリの VRF 情報を表示できます。が見づらいです。
Router#show ip nat translations verbose
Pro Inside global Inside local Outside local Outside global
--- 192.168.50.20 172.16.100.20 --- ---
create 00:00:23, use 00:00:23 timeout:0,
flags:
static, use_count: 0, entry-id: 19, lc_entries: 0
--- 192.168.100.20 10.10.10.100 --- ---
create 00:28:06, use 00:17:08 timeout:0,
flags:
static, use_count: 0, VRF : VRF-A, entry-id: 13, lc_entries: 00
また、show ip nat translations vrf <VRF名>
のように vrf 指定を行うと、指定した VRF に関するエントリのみを表示できます。
Router#show ip nat translations vrf VRF-A
Pro Inside global Inside local Outside local Outside global
--- 192.168.100.20 10.10.10.100 --- ---
NAT IP について ARP 応答しない事象
これはバグのような事象に遭遇したという話です。対象ルータ機種は C891FJ-K9 です。
例えば以下のようなスタティック NAT が設定されていたとします。また inside global である 192.168.100.10 はルータのコネクトセグメントの IP であるとします。
ip nat inside source static 10.20.30.100 192.168.100.10
この場合、NAT が設定されているルータは、outside 側セグメントにおいて inside global (上の設定例では 192.168.100.10 に該当) に対する ARP リクエストに対して ARP 応答をします。
ところが、突然 inside global に対する ARP リクエストに対して ARP 応答をしなくなったことがありました。このとき、NAT の設定をいったん削除してから再度設定し直しても、ARP 応答はしませんでした。さらにその後、ルータを再起動したところ、ARP 応答するようになりました。
参考資料

