[Tutorial] How to Secure and Implement Internal IPv6 NAT66/NPt

Started by millerwissen, June 17, 2025, 03:11:13 PM

Previous topic - Next topic
Hello!

I made a tutorial about this on the pfsense forums and my goal was to make it here as well since I use both even know nowadays I am mostly leaning towards OPNsense due to the netgate policies but I personally prefer the UI of pfsense just old habits and whatnot but anyway.

I literally am tired of reading about people not knowing how IPv6 works on the internet in general assuming that you either have only public addresses or nothing, anything outside of ULAs without internet access or public IPv6 = impossible.  The worst part is that they use this an excuse not to implement IPv6 in their network but now that's over.

The point of this tutorial will be to change this concept once and for all and hopefully this will change a few things for a lot of people out there. As in I want to plant the final nail in the coffin and answer all the questions once and for all.

If you just want the tutorial skip to the chapter where I talk about this but first an introduction to the scope of the problem. And excuse my rant :)

1 -- Introduction:

NAT44 came to resolve a problem the lack of IPv4 addresses or at least many would assume that at first glance or if you ask the people at IANA about RFC1918 (that is after they regain consciousness from their panic attacks upon you mention that RFC) you will get a lot of angry, dismissive and frowny comments from them about how awful it was and that IPv6 with all public addresses came exactly to address this problem, as in the whole point of IPv6 was to solve the lack of addresses of IPv4.

The reality is that NAT44 brought one major security benefit, your computers can be in a safe internal network without being immediately exposed to the internet or rely on a system firewall which you may/may not have control over it, you also don't have to worry about unencrypted traffic being sniffed by your ISP as in traffic in transit from amongst your internal computers, does it mean NAT is a security feature? Yes and No, the whole point of having an edge and core router is to control and direct traffic with far more horsepower than your phone/fridge/security camera has in terms of routing and firewall but we'll get to that.

The point of NAT is simple, control, your network your rules no one else has the right to force you to design your internal network a certain way, as for security it does provide you with advanced port control where it needs it, you can route ports out different uplinks, load balance and just in general have full control, but that means that if you have a machine where having a certain port exposed to the internet will cause it to be compromised by being on an internal network that cannot be reached from the outside it puts you in a position where NAT is your most important security feature in this example, but of course if you were to route that port to a public ip address (v4 or v6 doesn't matter what it is) you would be just as compromised, the key is control.

The people at IANA decided that the common/average IPv6 deployment MUST be public and NAT is evil, and your system must be able to handle security individually (given no network firewall in between such as opnsense) which is a common case with the average people which only have an ISP provided box in their home if you think about it, not everyone out there is even aware of the benefits of having a firewall in their network and can perceive that as an unnecessary expense because 'it just works', but in reality having a firewall is quite important and no i'm not shilling for firewall platforms whether it's opnsense pfsense or any other firewall solution available in specific, regardless whether it's paid or free this applies to any firewall out there that is controlling the traffic from outside to inside.

Ask yourself, do you want or need a public ip address on your smart fridge, your phone, your security camera, your computer even, do you actually NEED it, as it are you actually accessing it's resources directly over the internet (not using an encrypted site-to-site tunnel such as wireguard with static routes/iBGP) do you want a botnet to have the same access to your devices as you do while they constantly try to use common known exploits and even brute force to get into all of your devices while you sleep? Does that sound like a good way to setup network? Because this is how IANA thinks it should be, you buy a fridge which you have 0 access to it's firewall features it relies on some cloud server for control/software updates if they decide to make your fridge EOL and you keep it connected you're on your own and they never provided any access to control services/ports for it most likely.

Yes I am absolutely furious with IANA for many reasons, I have tried to push for an ID (Internet Draft) in the past to acknowledge and standardise the prefixes for NAT66 but upon being met with hostility by pretty much everyone there I gave up and instead decided to simply spread the word because the bottom line is this, you don't need anyone's permission to do anything internally you can run any IP prefix inside your private network the only advantage of having standard prefixes is to avoid the possibility of not being able to reach an external network. They did standardise some of the prefixes and pretty much all of them are in the f000::/4 subnet for many purposes and not only NAT/ULA but the "F" prefix was designed to be a special use case prefix multicast/ula/link-local/site-local etc.

What is f000::/4? It's everything from f000:0000:0000:0000:0000:0000:0000:0000 to ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff It consists of 8 hextets (unlike IPv4's octets IPv6 it's called hextets).  It is perfect for NAT66/NPt it allows you to customise 8 hextets allowing you lots of freedom when organising your internal addresses, you can do something like this for example:

f1:33:3:1a :: 1 : 2 : 3 : 4

f1 = Network 1/Organisation 1
33 = France
3  = Strasbourg
1a = Location 1 Building A
:: = Separator
1  = 1st Internal Separation
2  = 2nd Internal Separation
3  = 3rd Internal Separation
4  = 4th Internal Separation

This gives you the network f1:33:3:1a::/64 for this site/location. Again just an example feel free to customise as you please it's your network after all.

Something like f1:33:3:1a::77::2a (could mean for instance 77 = Virtual Machines, 2a = VM 2 and the A is the first virtual IP or simply 2 for physical nics) f1:33:3:1a::/64 being your network in this example, conveniently sized, easy to route, organised and now if the public IPv6 changes or the entire prefix changes your internal addresses are static/dynamically assigned by your own infrastructure and everything will work as expected without any outages.

See how customisible this is? Instead of using randomly assigned ISP owned addresses you have lots of flexibility and lots of addresses thanks to f000::/4, not everything is available for use let's explore further:

Let's separate these further:

f000::/8 - f999::/8 = The "numbers", Available to use!

fa::/8 and fb::/8 = Also not in use, Available to use!

fc::/8 and fd::/8 = Those are actual ULAs RFC4193, these are used by many things because it's an "official" local IPv6 address much like the ones from RFC1918 but the downside is using these can lead to problems for instance the matter protocol assigns fd::/8 addresses to your local devices for internal communications, so if you use matter at home i would stay away from using fd::/8 as your internal network, fc can be used by certain things like VPNs and whatnot so to avoid the possibility of things not working i usually don't touch fc either but technically fa fb fc are all options as well I like using fa fb for SAN networks.

fe80::/8 - I do not touch fe either because of fe80::/10 as defined in RFC 4291 is used for link-local this is a core feature of IPv6, fec0::/10 used to be site local unicast but it has been since deprecated RFC 3879 for references. and finally ff00::/8 is multicast also from RFC4291.

In short you can use anything from f000::/4 except "fe,ff" and you should avoid "fc,fd" just in case something else may need it, literally everything else up for grabs eg. f1f3:: f333:: f16:: f22:: f35:: f117:: etc

so for a SAN literally fa::3:1a/64 as the example for the VM used earlier even fa::1 would be a nice short ipv6 in this network, it can be even easier to remember than IPv4, all this can be your reality it does not have to be complicated it does not have to be difficult, IPv6 can be this easy.

2 -- Understanding your options at the network design level.

A - Direct IPv6:
This could be a desired configuration sometimes, just like servers that had their public IPv4 directly on device, if you have limited resources a VM or a machine somewhere with a single ipv4 and even a large ipv6 prefix but a very simple purpose it may be the case that all you want is just a public ipv6 and ipv4 with nothing in between but ufw/iptables and that's about it, there is a use case for it but certainly shouldn't be the default just like using public IPv4 even if there were enough IPv4s out there would've seem quite insecure because it is but it means no added routing complexity.

B - NAT66/NPt:
This is basically the same as RFC1918 (the good old 192.168.x.x addresses) the difference here between NAT66 and NPt is how ports are handled with NAT66 you will have the same limitation as you have with IPv4 in terms of ports which is 65.536 ports per public IP, if this isn't enough you can use multiple public ips, each will give you the same number of ports, keep in mind this is the amount of concurrent connections not the number of maximum connections you can ever make, if you understand this limitation which for most home users it really isn't a concern for most cases then NAT66 is fine here, also if you run your static routes/iBGP with wireguard anything handled by your site-to-site VPNs do not count so if your home workstation is "f1:33:3:1a::55:1" and your office workstation is "f2:33:3:1a::55:1" and they're connected through site-to-site vpn then this internal connection goes through the VPN and does not count towards your port limit, if you have lots of site but they're all internally interconnected NAT66 is still plenty suitable, the other option is NPt which will translate all your internal addresses to the external prefix, this however assumes you have a prefix which to many may seem like an obvious assumption right? surely every ISP that supports IPv6 will just give you at least an /64 you can delegate to your network with all ports open, surely right? no..

for NPt it will translate the 'right side' of the :: (separator) to the left side so using the example from earlier:

Example Internal IPv6 = f1:33:3:1a::1:2:3:4a/64
Example External IPv6 Network = 2001:4860:4860::/64
Example NPt Translated Address: 2001:4860:4860::1:2:3:4a/64

In Germany for instance if you call Vodafone and ask for bridged mode you will get 1x public IPv4 (not a given in this day and age.. sometimes you're stuck with CGNAT or even DS-Lite so I can't complain too much about them) but if you use a /128 your IPv6 will be fully open, as in you can route services but a /64 prefix will not be open ports, this can be on purpose to mitigate some of the problems mentioned earlier since home users are not expected to know how to design/handle their networks and they decided to silently block "all"/most incoming ports by default was a good enough solution to reduce botnets and compromised systems, by having NAT66 on your network you actually have all 65.536 ports available to you but only if you use /128 on the WAN side (single IPv6) and NAT66 so obviously here NAT66 is a no-brainer, but if your ISP allows you to use your prefix you might also consider NPt.

I have also a tutorial on how to do that for pfsense on the pfsense forums so here I will only focus on OPNsense even though it's mostly similar:

3 -- How to do that in OPNsense:

- Go to Firewall > NAT > Outbound

- Change NAT Mode to Hybrid then Save/Apply Changes.

- Add a New Map Rule as follows:

--------
Interface: WAN
TCP/IP Version: IPv6
Protocol: Any
Source Address: LAN net [or manually set the network with 'Single host or Network' if desired eg. f1:33:3:1a::/64 (this is the example from earlier)]
Translation: WAN Address (or the respective WAN interface)
Description: "F--- IANA BS I have NAT66 and I am Free" or something else of your preference
--------

- Save and Apply Changes

4 -- Additional but important things:

IPv6 handles things a little differently you have RA (Router Advertisement) and DHCPv6, DHCPv6 is a little more nerfed compared to IPv4 with fewer options but it's much of the same idea, RA works along with DHCPv6 but it assigns addresses on in a different manner to DHCPv6  you should have both enabled, some devices do not support DHCPv6 and some will take addresses from either or both you have plenty of addresses it's not a problem, it is very common for a device with IPv6 to have multiple addresses assigned to it so don't be alarmed if you see literally a single nic with 5 IPv6 addresses depending on how your network runs, I personally manage my networks with a separate DNS/DHCP server solution you can also do that which will give you way more control over things or if you want to stick to running those on OPNsense directly you can do the following:

- Go to Services > Router Advertisements:

--------
Router Advertisements: Assisted (if you have a DHCPv6 server which you should ideally this is the correct mode)
Router Priority: High
Advertise Routes: Prefix:: f1:33:3:1a:: Length:: /64 (this is the example from earlier)
DNS Servers:
1 -- f1:33:3:1a::111:1/64 (this an example Internal IP)
2 -- f1:33:3:1a::111:2/64 (this an example Internal IP)
Domain Search List: dynamic.yournetwork.yourdomain.net (if have a domain for your location/network/whatever you can set it here just like DHCP).
--------

Save and Restart the RA Service.

Important: RA by default will assign any available address within your range, but it will not assign addresses already in use, unlike DHCP you cannot block or set a range within a network (sadly) but because it will not assign anything in use and usually really random addresses it's unlikely to cause problems but something to keep in mind if you do a lot of static addressing.

- Go to Services > ISC DHCPv6

- There are many ways to configure DHCPv6, but if you have NPt/PD you'll likely have your delegated prefix range here
- You can enable/disable the server if you have a separate more capable DHCP setup the options there should be pretty straightforward so i'll not get into details it is much the same as IPv4 except for Gateway, this is handled by RA in IPv6 instead you only assign the addresses themselves via DHCPv6, easy right?

Save and Restart the ISC DHCPv6 Server.

Since not all of the IPs within f000::/4 are considered "bogon" networks technically if OPNsense is not aware to drop any attempts to connect to an external network in these addresses it will forward to the upstream gateway, this may be desired under specific configurations but if not you may also want to create a rule to block these addresses from leaving through your WAN, that way if you accidently mistype an internal ip or due to a configuration error it is not on your local network it will also protect from the exploit of having that network reachable from your ISP side the same way you have that with RFC 1918 except since this isn't a standard configuration most routers don't know to drop these addresses so you must do that yourself, to do that it's pretty simple:

- Go to Firewall > Rules > WAN:

- Add a new Rule:

--------
Action: Block
Interface: WAN
TCP/IP Version: IPv6
Protocol: Any
Source: Single Host or Network f000::/4
Destination: Any
Description: Block internal IPv6 (f000::/4) from leaving via WAN
--------

- Save and Apply Changes

- Restart your whole network, Ping and be amazed :)

- No traffic? Check your gateway settings and other rules conflicting.

- What about NAT64? That's for something else entirely and in RFC 6052 64:ff9b::/96 was assigned for that use case but this is not to be confused with NAT66 these are entirely different uses and it's beyond this tutorial.

I will also make a tutorial about multi-site vpn someday but goes without saying that by having these internal ipv6s you can obviously configure site-to-site encrypted tunnels and pretty much interconnect everything everywhere you can ping your office your datacentres everything directly using encrypted tunnels the possibilities are endless all it needs is a different left side of the /64 separator for each location and you're all set, tunnel + static routes or iBGP and your whole intranet cyberspace is here.