概要
VLAN 2069 を IPv6-mostly / NAT64 評価用セグメントとして作ったときの作業メモです。
構成としては、Catalyst 側で VLAN/SVI を作り、Kea で DHCPv4 option 108
IPv6-Only Preferred を返し、Unbound の DNS64 専用 instance で合成 AAAA を返し、
Cisco IOS XE ルータで Stateful NAT64 PAT を行います。
最終的に、IPv4 address を持たない Linux コンテナから以下が成功しました。
curl -6 -v https://www.yahoo.co.jp/
...
Connected to www.yahoo.co.jp (2001:db8:24:4ff:64:0:...) port 443
< HTTP/2 200
この記事では、成功構成だけでなく、途中ではまった点も残します。
前提
今回の評価 VLAN は以下です。
VLAN: 2069
IPv4 gateway: 192.168.69.1/24
IPv6 gateway: 2001:DB8:24:409::1/64
DNS64 prefix: 2001:DB8:24:4FF:64::/96
DNS64 listener は通常 resolver と分離しました。
dns1 DNS64: 2001:DB8:24:404::64:16
dns2 DNS64: 2001:DB8:24:404::64:17
NAT64/PLAT は cr1 の Cisco IOS XE ルータで実施します。
全体像
役割は以下です。
client on VLAN2069
|
| IPv6 only / IPv6-mostly
v
sw1 Vlan2069
- 192.168.69.1/24
- 2001:DB8:24:409::1/64
- RA RDNSS: DNS64 listener
- DHCPv4 relay to Kea
|
v
dns1/dns2
- Kea DHCPv4 option 108
- Unbound DNS64 dedicated instance
|
v
cr1
- Stateful NAT64 PAT
Step 1: VLAN/SVI
sw1 に Vlan2069 を作りました。
ポイントは、完全な IPv6-only ではなく、DHCPv4 option 108 を評価するために
IPv4 gateway も持たせることです。DHCPv4 relay では SVI の IPv4 address が
giaddr になるためです。
設定イメージ:
interface Vlan2069
description ### NAT64 / CLAT evaluation ###
ip address 192.168.69.1 255.255.255.0
ip helper-address 192.168.64.16
ip helper-address 192.168.64.17
ipv6 address 2001:DB8:24:409::1/64
ipv6 enable
ipv6 nd ra dns server 2001:DB8:24:404::64:16
ipv6 nd ra dns server 2001:DB8:24:404::64:17
ip router isis IOSLAB
ipv6 router isis IOSLAB
isis circuit-type level-2-only
SVI は L2 側に VLAN 2069 の up/up port がないと line protocol down になるので、
access port または trunk allowed VLAN の確認も gate にしました。
Step 2: Kea DHCPv4 option 108
Kea には 192.168.69.0/24 を追加しましたが、原則として IPv4 pool は持たせません。
狙いは RFC 8925 の IPv6-Only Preferred option を返し、対応端末には IPv4 を
持たせないことです。
Kea の設定イメージ:
- id: 13
subnet: 192.168.69.0/24
valid-lifetime: 1800
option-data:
- name: routers
data: 192.168.69.1
- name: domain-name-servers
data: 192.168.64.16, 192.168.64.17
- name: domain-name
data: example.com
- name: v6-only-preferred
data: 1800
はまった点として、Kea では option 108 は標準 option として扱われます。
そのため、custom option-def として再定義すると target Kea で拒否されます。
つまり、v6-only-preferred は option-data に書くだけでよく、独自 option-def は
追加しません。
Step 3: DNS64 専用 Unbound
既存 resolver に DNS64 を直接有効化すると、既存セグメントにも DNS64 が効く可能性が
あります。そのため、DNS64 用の Unbound を別 instance として起動しました。
dns1 の例:
server:
interface: 2001:DB8:24:404::64:16
port: 53
pidfile: "/var/run/unbound-dns64.pid"
directory: "/var/unbound-dns64"
access-control: 2001:DB8:24:409::/64 allow
access-control: 0.0.0.0/0 refuse
access-control: ::0/0 refuse
module-config: "dns64 validator iterator"
dns64-prefix: 2001:db8:24:4ff:64::/96
最初、DNS64 専用 listener を loopback に bind する案も考えましたが、既存 Unbound と
衝突するためやめました。DNS64 instance は専用 IPv6 address のみに bind します。
FreeBSD 側では、DNS64 用 address を追加で持たせました。
dns1: 2001:db8:24:404::64:16/128
dns2: 2001:db8:24:404::64:17/128
確認:
dig @2001:db8:24:404::64:16 -t AAAA ipv4only.arpa
ipv4only.arpa. 600 IN AAAA 2001:db8:24:4ff:64:0:c000:aa
ipv4only.arpa. 600 IN AAAA 2001:db8:24:4ff:64:0:c000:ab
この時点で DNS64 は OK です。
Step 4: cr1 Stateful NAT64
最終的に必要だった基本構成はこれです。
ipv6 access-list ACL_NAT64_VLAN2069_V6
permit ipv6 2001:DB8:24:409::/64 any
nat64 prefix stateful 2001:DB8:24:4FF:64::/96
nat64 v4 pool NAT64_POOL_VLAN2069 203.0.113.174 203.0.113.174
nat64 v6v4 list ACL_NAT64_VLAN2069_V6 pool NAT64_POOL_VLAN2069 overload
NAT64 を通す WAN/LAN interface には nat64 enable を入れました。
interface TenGigabitEthernet0/0/8
nat64 enable
interface TenGigabitEthernet0/0/9
nat64 enable
環境によって必要 interface は異なりますが、少なくとも入口側の inside/transit
interface で NAT64 drop が増えるかを見るのが重要でした。
はまった点 1: Well-Known Prefix は Stateful NAT64 prefix に使えない
最初は DNS64 の慣例で 64:ff9b::/96 を使おうとしました。
nat64 prefix stateful 64:FF9B::/96
しかし IOS XE では以下で拒否されました。
%NAT64: Cannot use the well-known prefix 64:FF9B::/96 for a stateful prefix
そのため、Network-Specific Prefix として以下を使いました。
2001:DB8:24:4FF:64::/96
DNS64 の dns64-prefix と cr1 の nat64 prefix stateful は必ず一致させます。
はまった点 2: nat64 route 0.0.0.0/0 は不要だった
途中で nat64 route が必要だと思い、以下を試しました。
nat64 route 0.0.0.0/0 TenGigabitEthernet0/0/9
しかし、NAT64 pool と route が重なるため、IOS XE が拒否しました。
%NAT64-3-EINVAL: The range 203.0.113.174-203.0.113.174 cannot overlap with the NAT64 route 0.0.0.0/0
結論として、今回の Stateful NAT64 PAT では nat64 route は不要でした。
show nat64 routes が空でも、通常の IPv4 routing table に従って NAT64 後の IPv4
packet が転送されます。
確認時の状態:
show nat64 routes
IPv4 Prefix Adj. Address Enabled VRF Output IF
Global IPv6 Prefix
それでも curl は成功し、translation も作成されました。
Total active translations: 6
Sessions created: 7
Packets translated (IPv6 -> IPv4) Stateful: 176
Packets translated (IPv4 -> IPv6) Stateful: 320
はまった点 3: NAT64 pool に使える public IPv4
最も時間がかかったのは NAT64 pool address です。
203.0.113.169 は不可
.169 は既存の Loopback1 / Tunnel0 / NAT44 PAT で使っていました。
そのため NAT64 pool にすると即座に拒否されます。
%NAT64-3-EINVAL: The range 203.0.113.169-203.0.113.169 cannot contain an interface address
(found overlap with address on interface Loopback1)
IOS XE の Stateful NAT64 pool には、ルータ自身の interface address は使えません。
203.0.113.168 は設定できるが動かない
.168 は設定としては入りました。
nat64 v4 pool NAT64_POOL_VLAN2069 203.0.113.168 203.0.113.168
しかし curl は失敗し、translation は作られませんでした。
Total active translations: 0
Sessions created: 0
QFP 側では以下が増えました。
NAT64_DROP_SC_ADDR_PORT_FAIL
NAT64_DROP_SC_ADDR_NOT_AVAIL
つまり、設定はできても dataplane では変換元 address として使えませんでした。
203.0.113.175 も設定できるが動かない
cr1 上で 203.0.113.168/29 として interface 設定しているわけではありません。
また、ISP 側はこの public block 内の先頭/末尾相当の address も /32 として通せる
ことを過去に確認していました。
そのため、.175 も NAT64 pool として試しました。
nat64 v4 pool NAT64_POOL_VLAN2069 203.0.113.175 203.0.113.175
これも設定としては入りましたが、実通信は失敗しました。
curl: (7) Failed to connect to www.yahoo.co.jp port 443
cr1 側では translation は作られず、QFP drop は .168 と同じ傾向でした。
Total active translations: 0
NAT64_DROP_SC_ADDR_PORT_FAIL
NAT64_DROP_SC_ADDR_NOT_AVAIL
203.0.113.174 は動いた
既存 static NAT で使っていた .174 を一時的に外し、NAT64 pool にすると成功しました。
no ip nat inside source static 172.24.101.50 203.0.113.174
no ip route 203.0.113.174 255.255.255.255 Null0 name SDWAN_VSMART_NAT_ALIAS
nat64 v4 pool NAT64_POOL_VLAN2069 203.0.113.174 203.0.113.174
nat64 v6v4 list ACL_NAT64_VLAN2069_V6 pool NAT64_POOL_VLAN2069 overload
成功時の translation:
tcp 198.51.100.124:443
[2001:db8:24:4ff:64:0:c633:647c]:443
203.0.113.174:36178
[2001:db8:24:409:be24:11ff:fe67:88f3]:36178
この結果から、少なくとも今回の cr1 / IOS XE Stateful NAT64 では .168 と .175 は
NAT64 pool として使えず、.174 は使えました。
当初は /29 の network/broadcast 相当 address だから使えないのではないか、と
疑いました。しかし、この環境では ISP 側が public block 内の先頭/末尾相当 address も
/32 として通せることを過去に確認しています。そのため、.168 / .175 の失敗を
単純に ISP 側の /29 制約とは説明できません。
追加で cr1 を確認したところ、interface address や route として
203.0.113.168/29 は存在しませんでした。
show ip route 203.0.113.168 255.255.255.248
% Subnet not in table
show ip route 203.0.113.168
% Subnet not in table
show ip route 203.0.113.175
% Subnet not in table
一方で、hairpin / ZBFW 用の ACL には public block 全体を表す
203.0.113.168 0.0.0.7 が使われていました。
ip access-list extended NAT_HAIRPIN_PUBLIC_V4
20 permit ip 192.168.0.0 0.0.255.255 203.0.113.168 0.0.0.7
30 permit ip 172.16.0.0 0.15.255.255 203.0.113.168 0.0.0.7
40 permit ip 10.0.0.0 0.255.255.255 203.0.113.168 0.0.0.7
100 permit ip any 203.0.113.168 0.0.0.7
route-map NAT_HAIRPIN_TO_VASI permit 10
match ip address NAT_HAIRPIN_PUBLIC_V4
set ip next-hop 10.255.255.2
この ACL が NAT64 pool address の失敗に直接関係しているかは、今回の確認だけでは
断定できません。確実に言えるのは、IOS XE の NAT64 dataplane が .168 / .175 で
address/port を割り当てられず、.174 では割り当てられた、という点までです。
検証コマンド
クライアント側:
ip addr
ip route
ip -6 route
cat /etc/resolv.conf
dig -t AAAA ipv4only.arpa
dig -t AAAA www.yahoo.co.jp
curl -6 -v https://www.yahoo.co.jp/
IPv4 を持っていないこと:
inet6 2001:db8:24:409:be24:11ff:fe67:88f3/64 scope global dynamic
DNS64 合成:
www.yahoo.co.jp. CNAME edge12.g.yimg.jp.
edge12.g.yimg.jp. AAAA 2001:db8:24:4ff:64:0:...
cr1 側:
show nat64 statistics
show nat64 translations
show nat64 pool
show nat64 aliases
show platform hardware qfp active feature nat64 datapath statistics
show logging | include NAT64|nat64|EINVAL
特に見るべきところ:
Total active translations
Sessions created
Packets translated (IPv6 -> IPv4) Stateful
Packets translated (IPv4 -> IPv6) Stateful
NAT64_DROP_SC_ADDR_PORT_FAIL
NAT64_DROP_SC_ADDR_NOT_AVAIL
最終的な理解
今回の IOS XE Stateful NAT64 PAT では、以下が重要でした。
- Stateful NAT64 prefix に
64:ff9b::/96は使えない。 - DNS64 と NAT64 の prefix は一致させる。
-
nat64 route 0.0.0.0/0は不要。 -
show nat64 routesが空でも Stateful NAT64 PAT は動作する。 - NAT64 pool は interface address と重複できない。
- 設定として入る IPv4 address でも、dataplane で
ADDR_NOT_AVAILになり得る。 -
.168/.175は設定できたが実通信不可。 -
.174は既存 static NAT を一時的に外すと NAT64 pool として動作した。 -
.168/.175の失敗理由は/29の network/broadcast とは断定しない。 - cr1 の interface/route に
203.0.113.168/29は見えなかった。 - ただし hairpin / ZBFW ACL では
203.0.113.168 0.0.0.7として public block
全体を扱っていた。
まとめ
DNS64 までは比較的素直でしたが、IOS XE の Stateful NAT64 は pool address の扱いで
かなりはまりました。
今回一番大きな学びは、nat64 route ではなく、まず Stateful NAT64 PAT の基本構成を
素直に入れること、そして pool address が dataplane で本当に使えるかを
show nat64 translations と QFP drop counter で見ることです。
curl の失敗だけを見ると経路問題に見えますが、実際には NAT64 pool address の
割り当て失敗でした。