Page MenuHomeVyOS Platform

Support NAT for ipv6(NPT)
Needs testing, NormalPublicFEATURE REQUEST

Assigned To
Authored By
jack9603301
May 26 2020, 1:30 PM
Referenced Files
F1119180: 图片.png
Jan 21 2021, 5:38 AM
F1119184: 图片.png
Jan 21 2021, 5:38 AM
F1119189: 图片.png
Jan 21 2021, 5:38 AM
F872747: 图片.png
Sep 23 2020, 1:49 PM
F872745: 图片.png
Sep 23 2020, 1:49 PM
F872743: 图片.png
Sep 23 2020, 1:49 PM
F872364: VyOS NAT66 NDPPD Ethernet Topology.png
Sep 22 2020, 5:33 PM
F861749: VyOS NAT66 Topology.png
Sep 16 2020, 10:50 PM

Description

At present, there are configuration options about NPT in vyos version, but they seem to have no effect. Does anyone know how to implement this feature.

Referring to H3C, NPT is also called nat66 technology. In fact, it is SNAT and DNAT implemented by IPv6. Different from IPv4, nat66 only supports 1-to-1 mapping of routing prefix, which will provide vyos with nat66 experimental support supporting SNPT and DNPT. This implementation needs to be tested. Please summarize all bugs and modification suggestions under this task for tracking.

set nat66 source rule <ruleid> description <description>
set nat66 source rule <ruleid> disable
set nat66 source rule <ruleid> log
set nat66 destination rule <ruleid> oinbound-interface <interface>
set nat66 source rule <ruleid> source prefix <prefix>
set nat66 source rule <ruleid> translation address <prefix>
set nat66 destination rule <ruleid> description <description>
set nat66 destination rule <ruleid> disable
set nat66 destination rule <ruleid> log
set nat66 destination rule <ruleid> outbound-interface <interface>|any
set nat66 destination rule <ruleid> destination address <ipv6-address>|<ipv6-network>
set nat66 destination rule <ruleid> translation address <ipv6-address>|<ipv6-network>

I refer to the configuration structure of H3C. In the original command structure, NPT does not support the division of SNAT and DNAT. In order to implement nat66, I separated it for the following reasons:

  1. I can modify it according to the existing script of NAT, and I can modify it less nat.py , I created nat66 and the independent nftables-nat66.tmpl to complete the implementation of nat66.
  2. It can fully support the configuration of SNPT and DNPT in nat66. If users do not need SNPT or DNPT, it should not take effect by default.

My initial implementation of npt is in:

Since the current branch uses the kernel Linux 5.10, I began to pay attention to the implementation of NPT again. At present, I have completed the following features:

  • SNPT 1:1 mapping
  • SNPT Address Mapping
  • DNPT single address mapping
  • DNPT 1:1 mapping

Details

Difficulty level
Normal (likely a few hours)
Version
-
Why the issue appeared?
Will be filled on close
Is it a breaking change?
Config syntax change (non-migratable)

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes

Hey guys, I am testing nat66 from @jack9603301 which @c-po provided the ISO for me today (VyOS 1.3-nat66-202009161808)

I have a remote access "road warrior" Wireguard instance running, which assigns clients addresses from fc00:dead:beef::/64. I have a nat66 rule in place when traffic should leave my R2 VyOS Router.

The nat66 source rule does translate prefix as expected, but the trouble is my upstream router (R1) is unable to reply from it's interface on the same translated-prefix.

Upstream R1 is unable to reply to PC2.

Attached is a simple diagram for my use case, and the configuration for R2, and laptop ping tests.

set firewall all-ping 'enable'
set firewall broadcast-ping 'disable'
set firewall config-trap 'disable'
set firewall ipv6-name OUTSIDE_IN_V6 default-action 'drop'
set firewall ipv6-name OUTSIDE_IN_V6 rule 1000 action 'accept'
set firewall ipv6-name OUTSIDE_IN_V6 rule 1000 description 'IPv6 Allow established/related'
set firewall ipv6-name OUTSIDE_IN_V6 rule 1000 state established 'enable'
set firewall ipv6-name OUTSIDE_IN_V6 rule 1000 state related 'enable'
set firewall ipv6-name OUTSIDE_IN_V6 rule 1100 action 'drop'
set firewall ipv6-name OUTSIDE_IN_V6 rule 1100 description 'Drop invalid state'
set firewall ipv6-name OUTSIDE_IN_V6 rule 1100 state established 'disable'
set firewall ipv6-name OUTSIDE_IN_V6 rule 1100 state invalid 'enable'
set firewall ipv6-name OUTSIDE_IN_V6 rule 1100 state new 'disable'
set firewall ipv6-name OUTSIDE_IN_V6 rule 1100 state related 'disable'
set firewall ipv6-name OUTSIDE_IN_V6 rule 1200 action 'accept'
set firewall ipv6-name OUTSIDE_IN_V6 rule 1200 protocol 'icmpv6'
set firewall ipv6-name OUTSIDE_IN_V6 rule 9999 action 'accept'
set firewall ipv6-name OUTSIDE_IN_V6 rule 9999 protocol 'ipv6-icmp'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 default-action 'drop'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 1000 action 'accept'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 1000 description 'IPv6 Allow established/related'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 1000 state established 'enable'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 1000 state related 'enable'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 1100 action 'drop'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 1100 description 'Drop invalid state'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 1100 state established 'disable'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 1100 state invalid 'enable'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 1100 state new 'disable'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 1100 state related 'disable'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 1200 action 'accept'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 1200 protocol 'icmpv6'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 1300 action 'accept'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 1300 destination port '9922'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 1300 protocol 'tcp'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 1400 action 'accept'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 1400 destination port '53'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 1400 protocol 'udp'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 9999 action 'accept'
set firewall ipv6-name OUTSIDE_TO_RTR_V6 rule 9999 protocol 'ipv6-icmp'
set firewall ipv6-receive-redirects 'disable'
set firewall ipv6-src-route 'disable'
set firewall ip-src-route 'disable'
set firewall log-martians 'enable'
set firewall receive-redirects 'disable'
set firewall send-redirects 'enable'
set firewall source-validation 'disable'
set firewall syn-cookies 'enable'
set firewall twa-hazards-protection 'disable'
set interfaces ethernet eth0 description 'WAN1 - 10G'
set interfaces ethernet eth0 firewall in ipv6-name 'OUTSIDE_IN_V6'
set interfaces ethernet eth0 firewall local ipv6-name 'OUTSIDE_TO_RTR_V6'
set interfaces ethernet eth0 hw-id 'XX:XX:XX:XX:XX:2f'
set interfaces ethernet eth0 smp-affinity 'auto'
set interfaces ethernet eth1 address 'xxxx:xxxx:16:10::3/64'
set interfaces ethernet eth1 description 'WAN2 - 1G'
set interfaces ethernet eth1 firewall in ipv6-name 'OUTSIDE_IN_V6'
set interfaces ethernet eth1 firewall local ipv6-name 'OUTSIDE_TO_RTR_V6'
set interfaces ethernet eth1 hw-id 'XX:XX:XX:XX:XX:3f'
set interfaces ethernet eth1 smp-affinity 'auto'
set interfaces ethernet eth3 description 'Inside VLAN2400'
set interfaces ethernet eth3 address '2001:xxxx:16:24::62/64'
set interfaces ethernet eth3 firewall local ipv6-name 'OUTSIDE_TO_RTR_V6'
set interfaces ethernet eth3 smp-affinity 'auto'
set interfaces wireguard wg01 address 'fc00:dead:beef::1/64'
set interfaces wireguard wg01 description 'Remote Access'
set interfaces wireguard wg01 peer MacbookAir_WAN1_v4 allowed-ips 'fc00:dead:beef::90/128'
set interfaces wireguard wg01 peer MacbookAir_WAN1_v4 pubkey 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
set interfaces wireguard wg01 port '53'
set nat66 source rule 1 outbound-interface 'eth3'
set nat66 source rule 1 source prefix 'fc00:dead:beef::/64'
set nat66 source rule 1 translation prefix '2001:xxxx:16:24::/64'
set protocols static interface-route6 fc00:dead:beef::/64 next-hop-interface wg01
set system conntrack

Laptop / Wireguard client:

➜  ~ ifconfig utun10
utun10: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1420
    options=6403<RXCSUM,TXCSUM,CHANNEL_IO,PARTIAL_CSUM,ZEROINVERT_CSUM>
    inet 172.16.10.90 --> 172.16.10.90 netmask 0xffffff00
    inet6 fe80::3af9:d3ff:fe21:d814%utun10 prefixlen 64 scopeid 0x1b
    inet6 fc00:dead:beef::90 prefixlen 64
    nd6 options=201<PERFORMNUD,DAD>

➜  ~ ping6 fc00:dead:beef::1
PING6(56=40+8+8 bytes) fc00:dead:beef::90 --> fc00:dead:beef::1
16 bytes from fc00:dead:beef::1, icmp_seq=0 hlim=64 time=19.681 ms

--- fc00:dead:beef::1 ping6 statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 19.681/19.681/19.681/0.000 ms

➜  ~ ping6 2001:xxxx:16:24::251
PING6(56=40+8+8 bytes) fc00:dead:beef::90 --> 2001:xxxx:16:24::251
^C
--- 2001:xxxx:16:24::251 ping6 statistics ---
3 packets transmitted, 0 packets received, 100.0% packet loss

R1 packet-capture on it's eth2 interface:

22:33:44.996301 IP6 2001:xxxx:16:24::cfa3:82d4 > 2001:xxxx:16:24::251: ICMP6, echo request, seq 0, length 16
22:33:44.996361 IP6 2001:xxxx:16:24::251 > ff02::1:ffa3:82d4: ICMP6, neighbor solicitation, who has 2001:xxxx:16:24::cfa3:82d4, length 32
22:33:45.997372 IP6 2001:xxxx:16:24::251 > ff02::1:ffa3:82d4: ICMP6, neighbor solicitation, who has 2001:xxxx:16:24::cfa3:82d4, length 32
22:33:45.997559 IP6 2001:xxxx:16:24::cfa3:82d4 > 2001:xxxx:16:24::251: ICMP6, echo request, seq 1, length 16
22:33:47.006692 IP6 2001:xxxx:16:24::cfa3:82d4 > 2001:xxxx:16:24::251: ICMP6, echo request, seq 2, length 16
22:33:47.021376 IP6 2001:xxxx:16:24::251 > ff02::1:ffa3:82d4: ICMP6, neighbor solicitation, who has 2001:xxxx:16:24::cfa3:82d4, length 32
22:33:50.064586 IP6 fe80::9c84:d3ff:fe7d:9f77 > 2001:xxxx:16:24::251: ICMP6, neighbor solicitation, who has 2001:xxxx:16:24::251, length 32
22:33:50.064655 IP6 2001:xxxx:16:24::251 > fe80::9c84:d3ff:fe7d:9f77: ICMP6, neighbor advertisement, tgt is 2001:xxxx:16:24::251, length 24

VyOS NAT66 Topology.png (566×231 px, 25 KB)

Please give the configuration of R1 so that I can immediately test your topology in the simulation environment

@jack9603301 Here is R1

set interfaces ethernet eth0 address '2001:xxxx:16:9::1/64'
set interfaces ethernet eth1 address '2001:xxxx:16:10::1/64'
set interfaces ethernet eth2 address '2001:xxxx:16:24::251/64'
set interfaces ethernet eth2 description 'LAN2400 - Inside Management'
set interfaces ethernet eth3 address '2001:xxxx:16:17::18/64'
set interfaces ethernet eth3 description 'NET-A Backbone'
set interfaces ethernet eth4 address '2001:xxxx:16:18::18/64'
set interfaces ethernet eth4 description 'NET-B Backbone'
set interfaces loopback lo address '2001:xxxx:16:11::1/64'
set protocols static route6 ::/0 next-hop fe80::xxxx:xxxx:fedf:2a71 distance '185'
set protocols static route6 ::/0 next-hop fe80::xxxx:xxxx:fe65:c019 distance '200'
This comment was removed by jack9603301.
jack9603301 changed the task status from On hold to In progress.Sep 18 2020, 10:50 AM

It is confirmed that there is a bug in the implementation, but no solution has been found yet. In the nat66 rule, the prefix translation is indeed performed in the expected behavior, but the upstream device cannot return the data packet from the specific prefix. If the community has a good solution, please let me know

I worked with @jack9603301 and discovered [1] that stateless NAT66 depends on IPv6 neighbor proxy, otherwise VyOS will not respond to IPv6 neighbor discovery broadcasts.

To manually test I did the following for my environment:

sysctl -w net.ipv6.conf.all.proxy_ndp=1
sudo ip -6 neigh add proxy 2001:xxxx:16:24::e686:9490 dev eth3

And immediately saw ping replies from the test VM.

Obviously managing each host address is not ideal, so there is a daemon called "ndppd".
ndppd runs as a daemon, and uses a simple ndppd.conf

Alternatively, we could look at using a stateful approach with NPTv6, but that has not been tested/discussed.

Reference: [1] Re: How to use IPv6 SNPT?

This is a milestone, which means we have to decide whether to use stateful or stateless

Beeing stateless or statefull both should work. We can add a CLI node for the proxy.ndp option like we have for proxy arp on ipv4, no big deal.

In T2518#75586, @c-po wrote:

Beeing stateless or statefull both should work. We can add a CLI node for the proxy.ndp option like we have for proxy arp on ipv4, no big deal.

Support at the same time?

jack9603301 changed the status of subtask T2898: Support NDP proxy from Open to In progress.Sep 19 2020, 9:39 AM

Hey guys,

I've been working closely with @jack9603301 on testing ndp-proxy (ndppd) and his stateless nat66 code. We've tested SNAT prefix translation and DNAT address translation.

Here's some update:

  • With NFT SNAT prefix translation, the address is not a 1:1 mapping. For example, if we have source prefix 2001:db8:1::/64 and translation prefix of 2001:db8:2::/64, the source address 2001:db8:1::1 will not translate to 2001:db8::2::1. The nftables translation calculates a new address which prevents the 1:1 host address mapping.
  • SNAT Prefix translation is working
  • DNAT address translation is working

In the case of building a DNAT rule, the operator needs to figure out what nftables has assigned the new snat host address. I do not know how nftables determines this, so without first enabling an SNAT rule, and then getting the public IP address, and then building the DNAT ruleset with this calculated host address number.

set nat66 source rule 1 outbound-interface 'eth3'
set nat66 source rule 1 source prefix 'fc00:dead:beef::/64'
set nat66 source rule 1 translation prefix '2001:xxxx:16:24::/64'

set nat66 destination rule 1 destination address '2001:xxxx:16:24::2ae8:926b'
set nat66 destination rule 1 inbound-interface 'eth3'
set nat66 destination rule 1 translation address 'fc00:dead:beef::25'

To get this to actually work, ndppd deb package is installed with the following config file built manually

ndppd.conf:

route-ttl 30000

proxy eth3 {
        router yes
        timeout 500
        ttl 30000
        rule 2001:xxxx:16:24::/64 {
                static
        }
}

proxy eth4 {
        router yes
        timeout 500
        ttl 30000
        rule fc00:dead:beef::/64  {
                static
        }
}

VyOS NAT66 NDPPD Ethernet Topology.png (636×236 px, 22 KB)

The next steps need input from devs - should ndppd be operationally hooked into the nat66 ruleset? That is, with the data we have from nat66 rules, should we just have ndppd config managed automatically? Or - provide config options for nat66 AND separate ndp arp proxy parameters? Alone, stateless nat66 cannot work in all (most?) network topologies. I think there may be use cases where ndp arp proxy is needed, but nat66 is not.

With NFT SNAT prefix translation, the address is not a 1:1 mapping. For example, if we have source prefix 2001:db8:1::/64 and translation prefix of 2001:db8:2::/64, the source address 2001:db8:1::1 will not translate to 2001:db8::2::1. The nftables translation calculates a new address which prevents the 1:1 host address mapping.

I'm thinking about a problem. In fact, now nat66 may have met the one-to-one unique mapping, but the host segment of its mapped address after conversion is not equal to the host segment of the address before conversion

The example of H3C shows that the conversion is also asymmetric. I don't know the effect of other devices, but it seems that this is normal

As long as the address is unique, it should meet the design requirements

I must disagree, prefix translation means only the prefix is translated and the interface identifier keeps the same. Meaning fc00::1111:2222:3333:4444/64 should be translated to 2001:db8::1111:2222:3333:4444/64.

Well, at present, the nat66 prefix conversion of nftables has not found a way to not change the interface identifier. Maybe other people in the community can provide some suggestions?

I think about it carefully. What if the user inputs two unequal prefixes? For example, the prefix 56 is converted to the prefix 64, or vice versa

Do other community members test the behavior of other devices?

prefix translation should only be done on equal sized prefixes. This can be easily checked in verify() stage.

nftables nat66 seems to be the best solution that can be done now, I am still exploring a better implementation, do you have any suggestions?

We are not forced to nftables and still use iptables6 if its not supported properly.

Thank you for your suggestion. I am considering how to implement peer-to-peer translation without modifying the interface identifier. According to some information on the Internet, the support of ipv6 nat is divided into peer address and non-equivalent address. The standard https://tools.ietf.org/html/rfc6296 display does not indicate the interface identifier. The symbol cannot be modified, but only stipulates that the address mapping conforms to the one-dimensional linear equation relationship (that is, an address mapping is unique.

Searching for related solutions is continuing

@c-po The map66 solution last released on July 25th, 2015 does not seem to have been explored. It can work with iptables. I am not sure if it has stopped maintenance. I am considering whether to consider it, but it means that it needs to be compiled, installed and generated deb package , Otherwise vyos cannot install it

I don’t really want to use an old or even obsolete solution, which means we can’t receive its updates to ensure normal maintenance, but if possible, we can maintain it ourselves

https://sourceforge.net/projects/map66/

Hi, everyone, I have been looking for a way to handle the 1-to-1 address prefix symmetry mapping. I contacted the IRC channel of the official community. According to the official information, it seems to be resolved in the 5.8 kernel version, otherwise the patch needs to be backported To 4.19.

The official community tells me that I only need to change snat to into snat prefix to, but need to operate on the kernel above 5.8,otherwise the patch needs to be backported To 4.19.

图片.png (703×1 px, 125 KB)

图片.png (427×1 px, 41 KB)

图片.png (563×1 px, 79 KB)

patch:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3ff7ddb

In linux kernel version 5.8 and above, you can start symmetric translation of ipv6 address prefix by changing snat to to snat prefix to in the policy (without changing the interface identifier), but this function cannot be used before vyos upgrade 5.9 , This patch is not a back-portable patch, so this feature cannot be used in 4.19. There are now 3 solutions:

a) Wait for the kernel to be upgraded to 5.9 merge, and only support symmetric mapping

b) Add compatibility switch to switch between two mapping methods

c) Waiting for the kernel to be upgraded to 5.9 merge, but support 2 different mapping modes at the same time

ps: The function still depends on the NDP proxy

Also come back to this question?

The next steps need input from devs - should ndppd be operationally hooked into the nat66 ruleset? That is, with the data we have from nat66 rules, should we just have ndppd config managed automatically? Or - provide config options for nat66 AND separate ndp arp proxy parameters? Alone, stateless nat66 cannot work in all (most?) network topologies. I think there may be use cases where ndp arp proxy is needed, but nat66 is not.

NDP Proxy has been implemented in T2898. For nat66 to work normally, proxy-ndp must be operated in static mode.

When the merger of nat66 and proxy-ndp is completed, consider adding the function of nat66 auto-proxy-ndp to realize automatic configuration of proxy-ndp

PR:https://github.com/vyos/vyos-1x/pull/520

Note that because the test requirements are not met for the time being (vyos does not use the linux kernel with a kernel version of 5.8+ for the time being), it cannot be tested well. The merged code has not undergone any testing. Please upgrade the vyos linux kernel to 5.8+ , Let me know that I can perform related tests, and merge after testing

PR: https://github.com/vyos/vyos-1x/pull/520

Since the current branch uses the kernel Linux 5.10+, I began to pay attention to the implementation of NPT again. At present, I have completed the following features:

  • SNPT 1:1 mapping
  • DNPT single address mapping
  • DNPT 1:1 mapping
jack9603301 changed Version from vyos 1.3 to -.

I have finished the test of nat66 in GNS lab

Test case topology:

图片.png (410×903 px, 16 KB)

SNPT test case:

GNS Router configuration:

set interfaces ethernet eth0 address 'fc00::1/64'
set interfaces ethernet eth1 address 'fc01::1/64'
set nat66 source rule 1 outbound-interface 'eth0'
set nat66 source rule 1 source prefix 'fc01::/64'
set nat66 source rule 1 translation prefix 'fc00::/64'
set service router-advert interface eth0 prefix ::/0
set service router-advert interface eth1 prefix ::/0

SNPT test results (packet capture at router output port):

图片.png (394×1 px, 100 KB)

DNPT test case:

GNS Router configuration:

set interfaces ethernet eth0 address 'fc00::1/64'
set interfaces ethernet eth1 address 'fc01::1/64'
set nat66 destination rule 1 destination address 'fc00::/64'
set nat66 destination rule 1 inbound-interface 'eth0'
set nat66 destination rule 1 translation address 'fc01::/64'
set service router-advert interface eth0 prefix ::/0
set service router-advert interface eth1 prefix ::/0

DNPT test results (fc00::/64 requests SSH):

图片.png (587×980 px, 26 KB)

jack9603301 changed the task status from In progress to Needs testing.Jan 24 2021, 9:13 AM
jack9603301 moved this task from In Progress to Finished on the VyOS 1.3 Equuleus board.
jack9603301 changed the status of subtask T2898: Support NDP proxy from Open to In progress.Jan 13 2022, 7:40 PM

Is there a way to get this to work with a dynamically assigned /64 PD from my ISP?

set nat66 destination rule 10 inbound-interface 'eth1'
set nat66 destination rule 10 translation address 'fc00::/64'

set nat66 source rule 10 outbound-interface 'eth1'
set nat66 source rule 10 source prefix 'fc00::/64'
set nat66 source rule 10 translation address '2603:xxxx:xxxx:6f01::/64'

but 2603:xxxx:xxxx:6f01::/64 is assigned dynamically through eth1

@ajgnet If you have a way to limit the dynamic prefix to a known prefix, then using 1:1 NAT66 prefix translation should work (only the host segment is dynamic)

n.fort changed the status of subtask T4598: nat66 - Add exclude options from In progress to Needs testing.Aug 9 2022, 10:39 AM

@ajgnet If you have a way to limit the dynamic prefix to a known prefix, then using 1:1 NAT66 prefix translation should work (only the host segment is dynamic)

Yes, would be great to fully support dynamic prefix when the prefix is not known

Yeah, in my case as well, NPTv6 is mostly only useful if it it works with a dynamic (from DHCPv6-PD) prefix, since that's how my ISP provides addresses (AFAIK I'd have to pay for a business connection to get a static prefix, though I haven't actually called and asked myself). I'm tempted to play with hacking something together by building from source myself with some tweaks to auto-update the nat rules when it gets a new PD prefix.