How to Assign an Entire IPv6 Address Block (/64) to a Network Interface in Linux


1 views

When working with IPv6 at scale, traditional IP assignment methods become impractical. While ip addr add works fine for individual addresses, assigning a full /64 block (18,446,744,073,709,551,616 addresses) manually would be impossible.

Modern Linux kernels support automatic address assignment for entire blocks through these methods:

# Enable IPv6 forwarding
sysctl -w net.ipv6.conf.all.forwarding=1

# Assign a /64 block to eth0
ip -6 address add 2001:db8:1234:5678::/64 dev eth0

# Alternatively using sysctl (for temporary assignment)
echo 1 > /proc/sys/net/ipv6/conf/eth0/accept_ra_pinfo

For application development, you'll want programs to bind to any address in the range:

// C example binding to any address in block
struct sockaddr_in6 addr;
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(PORT);
inet_pton(AF_INET6, "2001:db8:1234:5678::", &addr.sin6_addr);

// Allow binding to any IP in the /64 block
setsockopt(sock, IPPROTO_IPV6, IPV6_BINDANY, &enable, sizeof(enable));
bind(sock, (struct sockaddr*)&addr, sizeof(addr));

For production environments, consider these optimizations:

# Make the assignment persistent
echo "net.ipv6.conf.eth0.accept_ra_pinfo = 1" >> /etc/sysctl.conf

# For DHCPv6 prefix delegation:
cat > /etc/dhcp/dhclient6.conf <

If addresses aren't being properly assigned:

  1. Verify kernel supports IPv6: grep IPV6 /boot/config-$(uname -r)
  2. Check route acceptance: sysctl net.ipv6.conf.eth0.accept_ra
  3. Test with tcpdump: tcpdump -i eth0 ip6

Remember that proper firewall configuration (ip6tables/nftables) is crucial when working with large IP ranges.


When working with IPv6 at scale, manually assigning individual addresses from a /64 block (18 quintillion addresses) to an interface is impractical. Traditional methods like:

ip addr add 2001:db8::1/64 dev eth0
ip addr add 2001:db8::2/64 dev eth0

become unmanageable when you need the entire range available for dynamic binding.

Linux supports assigning entire subnets to interfaces through kernel parameters and network configuration tools:

# Assign entire /64 to eth0
ip addr add 2001:db8::/64 dev eth0

# Verify the assignment
ip -6 addr show dev eth0

This single command makes all addresses in the 2001:db8::/64 range available for binding.

Method 1: Using iproute2

# Assign the block
sudo ip -6 addr add 2001:db8:feed::/64 dev eth0

# Make it persistent (Debian/Ubuntu)
echo "iface eth0 inet6 static
    address 2001:db8:feed::1
    netmask 64" >> /etc/network/interfaces

Method 2: NetworkManager Configuration

[connection]
id=eth0-ipv6
type=ethernet
interface-name=eth0

[ipv6]
method=manual
address1=2001:db8:beef::/64

With the block assigned, applications can bind to any address in the range:

// C example
struct sockaddr_in6 addr;
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(8080);
inet_pton(AF_INET6, "2001:db8::1234", &addr.sin6_addr);
bind(sock, (struct sockaddr*)&addr, sizeof(addr));
  • Enable privacy extensions: sysctl -w net.ipv6.conf.all.use_tempaddr=2
  • Configure proper firewall rules for the entire block
  • Consider implementing route advertisements if needed

Problem: Applications can't bind to addresses despite the block being assigned.
Solution: Check kernel parameters:

sysctl -w net.ipv6.ip_nonlocal_bind=1

This allows binding to non-local addresses within the assigned block.