IPv6 Unique Local Addresses (ULAs) are the modern successor to IPv4 private addresses (like 10.0.0.0/8, 192.168.0.0/16). Defined in RFC 4193, they are intended for local communication within a site or between a limited set of sites, and are not expected to be routable on the global internet. This article explains what ULAs are, how to generate them correctly, and when to use them in your network design.

What Are IPv6 Unique Local Addresses?
ULAs have the prefix fc00::/7, which splits into two halves:
fc00::/8— Reserved for future definition (currently not used).fd00::/8— Locally assigned ULAs. The next 40 bits form a Global ID, followed by 16 bits of Subnet ID, and 64 bits of Interface ID. The structure is:
| 8 bits | 40 bits (Global ID) | 16 bits (Subnet ID) | 64 bits (Interface ID) |
| fd | pseudo-random | your subnet | EUI-64 or random |
The key difference from IPv4 private addresses is that ULAs are designed to be globally unique (through the random Global ID), reducing collision risk when merging networks or connecting via VPN.
Why Use ULAs?
- Private internal networks — No need for public IPs for devices that never need direct internet access.
- Stable addressing — Unlike link-local addresses (
fe80::/10), ULAs are routable within your site and can be used for DNS, servers, and infrastructure. - Network merging — The random Global ID makes accidental overlap extremely unlikely.
- VPNs and multi-site — ULAs can be routed between sites without conflict with public addresses.
How to Generate a ULA Prefix
The Global ID must be generated pseudo-randomly. Do not use a predictable value like a sequence number or your company’s ASN. The recommended method is:
- Obtain a timestamp (e.g., current time in seconds since epoch).
- Obtain a unique identifier (e.g., MAC address of a router, or a machine ID).
- Concatenate them and compute an SHA-1 hash.
- Take the lower 40 bits of the hash as the Global ID.
Example Generation (Python)
import hashlib
import time
import uuid
# Replace with your own unique inputs
timestamp = str(int(time.time()))
machine_id = uuid.getnode() # MAC address as integer
# Concatenate and hash
seed = (timestamp + str(machine_id)).encode()
hash_result = hashlib.sha1(seed).hexdigest()
# Take first 40 bits (10 hex characters)
global_id = hash_result[:10]
# Form the prefix
prefix = f"fd{global_id[:2]}:{global_id[2:6]}:{global_id[6:10]}::/48"
print(prefix) # e.g., fd12:3456:789a::/48
You can also use our IPv6 ULA Generator to instantly create a valid /48 prefix with a random Global ID.
Subnetting and Address Planning
Once you have a /48 prefix (e.g., fd12:3456:789a::/48), you have 16 bits for subnetting, giving 65536 subnets (each /64). A common plan:
| Subnet ID (hex) | Purpose |
|---|---|
| 0000 | Infrastructure / routers |
| 0001 | Servers |
| 0002-00FF | Reserved |
| 0100 | Management network |
| 0200-FFFF | User VLANs / dynamic |
For the Interface ID, use either EUI-64 (based on MAC address) or a random stable identifier. EUI-64 can expose the MAC address to the network, so consider using privacy extensions (RFC 7217) for clients.
When NOT to Use ULAs
- Global internet services — Use Global Unicast Addresses (GUAs) for publicly reachable servers.
- NAT avoidance — ULAs are not meant to be NATed; if you need internet access, combine with GUAs or use a proxy.
- Link-local only — For single-link communication, use
fe80::/10.
Common Pitfalls
- Using
fc00::/8— The standard currently only definesfd00::/8for local assignment.fc00::/8is reserved and may never be allocated. Always usefd. - Predictable Global ID — If you use a simple pattern (e.g.,
fd00::/8with all zeros), you risk collision when merging networks. - Mixing with GUAs incorrectly — When both ULAs and GUAs are present, ensure routing policies prefer the correct address for outbound traffic (typically GUAs for internet, ULAs for internal).
- Forgetting to add routes — ULAs are not automatically routable; configure static routes or dynamic routing protocols (e.g., OSPFv3) within your site.
- Using ULAs for public DNS — ULAs should not appear in public DNS; use private DNS or split-horizon DNS.
FAQ
What is the difference between ULA and link-local?
Link-local addresses (fe80::/10) are only valid on a single link and are not routable. ULAs (fd00::/8) are routable within a site and can span multiple subnets.
Can I use ULAs with NAT?
Technically yes, but it defeats the purpose. ULAs are meant for end-to-end connectivity within a site. If you need internet access, assign a GUA to the device or use a proxy.
How do I ensure my ULA prefix is unique?
Follow the RFC 4193 generation algorithm using a pseudo-random Global ID. The 40-bit space (about 1 trillion possibilities) makes collision negligible.
Should I use ULAs or GUAs for internal servers?
Both. Assign a ULA for stable internal access and a GUA if the server needs direct internet access. Use DNS to return the appropriate address based on the client’s location.
Can I route ULAs over the internet?
Technically possible, but not recommended. Many ISPs filter fc00::/7 traffic. ULAs are designed for private networks; use VPN tunnels between sites.
Conclusion
IPv6 Unique Local Addresses provide a robust, collision-resistant addressing scheme for private networks. By generating a random Global ID and planning your subnet allocation, you can build scalable internal infrastructure without relying on NAT. Use our IPv6 ULA Generator to quickly create your prefix and start designing your network today.