Table of Contents

NAT64

This lab show an NAT64 lab example using BSDPR with tayga (user space) and ipfw (kernel space).

Presentation

Network diagram

Here is the logical and physical view:

Setting-up the lab

Downloading BSD Router Project images

Download BSDRP serial image (prevent to have to use an X display).

Download Lab scripts

More information on these BSDRP lab scripts available on How to build a BSDRP router lab.

Start the lab with 3 routers. With bhyve under FreeBSD:

user:~ # tools/BSDRP-lab-bhyve.sh -i BSDRP-1.93-full-amd64-serial.img.xz -n 3
BSD Router Project (http://bsdrp.net) - bhyve full-meshed lab script
Setting-up a virtual lab with 3 VM(s):
- Working directory: /tmp/BSDRP
- Each VM has 1 core and 512M RAM
- Emulated NIC: virtio-net
- Switch mode: bridge + tap
- 0 LAN(s) between all VM
- Full mesh Ethernet links between each VM
VM 1 has the following NIC:
- vtnet0 connected to VM 2
- vtnet1 connected to VM 3
VM 2 has the following NIC:
- vtnet0 connected to VM 1
- vtnet1 connected to VM 3
VM 3 has the following NIC:
- vtnet0 connected to VM 1
- vtnet1 connected to VM 2
To connect VM'serial console, you can use:
- VM 1 : cu -l /dev/nmdm-BSDRP.1B
- VM 2 : cu -l /dev/nmdm-BSDRP.2B
- VM 3 : cu -l /dev/nmdm-BSDRP.3B

Generic configuration

VM 1 (client)

VM1 is configured as a simple IPv6 only host:

sysrc hostname=VM1 \
 gateway_enable=NO \
 ipv6_gateway_enable=NO \
 ifconfig_vtnet0_ipv6="inet6 2001:db8:12::1 prefixlen 64" \
 ipv6_defaultrouter="2001:db8:12::2"
service hostname restart
service netif restart
service routing restart
config save

Router 2

VM2 is a router with one interface toward IPv6 network, and another toward IPv4 network.

sysrc hostname=VM2 \
 ifconfig_vtnet1="inet 2.2.2.2/24" \
 ifconfig_vtnet0_ipv6="inet6 2001:db8:12::2 prefixlen 64"
service hostname restart
service netif restart
service routing restart
config save

VM 3 (client)

VM3 is configured as a simple IPv4 only host:

sysrc hostname=VM3 \
 gateway_enable=NO \
 ipv6_gateway_enable=NO \
 ifconfig_vtnet1="inet 2.2.2.3/24" \
 defaultrouter="2.2.2.2"
service hostname restart
service netif restart
service routing restart
config save

Tayga (user space stateless NAT64)

VM2

Modify default default tayga's configuration file and enable it:

service tayga enable
sed -i "" 's/192.168.255./2.2.1./g' /usr/local/etc/tayga.conf
sed -i "" 's/2001:db8:1:ffff::/64:ff9b::/g' /usr/local/etc/tayga.conf
service tayga start

Quick test from VM2 by pinging its IPv4 address from its IPv6 one, and same by targeting VM3:

[root@VM2]~# ping6 -c 3 64:ff9b::2.2.2.2
PING6(56=40+8+8 bytes) 2001:db8:12::2 --> 64:ff9b::202:202
16 bytes from 64:ff9b::202:202, icmp_seq=0 hlim=63 time=0.128 ms
16 bytes from 64:ff9b::202:202, icmp_seq=1 hlim=63 time=0.082 ms
16 bytes from 64:ff9b::202:202, icmp_seq=2 hlim=63 time=0.069 ms

--- 64:ff9b::2.2.2.2 ping6 statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 0.069/0.093/0.128/0.025 ms
[root@VM2]~# ping6 -c 3 64:ff9b::2.2.2.3
PING6(56=40+8+8 bytes) 2001:db8:12::2 --> 64:ff9b::202:203
16 bytes from 64:ff9b::202:203, icmp_seq=0 hlim=62 time=0.228 ms
16 bytes from 64:ff9b::202:203, icmp_seq=1 hlim=62 time=0.164 ms
16 bytes from 64:ff9b::202:203, icmp_seq=2 hlim=62 time=0.157 ms

--- 64:ff9b::2.2.2.3 ping6 statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 0.157/0.183/0.228/0.032 ms

Testing

From VM4, start a tcpdump to check IPv4 source address seen by VM3:

[root@VM3]~# tcpdump -c 2 -pni vtnet1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on vtnet1, link-type EN10MB (Ethernet), capture size 262144 bytes
...

From VM1 (IPv6 only host), ping NAT64 IPv6 address corresponding to VM3 IPv4 address:

[root@VM1]~# ping6 -c 3 64:ff9b::2.2.2.3
PING6(56=40+8+8 bytes) 2001:db8:12::1 --> 64:ff9b::202:203
16 bytes from 64:ff9b::202:203, icmp_seq=0 hlim=61 time=0.298 ms
16 bytes from 64:ff9b::202:203, icmp_seq=1 hlim=61 time=0.257 ms
16 bytes from 64:ff9b::202:203, icmp_seq=2 hlim=61 time=0.261 ms

--- 64:ff9b::2.2.2.3 ping6 statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 0.257/0.272/0.298/0.018 ms

From VM3, check source IP addresses of ICMP:

...
17:43:03.094975 IP 2.2.1.249 > 2.2.2.3: ICMP echo request, id 6575, seq 0, length 16
17:43:03.094983 IP 2.2.2.3 > 2.2.1.249: ICMP echo reply, id 6575, seq 0, length 16
2 packets captured
2 packets received by filter
0 packets dropped by kernel

IPFW NAT64 (kernel space)

IPFW NAT64 module supports both stateful (lsn) and stateless (stl) NAT64.

Stateful (lsn)

VM2

Configure a stateful NAT64 with ipfw:

service ipfw enable
sysrc firewall_script="/etc/ipfw.rules"
echo "# Temporary fix to avoid panicing a 12-stable:" >> /etc/sysctl.conf
echo "net.inet.ip.fw.nat64_direct_output=1" >> /etc/sysctl.conf
cat > /etc/ipfw.rules <<'EOF'
#!/bin/sh
fwcmd="/sbin/ipfw"
kldstat -q -m ipfw_nat64 || kldload ipfw_nat64
${fwcmd} -f flush
${fwcmd} nat64lsn NAT64 create prefix4 2.2.1.0/24
${fwcmd} add allow icmp6 from any to any icmp6types 135,136
${fwcmd} add nat64lsn NAT64 ip from 2001:db8:12::/64 to 64:ff9b::/96 in
${fwcmd} add nat64lsn NAT64 ip from any to 2.2.1.0/24 in
${fwcmd} add allow ip from any to any
'EOF'

service ipfw start
sysctl net.inet.ip.fw.nat64_direct_output=1

Testing

From IPv6 only host, ping NAT64 IPv6 address corresponding to VM3 IPv4 address:

[root@VM1]~# ping6 -c 3 64:ff9b::2.2.2.3
PING6(56=40+8+8 bytes) 2001:db8:12::1 --> 64:ff9b::202:203
16 bytes from 64:ff9b::202:203, icmp_seq=0 hlim=63 time=0.369 ms
16 bytes from 64:ff9b::202:203, icmp_seq=1 hlim=63 time=0.259 ms
16 bytes from 64:ff9b::202:203, icmp_seq=2 hlim=63 time=0.248 ms

--- 64:ff9b::2.2.2.3 ping6 statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 0.248/0.292/0.369/0.055 ms

Checking status on NAT64 router:

[root@VM2]~# ipfw nat64lsn NAT64 show states
2001:db8:12::1  2.2.1.210       ICMPv6          0       2.2.2.3
[root@VM2]~# ipfw show
00100 12 824 allow ipv6-icmp from any to any icmp6types 135,136
00200 12 672 nat64lsn NAT64 ip from 2001:db8:12::/64 to 64:ff9b::/96 in
00300 12 432 nat64lsn NAT64 ip from any to 2.2.1.0/24 in
65535  0   0 deny ip from any to any

Stateless (stl)

VM2

Configure a stateless NAT64 with ipfw, and enable logging:

service ipfw enable
sysrc firewall_script="/etc/ipfw.rules"

cat > /etc/ipfw.rules <<'EOF'
#!/bin/sh
fwcmd="/sbin/ipfw"
kldstat -q -m ipfw_nat64 || kldload ipfw_nat64
${fwcmd} -f flush
${fwcmd} table T46 create type addr valtype ipv6
${fwcmd} table T64 create type addr valtype ipv4
${fwcmd} table T46 add 2.2.1.1 2001:db8:12::1
${fwcmd} table T64 add 2001:db8:12::1 2.2.1.1
${fwcmd} nat64stl NAT64 create table4 T46 table6 T64
${fwcmd} add allow icmp6 from any to any icmp6types 135,136
${fwcmd} add nat64stl NAT64 ip from any to table\(T46\)
${fwcmd} add nat64stl NAT64 ip6 from table\(T64\) to 64:ff9b::/96
${fwcmd} add allow log ip from any to any
'EOF'

service ipfw start

Testing

From IPv6 only host, ping NAT64 IPv6 address corresponding to VM3 IPv4 address:

[root@VM1]~# ping6 -c 3 64:ff9b::2.2.2.3
PING6(56=40+8+8 bytes) 2001:db8:12::1 --> 64:ff9b::202:203
16 bytes from 64:ff9b::202:203, icmp_seq=0 hlim=63 time=1.037 ms
16 bytes from 64:ff9b::202:203, icmp_seq=1 hlim=63 time=1.048 ms
16 bytes from 64:ff9b::202:203, icmp_seq=2 hlim=63 time=1.560 ms

--- 64:ff9b::2.2.2.3 ping6 statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 1.037/1.215/1.560/0.244 ms

From IPv4 only host, ping NAT64 IPv4 address corresponding to VM3 IPv6 address:

[root@VM3]~# ping -c 3 2.2.1.1
PING 2.2.1.1 (2.2.1.1): 56 data bytes
64 bytes from 2.2.1.1: icmp_seq=0 ttl=63 time=17.147 ms
64 bytes from 2.2.1.1: icmp_seq=1 ttl=63 time=1.409 ms
64 bytes from 2.2.1.1: icmp_seq=2 ttl=63 time=5.017 ms

--- 2.2.1.1 ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 1.409/7.858/17.147/6.732 ms

And check on the NAT router VM2 some stats:

[root@VM2]~# ipfw nat64stl NAT64 stats
nat64stl NAT64
        6 packets translated from IPv6 to IPv4
        6 packets translated from IPv4 to IPv6
        0 IPv6 fragments created
        0 IPv4 fragments received
        0 output packets dropped due to no bufs, etc.
        0 output packets discarded due to no IPv4 route
        0 output packets discarded due to no IPv6 route
        0 packets discarded due to unsupported protocol
        0 packets discarded due to memory allocation problems
        0 packets discarded due to some errors