IPv6 ULA / NPTv6 Configuration

AstLinux supports IPv6 Unique Local Addresses (ULA) with Network Prefix Translation (NPTv6) to assign static local routable IPv6 subnets which can be have their prefix mapped 1:1 to Global Unicast Addresses (GUA) for global Internet access.

This feature is often used in conjunction with: DHCPv6 with Prefix Delegation

Should everyone configure IPv6 with ULA / NPTv6 ? Not everyone. For some, simply selecting “Assign GUA Prefix” for your LAN internal interface is all that is needed to provide global IPv6 connectivity for your devices.

Listed are common situations when IPv6 with ULA / NPTv6 is useful, if any applies continue reading below:

  • OpenVPN Server - you want to route IPv6 in the tunnel
  • Downstream IPv6 subnets that are statically defined
  • Transition from IPv4 to IPv6 but don't want GUA's everywhere
  • Define static firewall rules based on ULA's
  • Want to design an IPv6 network containing minimal ISP owned IPv6 prefixes

Note: AstLinux 1.3.0 or later is required

Unique Local Addresses (ULA)

What is a ULA ? IPv6 ULA's are used similarly to IPv4 local adresses e.g. 10.0.0.0/8. A good reference and random ULA generator can be found here: Unique Local IPv6 Generator

The 40-bit random part of the ULA makes it statistically unlikely that you will have a collusion with any other randomly generated ULA /48 prefix. Whether merging networks together or VPN use, a truly “unique” ULA is worth the effort.

Tip → If the IPv6 address begins with fd it is a ULA.

Some other examples, fd00::/48, fd01:1:1::/48, fd00:dead:beef::/48 are all examples of ULA's, but not very “unique” and should be avoided in practice.

As an alternative to using a web site for generating ULA prefixes, AstLinux has a CLI command unique-local-ipv6 for generating random ULA /48 prefixes:

# unique-local-ipv6
fd06:d115:91f1::/48

The unique-local-ipv6 command generates a new random ULA every time it is run.

Keep in mind you only need one ULA/48 prefix for your complete network. You will later carve the ULA/48 into ULA/64's for IPv6 autoconfig use. Since these are static and manually assigned, develop a method to keep track of the assigned /64's.

Global Unicast Addresses (GUA)

What is a GUA ? IPv6 GUA's are globally routable IPv6 addresses in the 2000::/3 prefix space.

Tip → If the IPv6 address begins with 2 it is a GUA.

If you want to connect to an IPv6 server on the internet, your device must either have a GUA, or a ULA with ULA→GUA prefix translation available.

Network Prefix Translation (NPTv6)

Is NPTv6 some sort of IPv6 NAT ? While NPTv6 is implemented in the Linux kernel NAT table, it is not the TCP/UDP port altering NAT we are familiar with IPv4. NPTv6 is a simple 1:1 mapping of one prefix to another prefix, the TCP/UDP ports remain the same. Often NPTv6 is stateless, but is implemented with the statefull firewall in AstLinux, so connection tracking occurs.

Note → NPTv6 is not the same as NAT66, which should be always avoided.

The benefit of NPTv6 is to have a network of static, never changing ULA's that can be mapped to a GUA of the same prefix length for internet access. With that in mind, if your ISP provides you a GUA/60 prefix, you should only assign ULA/60 prefixes on your network so a 1:1 mapping can occur. This will allow inbound EXT→LAN forward rules to be applied in the firewall using static ULA addresses. If your ISP provides you a GUA/56 prefix you should assign ULA/56 prefixes on your network, etc. .

Tip → If your ISP only provides a GUA/64 prefix it is not possible to perform a 1:1 mapping to a ULA/64 that won't collide with the GUA/64 prefix, but for only outbound initiated connections you can map a ULA/60 to your GUA/64 and the statefull firewall's connection tracking will properly return the packets to the ULA address.

Example IPv6 ULA / NPTv6 Setup

Select the Network Tab in the web interface.
Network Tab

External Interface: → Connection Type:
This example assumes an entry containing: DHCPv6
Network Tab

For this example we will be defining three internal interfaces, assume a GUA/60 prefix from the ISP, and the unique-local-ipv6 generated fd06:d115:91f1::/48 ULA from above.

1st LAN Interface: Both GUA/64 and ULA/64 (<ula>:1::1/64) prefixes are “IPv6 Autoconfig” advertised to devices.

2nd LAN Interface: Only the ULA/64 (<ula>:2::1/64) prefix is “IPv6 Autoconfig” advertised to devices.

3rd LAN Interface: No routable IPv6 is enabled.

Example Internal Interface settings are:
Internal Interfaces Network Tab

Note → A “Reboot System” is required to apply any changes related to the interface settings.

Configure Network Prefix Translation Firewall Plugin:
Network Prefix Translation

Click Configure Plugin, set ENABLED=1 and …

Define the global prefix, since we are using dynamic DHCPv6 only specify the prefix length:

NET_PREFIX_TRANSLATION_GLOBAL_PREFIX="::/60"

Define the local prefix, this must be fully qualified:

NET_PREFIX_TRANSLATION_LOCAL_PREFIX="fd06:d115:91f1::/60"

Tip → ULA's are /48's but you typically want a symmetric mapping so inbound firewall rules work. Only special situations may desire non-symmetric mapping. In general use the same _LOCAL_PREFIX length as the _GLOBAL_PREFIX length.


Since NET_PREFIX_TRANSLATION_UPDATE_ON_STATUS=1 is enabled by default, when the DHCPv6 client detects a change in the global prefix, the Network Prefix Translation Firewall Plugin will be called to update using the new global prefix.


Important → Carving the ULA/48 into ULA/64's that will result in a 1:1 mapping to a GUA/60 is important to understand. In the example above we used IPv6/nn entries of <ula>:1::1/64 and <ula>:2::1/64 (where <ula> is shorthand for fd06:d115:91f1). For a ULA/60 the largest possible sequence is <ula>:0::1/64 to <ula>:f::1/64, which are 16 possibilities, but be careful the first <ula>:0::1/64 best not be used since that will share the same address space as the first “Assign GUA Prefix”, since they are indexed 0, 1, etc. . If we had selected a second “Assign GUA Prefix” (index 1) it would be best to start the IPv6/nn entries with <ula>:2::1/64 or higher, best practice is to start a little higher.

Suggestion on how to manage your ULA's with a GUA/60 prefix:
GUA Prefix Delegation <gua>0::1/64, <gua>1::1/64, etc. (dhcp6c automatic indexing 0, 1, etc.)
ULA's with Assign GUA Prefix <ula>:5::1/64, <ula>:6::1/64, etc. (use IPv6/nn in Network tab with “Assign GUA Prefix”)
ULA's for Local IPv6 <ula>:a::1/64, <ula>:b::1/64, etc. (use IPv6/nn in Network tab with “enabled”)
ULA for OpenVPN <ula>:f::1/64 (use Network IPv6/nn in OpenVPN Server Configuration)

For completeness, a ULA/56, the largest possible sequence is <ula>:00::1/64 to <ula>:ff::1/64, which are 256 possibilities. In the GUA/56 with ULA/56 case, it is a good idea to start your IPv6/nn entries with <ula>:10::1/64 or such to leave plenty of room for reserved “Assign GUA Prefix” entries since you have plenty to use.

Suggestion on how to manage your ULA's with a GUA/56 prefix:
GUA Prefix Delegation <gua>00::1/64, <gua>01::1/64, etc. (dhcp6c automatic indexing 00, 01, etc.)
ULA's with Assign GUA Prefix <ula>:10::1/64, <ula>:11::1/64, etc. (use IPv6/nn in Network tab with “Assign GUA Prefix”)
ULA's for Local IPv6 <ula>:20::1/64, <ula>:21::1/64, etc. (use IPv6/nn in Network tab with “enabled”)
ULA for OpenVPN <ula>:f0::1/64 (use Network IPv6/nn in OpenVPN Server Configuration)

OpenVPN Server IPv6 ULA

The use of ULA's is particularly useful with VPN's since ULA's are static. Additionally, VPN's can route ULA's in a tunnel just as easily as GUA's.

Example OpenVPN Server Setup:

Network tab → VPN Type:
OpenVPN Server

Server Mode:

Network IPv6/nn: fd06:d115:91f1:f::1/64

“push”: route-ipv6 fd06:d115:91f1::/48