IPv6 - System IPv6 Settings
System IPv6 settings in VyOS provide control over IPv6 parameters at the level of the entire system, including forwarding, Duplicate Address Detection (DAD), multipath routing, neighbor discovery and other critical parameters of the IPv6 network stack.
Key Capabilities
- IPv6 Forwarding: Control over routing IPv6 packets between interfaces
- Strict DAD: Strict mode for detecting duplicate addresses
- Multipath Hashing: Layer 4 hashing for balancing IPv6 traffic
- Neighbor Table: Management of the IPv6 neighbor table (the equivalent of ARP for IPv4)
- Nexthop Tracking: Control over next-hop tracking for dynamic routing
- Interface-specific Settings: Disabling IPv6 on specific interfaces
- Sysctl Parameters: Low-level kernel parameters for IPv6
IPv6 Overview in VyOS
VyOS fully supports IPv6 and runs in dual-stack mode (IPv4 and IPv6 simultaneously) by default. System IPv6 settings let you control the behavior of the IPv6 stack at the operating-system kernel level.
Key Differences from IPv4
- Neighbor Discovery Protocol (NDP) instead of ARP
- SLAAC (Stateless Address Autoconfiguration) for automatic configuration
- Router Advertisement (RA) for advertising prefixes
- Duplicate Address Detection (DAD) for preventing address conflicts
- Privacy Extensions (RFC 4941) for temporary addresses
- 128-bit addresses instead of 32-bit
IPv6 Forwarding
Description
IPv6 forwarding controls the system’s ability to route IPv6 packets between interfaces. By default VyOS acts as a router with IPv6 forwarding enabled.
Configuration
# WARNING: This command DISABLES IPv6 forwarding
# Used only in special cases (firewall without routing)
set system ipv6 disable-forwarding
commit
saveImportant:
- IPv6 forwarding is enabled by default on VyOS
- The
disable-forwardingcommand turns off IPv6 routing - For the device to operate as a router, forwarding must be ENABLED
- Disable it only if VyOS is used as an endpoint rather than a router
Checking the State
# Check IPv6 forwarding in the kernel
sysctl net.ipv6.conf.all.forwarding
# Should be: net.ipv6.conf.all.forwarding = 1 (for a router)
# Check the VyOS configuration
show configuration system ipv6 | grep forwarding
# If you see "disable-forwarding" - forwarding is offUse Cases
- Routers: Forwarding must be ENABLED (default)
- Firewall without routing: Can be disabled
- Endpoint systems: Disable for security
Strict DAD (Duplicate Address Detection)
Description
Strict DAD (Duplicate Address Detection) is a strict mode for detecting duplicate IPv6 addresses. When a duplicate Link-Local address is detected, IPv6 is completely disabled on the interface.
How DAD Works
- When an IPv6 address is assigned, the system sends a Neighbor Solicitation (NS) to verify uniqueness
- If another node is using this address, it replies with a Neighbor Advertisement (NA)
- When an NA is received:
- Normal mode: The address is marked as duplicate, but the interface keeps working
- Strict DAD: IPv6 is completely disabled on the interface
Configuration
# Enable strict DAD
set system ipv6 strict-dad
commit
saveVerification
# Check the configuration
show configuration system ipv6
# Check the state of IPv6 addresses
show interfaces
# Check the logs for duplicate address messages
show log | match "duplicate"Example Scenario
# Situation: Two routers on the network share the same Link-Local address
# fe80::1 is configured on two different interfaces in the same segment
# Without strict-dad:
# - The address is marked as DAD failed
# - The interface keeps working with its other addresses
# With strict-dad:
# - IPv6 is completely disabled on the interface
# - Potential incorrect routing is preventedUse Cases
- Production networks: Recommended to enable to prevent IPv6 conflicts
- Managed Infrastructure: Mandatory with automated configuration
- Cloud Environments: Critical for Yandex Cloud, VK Cloud (automatic address assignment)
Multipath Hashing for IPv6
Description
Multipath hashing determines the algorithm for distributing IPv6 traffic across multiple equal-cost paths (ECMP - Equal-Cost Multi-Path). Layer 4 hashing uses transport-layer information to ensure consistent routing.
Configuration
# Enable Layer 4 hashing for IPv6 multipath
set system ipv6 multipath layer4-hashing
commit
saveHow Layer 4 Hashing Works
Without layer4-hashing (default):
- Only Source IPv6 and Destination IPv6 are used
- Hash:
hash(src_ipv6, dst_ipv6)
With layer4-hashing:
- Source IPv6, Destination IPv6, Protocol, Source Port, Destination Port are used
- Hash:
hash(src_ipv6, dst_ipv6, protocol, src_port, dst_port)
Benefits of Layer 4 Hashing
- Preserving packet order: All packets of a single TCP/UDP session take the same path
- Better distribution: More even balancing across paths
- Avoiding reordering: Prevents TCP retransmits caused by out-of-order packets
- Per-flow balancing: Each traffic flow gets its own path
Example ECMP Configuration with IPv6
# Configure two equal-cost IPv6 routes
set protocols static route6 2001:db8:100::/48 next-hop 2001:db8:1::1
set protocols static route6 2001:db8:100::/48 next-hop 2001:db8:1::2
# Enable layer4-hashing
set system ipv6 multipath layer4-hashing
commit
saveVerification
# Check IPv6 routes with ECMP
show ipv6 route
# You should see multiple next-hops for a single prefix
# Example:
# S> 2001:db8:100::/48 [1/0] via 2001:db8:1::1, eth0, weight 1, 00:01:23
# via 2001:db8:1::2, eth1, weight 1, 00:01:23
# Check the sysctl parameter
sysctl net.ipv6.fib_multipath_hash_policy
# Value: 1 (layer4 hashing)Use Cases
- Dual-WAN routers: Balancing between two IPv6 links
- BGP ECMP: Distributing traffic across multiple BGP next-hops
- Data Center: Load balancing across servers
- ISP Networks: Even distribution in the core network
Neighbor Table Size
Description
The Neighbor Table is the IPv6 equivalent of the ARP cache for IPv4. It stores the mapping between IPv6 addresses and MAC addresses. The table size is critical for large networks.
Configuration
# Configure the maximum size of the neighbor table
set system ipv6 neighbor table-size 8192
# Available values: 1024, 2048, 4096, 8192, 16384, 32768
commit
saveChoosing the Table Size
| Network size | Recommended table-size | Use case |
|---|---|---|
| < 100 hosts | 1024 (default) | Small offices |
| 100-500 hosts | 2048 | Medium offices |
| 500-2000 hosts | 4096 | Large offices, branches |
| 2000-5000 hosts | 8192 | Corporate networks |
| 5000-15000 hosts | 16384 | Data centers |
| > 15000 hosts | 32768 | ISPs, large data centers |
Verification
# Show the current IPv6 neighbors
show ipv6 neighbors
# Example output:
# IPv6 Address Interface Link-layer Address State Age
# fe80::250:56ff:fe12:3456 eth1 00:50:56:12:34:56 REACHABLE 15
# 2001:db8:1::100 eth1 00:50:56:12:34:57 STALE 120
# Count the number of entries
show ipv6 neighbors | grep -c REACHABLE
# Check the sysctl parameters
sysctl net.ipv6.neigh.default.gc_thresh1
sysctl net.ipv6.neigh.default.gc_thresh2
sysctl net.ipv6.neigh.default.gc_thresh3Neighbor Discovery States
- INCOMPLETE: The address is being resolved, an NS has been sent
- REACHABLE: The address is reachable, confirmed within ReachableTime
- STALE: The entry is outdated, confirmation is required upon use
- DELAY: Waiting for reachability confirmation
- PROBE: Active reachability check (Neighbor Unreachability Detection)
- FAILED: The neighbor is unreachable
Advanced Configuration via sysctl
# Configure garbage collection thresholds
sudo sysctl -w net.ipv6.neigh.default.gc_thresh1=1024
sudo sysctl -w net.ipv6.neigh.default.gc_thresh2=4096
sudo sysctl -w net.ipv6.neigh.default.gc_thresh3=8192
# gc_thresh1: Minimum number of entries before GC starts
# gc_thresh2: Soft limit (GC becomes more aggressive)
# gc_thresh3: Hard limit (new entries are not created)
# Persistent configuration
sudo tee /etc/sysctl.d/99-ipv6-neighbor.conf > /dev/null <<'EOF'
net.ipv6.neigh.default.gc_thresh1 = 1024
net.ipv6.neigh.default.gc_thresh2 = 4096
net.ipv6.neigh.default.gc_thresh3 = 8192
net.ipv6.neigh.default.gc_interval = 30
net.ipv6.neigh.default.gc_stale_time = 60
EOF
sudo sysctl -p /etc/sysctl.d/99-ipv6-neighbor.confNexthop Tracking
Description
Nexthop tracking (NHT) controls how dynamic routing protocols track the reachability of next-hop addresses. The no-resolve-via-default option forbids using the default route to resolve a next-hop.
Configuration
# Forbid resolving next-hops via the default route
set system ipv6 nht no-resolve-via-default
commit
saveHow Nexthop Tracking Works
Without no-resolve-via-default (default):
# BGP neighbor 2001:db8:100::1
# Routing table:
# ::/0 via 2001:db8:1::1
#
# BGP considers 2001:db8:100::1 reachable via the default route
# The BGP session is establishedWith no-resolve-via-default:
# BGP neighbor 2001:db8:100::1
# Routing table:
# ::/0 via 2001:db8:1::1
# NO specific route to 2001:db8:100::1
#
# BGP does NOT consider 2001:db8:100::1 reachable
# The BGP session is not establishedUse Cases
Recommended to enable:
- In BGP networks to prevent false-positive peer reachability
- When using IBGP with loopback addresses
- In OSPF/IS-IS to control next-hop resolution
Do not enable:
- If BGP peers are reachable only via the default route
- In simple configurations with a single upstream provider
Example with BGP
# BGP configuration with no-resolve-via-default
set system ipv6 nht no-resolve-via-default
# BGP peers must have specific routes
set protocols bgp local-as 65001
set protocols bgp neighbor 2001:db8:100::1 remote-as 65002
set protocols bgp neighbor 2001:db8:100::1 address-family ipv6-unicast
# Add a static route to the BGP peer
set protocols static route6 2001:db8:100::1/128 next-hop 2001:db8:1::1
commit
saveDisabling IPv6 on Interfaces
Global IPv6 Disable
# WARNING: Completely disables IPv6 on the entire system
set system ipv6 disable
commit
saveUse case: Used only if IPv6 is not going to be used at all. Reduces the attack surface and lowers overhead.
Verification
# Check whether IPv6 is disabled
show configuration system ipv6
# Check in the kernel
sysctl net.ipv6.conf.all.disable_ipv6
# Value: 1 (IPv6 disabled)
# Check the interfaces (there should be no IPv6 addresses)
show interfacesDisabling IPv6 on a Specific Interface
VyOS does not have a built-in command to disable IPv6 on a specific interface via the CLI. Use sysctl instead:
# Disable IPv6 on eth0
sudo sysctl -w net.ipv6.conf.eth0.disable_ipv6=1
# Persistent configuration
sudo tee /etc/sysctl.d/99-disable-ipv6-eth0.conf > /dev/null <<'EOF'
net.ipv6.conf.eth0.disable_ipv6 = 1
EOF
sudo sysctl -p /etc/sysctl.d/99-disable-ipv6-eth0.confUse Cases for Selective Disable
- Disable on WAN (if the provider does not offer IPv6)
- Disable on management interfaces (for security)
- Keep on LAN (for dual-stack clients)
Sysctl Parameters for IPv6
Critical Security Parameters
# Disable acceptance of Router Advertisements (for routers)
sudo sysctl -w net.ipv6.conf.all.accept_ra=0
sudo sysctl -w net.ipv6.conf.default.accept_ra=0
# Disable Router Advertisement forwarding
sudo sysctl -w net.ipv6.conf.all.forwarding=1
# Disable acceptance of redirects
sudo sysctl -w net.ipv6.conf.all.accept_redirects=0
sudo sysctl -w net.ipv6.conf.default.accept_redirects=0
# Disable source routing
sudo sysctl -w net.ipv6.conf.all.accept_source_route=0
sudo sysctl -w net.ipv6.conf.default.accept_source_route=0
# Persistent configuration
sudo tee /etc/sysctl.d/99-ipv6-security.conf > /dev/null <<'EOF'
# IPv6 Security Parameters
net.ipv6.conf.all.accept_ra = 0
net.ipv6.conf.default.accept_ra = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
net.ipv6.conf.all.forwarding = 1
EOF
sudo sysctl -p /etc/sysctl.d/99-ipv6-security.confPrivacy Extensions (RFC 4941)
# Enable privacy extensions for temporary addresses
# (usually on clients, not on routers)
sudo sysctl -w net.ipv6.conf.all.use_tempaddr=2
sudo sysctl -w net.ipv6.conf.default.use_tempaddr=2
# 0 = disabled
# 1 = enabled, but prefer public addresses
# 2 = enabled, prefer temporary addresses
# Configure the lifetime of temporary addresses
sudo sysctl -w net.ipv6.conf.all.temp_valid_lft=86400
sudo sysctl -w net.ipv6.conf.all.temp_prefered_lft=14400Duplicate Address Detection
# Number of NS messages for DAD (default 1)
sudo sysctl -w net.ipv6.conf.all.dad_transmits=1
sudo sysctl -w net.ipv6.conf.default.dad_transmits=1
# Optimistic DAD (use the address before DAD completes)
sudo sysctl -w net.ipv6.conf.all.optimistic_dad=0
sudo sysctl -w net.ipv6.conf.default.optimistic_dad=0Router Advertisement Parameters
# Maximum number of RAs to process
sudo sysctl -w net.ipv6.conf.all.max_addresses=16
# Lifetime of the default route from RA
sudo sysctl -w net.ipv6.route.max_size=4096
# Autoconf (SLAAC) parameters
sudo sysctl -w net.ipv6.conf.all.autoconf=1
sudo sysctl -w net.ipv6.conf.default.autoconf=1Performance Tuning for IPv6
sudo tee /etc/sysctl.d/99-ipv6-performance.conf > /dev/null <<'EOF'
# IPv6 Performance Parameters
# Neighbor Table Size
net.ipv6.neigh.default.gc_thresh1 = 1024
net.ipv6.neigh.default.gc_thresh2 = 4096
net.ipv6.neigh.default.gc_thresh3 = 8192
net.ipv6.neigh.default.gc_interval = 30
net.ipv6.neigh.default.gc_stale_time = 60
# Route Cache
net.ipv6.route.max_size = 16384
net.ipv6.route.gc_interval = 30
net.ipv6.route.gc_timeout = 60
net.ipv6.route.gc_min_interval = 5
# IPv6 Fragment Reassembly
net.ipv6.ip6frag_high_thresh = 4194304
net.ipv6.ip6frag_low_thresh = 3145728
net.ipv6.ip6frag_time = 60
# ICMPv6 Rate Limiting
net.ipv6.icmp.ratelimit = 1000
# Multipath Hashing
net.ipv6.fib_multipath_hash_policy = 1
EOF
sudo sysctl -p /etc/sysctl.d/99-ipv6-performance.confConfiguration Examples
1. Dual-Stack Router for Yandex Cloud
Objective: Configure VyOS in Yandex Cloud with dual-stack IPv4/IPv6.
# System IPv6 settings
set system ipv6 multipath layer4-hashing
set system ipv6 strict-dad
set system ipv6 neighbor table-size 4096
# WAN interface (eth0) - obtaining IPv6 from Yandex Cloud
set interfaces ethernet eth0 address dhcp
set interfaces ethernet eth0 address dhcpv6
set interfaces ethernet eth0 ipv6 address autoconf
# LAN interface (eth1) - distributing IPv4 and IPv6
set interfaces ethernet eth1 address 192.168.1.1/24
set interfaces ethernet eth1 address 2001:db8:1::1/64
# DHCPv4 server for LAN
set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 range 0 start 192.168.1.100
set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 range 0 stop 192.168.1.200
set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 option default-router 192.168.1.1
set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 option name-server 192.168.1.1
# Router Advertisement for IPv6 (SLAAC)
set service router-advert interface eth1 prefix 2001:db8:1::/64
set service router-advert interface eth1 name-server 2001:4860:4860::8888
set service router-advert interface eth1 name-server 2001:4860:4860::8844
# DHCPv6 server for additional options
set service dhcpv6-server shared-network-name LAN subnet 2001:db8:1::/64
set service dhcpv6-server shared-network-name LAN subnet 2001:db8:1::/64 name-server 2001:4860:4860::8888
set service dhcpv6-server shared-network-name LAN subnet 2001:db8:1::/64 name-server 2001:4860:4860::8844
# NAT for IPv4 (IPv6 works without NAT)
set nat source rule 100 outbound-interface eth0
set nat source rule 100 source address 192.168.1.0/24
set nat source rule 100 translation address masquerade
# Firewall for IPv6 (allow ICMPv6)
set firewall name WAN6_LOCAL default-action drop
set firewall name WAN6_LOCAL rule 10 action accept
set firewall name WAN6_LOCAL rule 10 state established
set firewall name WAN6_LOCAL rule 10 state related
set firewall name WAN6_LOCAL rule 10 description 'Allow established/related'
set firewall name WAN6_LOCAL rule 20 action accept
set firewall name WAN6_LOCAL rule 20 protocol ipv6-icmp
set firewall name WAN6_LOCAL rule 20 description 'Allow ICMPv6'
set firewall interface eth0 local name WAN6_LOCAL
commit
saveAdditional sysctl for Yandex Cloud:
sudo tee /etc/sysctl.d/99-yandex-cloud-ipv6.conf > /dev/null <<'EOF'
# Yandex Cloud IPv6 Settings
# Accept RA only on WAN
net.ipv6.conf.eth0.accept_ra = 2
net.ipv6.conf.eth0.autoconf = 1
net.ipv6.conf.eth1.accept_ra = 0
# Forwarding
net.ipv6.conf.all.forwarding = 1
# Security
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_source_route = 0
# Neighbor table for a small network
net.ipv6.neigh.default.gc_thresh1 = 512
net.ipv6.neigh.default.gc_thresh2 = 2048
net.ipv6.neigh.default.gc_thresh3 = 4096
EOF
sudo sysctl -p /etc/sysctl.d/99-yandex-cloud-ipv6.confVerifying the configuration:
# Check IPv6 addresses
show interfaces
# Check IPv6 connectivity
ping6 2001:4860:4860::8888
# Check Router Advertisement
show ipv6 route
# You should see:
# - Link-local addresses on all interfaces (fe80::...)
# - A global unicast address on eth0 from Yandex Cloud
# - The configured address on eth1 (2001:db8:1::1/64)
# Check neighbor discovery
show ipv6 neighbors2. IPv6-only Network for VK Cloud
Objective: Configure VyOS in VK Cloud for an IPv6-only infrastructure.
# System IPv6 settings
set system ipv6 multipath layer4-hashing
set system ipv6 strict-dad
set system ipv6 neighbor table-size 8192
set system ipv6 nht no-resolve-via-default
# WAN interface - IPv6 only
set interfaces ethernet eth0 address dhcpv6
set interfaces ethernet eth0 ipv6 address autoconf
set interfaces ethernet eth0 description 'WAN VK Cloud IPv6'
# LAN interface - IPv6 only
set interfaces ethernet eth1 address 2001:db8:100::1/64
set interfaces ethernet eth1 description 'LAN IPv6-only'
# Router Advertisement for clients
set service router-advert interface eth1 prefix 2001:db8:100::/64
set service router-advert interface eth1 prefix 2001:db8:100::/64 preferred-lifetime 14400
set service router-advert interface eth1 prefix 2001:db8:100::/64 valid-lifetime 86400
set service router-advert interface eth1 name-server 2001:4860:4860::8888
set service router-advert interface eth1 name-server 2001:4860:4860::8844
set service router-advert interface eth1 other-config-flag
# DHCPv6 server (stateful, to manage addressing)
set service dhcpv6-server shared-network-name LAN subnet 2001:db8:100::/64
set service dhcpv6-server shared-network-name LAN subnet 2001:db8:100::/64 range 0 start 2001:db8:100::1000
set service dhcpv6-server shared-network-name LAN subnet 2001:db8:100::/64 range 0 stop 2001:db8:100::1fff
set service dhcpv6-server shared-network-name LAN subnet 2001:db8:100::/64 name-server 2001:4860:4860::8888
set service dhcpv6-server shared-network-name LAN subnet 2001:db8:100::/64 name-server 2001:4860:4860::8844
# Firewall for IPv6
set firewall name WAN6_IN default-action drop
set firewall name WAN6_IN rule 10 action accept
set firewall name WAN6_IN rule 10 state established
set firewall name WAN6_IN rule 10 state related
set firewall name WAN6_IN rule 20 action drop
set firewall name WAN6_IN rule 20 state invalid
set firewall name WAN6_IN rule 30 action accept
set firewall name WAN6_IN rule 30 protocol ipv6-icmp
set firewall name WAN6_LOCAL default-action drop
set firewall name WAN6_LOCAL rule 10 action accept
set firewall name WAN6_LOCAL rule 10 state established
set firewall name WAN6_LOCAL rule 10 state related
set firewall name WAN6_LOCAL rule 20 action accept
set firewall name WAN6_LOCAL rule 20 protocol ipv6-icmp
set firewall name WAN6_LOCAL rule 30 action accept
set firewall name WAN6_LOCAL rule 30 source address fe80::/10
set firewall name WAN6_LOCAL rule 30 description 'Allow link-local'
set firewall interface eth0 in name WAN6_IN
set firewall interface eth0 local name WAN6_LOCAL
# Disable IPv4 (optional, if truly IPv6-only)
# set system ip disable-forwarding
commit
saveIPv6-only-specific settings:
sudo tee /etc/sysctl.d/99-vk-cloud-ipv6-only.conf > /dev/null <<'EOF'
# VK Cloud IPv6-only Configuration
# IPv6 Forwarding
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.default.forwarding = 1
# Accept RA only on WAN (to obtain the default route)
net.ipv6.conf.eth0.accept_ra = 2
net.ipv6.conf.eth0.autoconf = 1
net.ipv6.conf.eth1.accept_ra = 0
net.ipv6.conf.eth1.autoconf = 0
# Router Advertisement (the router must send RAs)
net.ipv6.conf.eth1.forwarding = 1
# Increase the neighbor table for a large IPv6 network
net.ipv6.neigh.default.gc_thresh1 = 2048
net.ipv6.neigh.default.gc_thresh2 = 4096
net.ipv6.neigh.default.gc_thresh3 = 8192
# Multipath hashing
net.ipv6.fib_multipath_hash_policy = 1
# Security
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
# Disable IPv4 (optional)
# net.ipv4.conf.all.forwarding = 0
EOF
sudo sysctl -p /etc/sysctl.d/99-vk-cloud-ipv6-only.confVerifying the IPv6-only configuration:
# Check that IPv6 is obtained from VK Cloud
show interfaces ethernet eth0
# You should see:
# - A link-local address (fe80::...)
# - A global unicast address from DHCPv6/SLAAC
# Check IPv6 routing
show ipv6 route
# You should see:
# - ::/0 default route via eth0
# - 2001:db8:100::/64 connected via eth1
# Connectivity test
ping6 2001:4860:4860::8888
# Check the DHCPv6 server
show dhcpv6 server leases
# Check Router Advertisement
show ipv6 route | grep RA3. BGP IPv6 Multihoming with ECMP
Objective: Configure a dual-uplink setup with BGP IPv6 and ECMP balancing.
# System IPv6 settings
set system ipv6 multipath layer4-hashing
set system ipv6 strict-dad
set system ipv6 neighbor table-size 16384
set system ipv6 nht no-resolve-via-default
# Uplink 1 - ISP A
set interfaces ethernet eth0 address 2001:db8:a::2/64
set interfaces ethernet eth0 description 'ISP-A Uplink'
# Uplink 2 - ISP B
set interfaces ethernet eth1 address 2001:db8:b::2/64
set interfaces ethernet eth1 description 'ISP-B Uplink'
# LAN
set interfaces ethernet eth2 address 2001:db8:100::1/64
set interfaces ethernet eth2 description 'LAN'
# BGP Configuration
set protocols bgp local-as 65001
set protocols bgp parameters router-id 10.0.0.1
# BGP neighbor ISP-A
set protocols bgp neighbor 2001:db8:a::1 remote-as 65100
set protocols bgp neighbor 2001:db8:a::1 address-family ipv6-unicast
set protocols bgp neighbor 2001:db8:a::1 description 'ISP-A'
# BGP neighbor ISP-B
set protocols bgp neighbor 2001:db8:b::1 remote-as 65200
set protocols bgp neighbor 2001:db8:b::1 address-family ipv6-unicast
set protocols bgp neighbor 2001:db8:b::1 description 'ISP-B'
# Announce LAN prefix
set protocols bgp address-family ipv6-unicast network 2001:db8:100::/48
# Maximum paths for ECMP
set protocols bgp address-family ipv6-unicast maximum-paths 2
# Router Advertisement on LAN
set service router-advert interface eth2 prefix 2001:db8:100::/64
commit
saveConfiguring ECMP via sysctl:
sudo tee /etc/sysctl.d/99-bgp-ipv6-ecmp.conf > /dev/null <<'EOF'
# BGP IPv6 ECMP Configuration
# Layer 4 hashing for per-flow balancing
net.ipv6.fib_multipath_hash_policy = 1
# Increase the neighbor table for a BGP full table
net.ipv6.neigh.default.gc_thresh1 = 4096
net.ipv6.neigh.default.gc_thresh2 = 8192
net.ipv6.neigh.default.gc_thresh3 = 16384
# Route table size for BGP
net.ipv6.route.max_size = 32768
# Forwarding
net.ipv6.conf.all.forwarding = 1
# BGP specific: do not accept RA on uplinks
net.ipv6.conf.eth0.accept_ra = 0
net.ipv6.conf.eth1.accept_ra = 0
net.ipv6.conf.eth2.accept_ra = 0
EOF
sudo sysctl -p /etc/sysctl.d/99-bgp-ipv6-ecmp.confVerifying ECMP:
# Check BGP sessions
show bgp ipv6 summary
# Check BGP routes with ECMP
show bgp ipv6
# Check the installed routes
show ipv6 route
# For a prefix with ECMP you should see multiple next-hops:
# B>* ::/0 [20/0] via 2001:db8:a::1, eth0, weight 1, 00:10:23
# via 2001:db8:b::1, eth1, weight 1, 00:10:23
# Test balancing
# From a LAN client, open several connections and check the distribution4. Data Center with IPv6 and High Load
Objective: Optimize VyOS for a Data Center with IPv6 traffic > 1 Gbps.
# System IPv6 settings
set system ipv6 multipath layer4-hashing
set system ipv6 strict-dad
set system ipv6 neighbor table-size 32768
set system ipv6 nht no-resolve-via-default
commit
savePerformance tuning for the Data Center:
sudo tee /etc/sysctl.d/99-datacenter-ipv6-performance.conf > /dev/null <<'EOF'
# Data Center IPv6 Performance Tuning
# Forwarding
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.default.forwarding = 1
# Neighbor Table for a large network (10K+ servers)
net.ipv6.neigh.default.gc_thresh1 = 8192
net.ipv6.neigh.default.gc_thresh2 = 16384
net.ipv6.neigh.default.gc_thresh3 = 32768
net.ipv6.neigh.default.gc_interval = 30
net.ipv6.neigh.default.gc_stale_time = 60
net.ipv6.neigh.default.base_reachable_time_ms = 30000
# Route Table for BGP/OSPF
net.ipv6.route.max_size = 65536
net.ipv6.route.gc_interval = 30
net.ipv6.route.gc_timeout = 60
net.ipv6.route.gc_min_interval = 5
# Multipath ECMP with Layer 4 hashing
net.ipv6.fib_multipath_hash_policy = 1
# Fragment Reassembly for Jumbo Frames
net.ipv6.ip6frag_high_thresh = 8388608
net.ipv6.ip6frag_low_thresh = 6291456
net.ipv6.ip6frag_time = 60
# ICMPv6 Rate Limiting (protection against floods)
net.ipv6.icmp.ratelimit = 1000
# Disable RA on all interfaces (data center internal)
net.ipv6.conf.all.accept_ra = 0
net.ipv6.conf.default.accept_ra = 0
net.ipv6.conf.all.autoconf = 0
net.ipv6.conf.default.autoconf = 0
# Security
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
# TCP Performance for IPv6
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 67108864
net.ipv4.tcp_wmem = 4096 65536 67108864
# Congestion Control
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
# Netfilter Conntrack
net.netfilter.nf_conntrack_max = 1048576
EOF
sudo sysctl -p /etc/sysctl.d/99-datacenter-ipv6-performance.confConntrack hashsize for high load:
# Set hashsize = conntrack_max / 8
echo 131072 | sudo tee /sys/module/nf_conntrack/parameters/hashsize
# Make it persistent (add to rc.local or a systemd service)
sudo tee /etc/systemd/system/conntrack-hashsize.service > /dev/null <<'EOF'
[Unit]
Description=Set nf_conntrack hashsize
After=network.target
[Service]
Type=oneshot
ExecStart=/bin/bash -c 'echo 131072 > /sys/module/nf_conntrack/parameters/hashsize'
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable conntrack-hashsize
sudo systemctl start conntrack-hashsize5. IPv6 Security Hardening
Objective: Configure IPv6 with maximum security for an edge router.
# System IPv6 settings
set system ipv6 multipath layer4-hashing
set system ipv6 strict-dad
set system ipv6 neighbor table-size 4096
# Firewall for IPv6
set firewall name WAN6_IN default-action drop
set firewall name WAN6_IN enable-default-log
# Allow established/related
set firewall name WAN6_IN rule 10 action accept
set firewall name WAN6_IN rule 10 state established
set firewall name WAN6_IN rule 10 state related
set firewall name WAN6_IN rule 10 description 'Allow established/related'
# Drop invalid
set firewall name WAN6_IN rule 20 action drop
set firewall name WAN6_IN rule 20 state invalid
set firewall name WAN6_IN rule 20 log
set firewall name WAN6_IN rule 20 description 'Drop invalid'
# Allow the necessary ICMPv6 (only critical types)
set firewall name WAN6_IN rule 30 action accept
set firewall name WAN6_IN rule 30 protocol ipv6-icmp
set firewall name WAN6_IN rule 30 icmpv6 type 1
set firewall name WAN6_IN rule 30 description 'Allow ICMPv6 Destination Unreachable'
set firewall name WAN6_IN rule 31 action accept
set firewall name WAN6_IN rule 31 protocol ipv6-icmp
set firewall name WAN6_IN rule 31 icmpv6 type 2
set firewall name WAN6_IN rule 31 description 'Allow ICMPv6 Packet Too Big'
set firewall name WAN6_IN rule 32 action accept
set firewall name WAN6_IN rule 32 protocol ipv6-icmp
set firewall name WAN6_IN rule 32 icmpv6 type 3
set firewall name WAN6_IN rule 32 description 'Allow ICMPv6 Time Exceeded'
set firewall name WAN6_IN rule 33 action accept
set firewall name WAN6_IN rule 33 protocol ipv6-icmp
set firewall name WAN6_IN rule 33 icmpv6 type 4
set firewall name WAN6_IN rule 33 description 'Allow ICMPv6 Parameter Problem'
set firewall name WAN6_IN rule 34 action accept
set firewall name WAN6_IN rule 34 protocol ipv6-icmp
set firewall name WAN6_IN rule 34 icmpv6 type 128
set firewall name WAN6_IN rule 34 description 'Allow ICMPv6 Echo Request (ping6)'
# Block Router Advertisement from WAN (protection against rogue RA)
set firewall name WAN6_IN rule 40 action drop
set firewall name WAN6_IN rule 40 protocol ipv6-icmp
set firewall name WAN6_IN rule 40 icmpv6 type 134
set firewall name WAN6_IN rule 40 log
set firewall name WAN6_IN rule 40 description 'Block rogue Router Advertisement'
# Firewall LOCAL
set firewall name WAN6_LOCAL default-action drop
set firewall name WAN6_LOCAL enable-default-log
set firewall name WAN6_LOCAL rule 10 action accept
set firewall name WAN6_LOCAL rule 10 state established
set firewall name WAN6_LOCAL rule 10 state related
set firewall name WAN6_LOCAL rule 20 action drop
set firewall name WAN6_LOCAL rule 20 state invalid
set firewall name WAN6_LOCAL rule 20 log
# Allow link-local (for Neighbor Discovery)
set firewall name WAN6_LOCAL rule 30 action accept
set firewall name WAN6_LOCAL rule 30 source address fe80::/10
set firewall name WAN6_LOCAL rule 30 description 'Allow link-local'
# Allow the necessary ICMPv6
set firewall name WAN6_LOCAL rule 40 action accept
set firewall name WAN6_LOCAL rule 40 protocol ipv6-icmp
set firewall name WAN6_LOCAL rule 40 icmpv6 type 1
set firewall name WAN6_LOCAL rule 40 description 'Allow ICMPv6 types'
# Allow the DHCPv6 client (if used)
set firewall name WAN6_LOCAL rule 50 action accept
set firewall name WAN6_LOCAL rule 50 protocol udp
set firewall name WAN6_LOCAL rule 50 source port 547
set firewall name WAN6_LOCAL rule 50 destination port 546
set firewall name WAN6_LOCAL rule 50 description 'Allow DHCPv6 client'
# Apply the firewall
set firewall interface eth0 in name WAN6_IN
set firewall interface eth0 local name WAN6_LOCAL
commit
saveSecurity sysctl for IPv6:
sudo tee /etc/sysctl.d/99-ipv6-security-hardening.conf > /dev/null <<'EOF'
# IPv6 Security Hardening
# Forwarding (for a router)
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.default.forwarding = 1
# Disable Router Advertisement acceptance (protection against rogue RA)
net.ipv6.conf.all.accept_ra = 0
net.ipv6.conf.default.accept_ra = 0
net.ipv6.conf.all.accept_ra_defrtr = 0
net.ipv6.conf.default.accept_ra_defrtr = 0
net.ipv6.conf.all.accept_ra_pinfo = 0
net.ipv6.conf.default.accept_ra_pinfo = 0
# Disable autoconf (SLAAC)
net.ipv6.conf.all.autoconf = 0
net.ipv6.conf.default.autoconf = 0
# Disable redirects
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
# Disable source routing
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
# Log martians
net.ipv6.conf.all.log_martians = 1
net.ipv6.conf.default.log_martians = 1
# Maximum addresses per interface (protection against RA flood)
net.ipv6.conf.all.max_addresses = 16
net.ipv6.conf.default.max_addresses = 16
# Disable privacy extensions on the router
net.ipv6.conf.all.use_tempaddr = 0
net.ipv6.conf.default.use_tempaddr = 0
# DAD for all addresses
net.ipv6.conf.all.dad_transmits = 1
net.ipv6.conf.default.dad_transmits = 1
# ICMPv6 rate limiting (protection against ICMPv6 flood)
net.ipv6.icmp.ratelimit = 1000
EOF
sudo sysctl -p /etc/sysctl.d/99-ipv6-security-hardening.confMonitoring and Diagnostics
Operational Commands
# Show the system IPv6 configuration
show system ipv6
# Show all IPv6 addresses on the interfaces
show interfaces
# IPv6 Neighbor Table (the equivalent of ARP)
show ipv6 neighbors
# Example output:
# IPv6 Address Interface Link-layer Address State Age
# fe80::250:56ff:fe12:3456 eth1 00:50:56:12:34:56 REACHABLE 15
# 2001:db8:1::100 eth1 00:50:56:12:34:57 STALE 120
# IPv6 Routing Table
show ipv6 route
# IPv6 BGP (if used)
show bgp ipv6 summary
show bgp ipv6
# Router Advertisement information
show ipv6 route | grep RA
# ICMPv6 statistics
show ipv6 statistics
# Flush the neighbor cache
reset ipv6 neighbors
# Flush the route cache
reset ipv6 route cacheChecking Neighbor Discovery
# Real-time NDP monitoring
sudo tcpdump -i eth1 -nn icmp6
# Filter for specific ICMPv6 types:
# Type 133: Router Solicitation
# Type 134: Router Advertisement
# Type 135: Neighbor Solicitation
# Type 136: Neighbor Advertisement
# Type 137: Redirect
# Only Neighbor Solicitation/Advertisement
sudo tcpdump -i eth1 -nn 'icmp6 and (ip6[40] == 135 or ip6[40] == 136)'
# Only Router Advertisement
sudo tcpdump -i eth1 -nn 'icmp6 and ip6[40] == 134'Sysctl Monitoring
# All IPv6 parameters
sysctl -a | grep net.ipv6
# Check forwarding
sysctl net.ipv6.conf.all.forwarding
# Check multipath hashing
sysctl net.ipv6.fib_multipath_hash_policy
# 0 = layer3 (src/dst IP only)
# 1 = layer4 (src/dst IP + ports)
# Neighbor table statistics
sysctl net.ipv6.neigh.default.gc_thresh1
sysctl net.ipv6.neigh.default.gc_thresh2
sysctl net.ipv6.neigh.default.gc_thresh3
# Check the current number of neighbors
ip -6 neigh show | wc -l
# Route table size
sysctl net.ipv6.route.max_size
ip -6 route show | wc -lPerformance Monitoring
# IPv6 statistics
cat /proc/net/snmp6
# Key metrics:
# Ip6InReceives - incoming packets
# Ip6OutRequests - outgoing packets
# Ip6InDiscards - drops on ingress
# Ip6OutDiscards - drops on egress
# Icmp6InMsgs - incoming ICMPv6 messages
# Icmp6OutMsgs - outgoing ICMPv6 messages
# IPv6 routing statistics
cat /proc/net/ipv6_route
# Neighbor table statistics
cat /proc/net/ndisc_cache
# ICMPv6 statistics detail
netstat -s -6 | grep -i icmpTroubleshooting Problems
# Check IPv6 connectivity
ping6 -c 3 2001:4860:4860::8888
# Traceroute for IPv6
traceroute6 2001:4860:4860::8888
# MTU Path Discovery
ping6 -M do -s 1400 2001:4860:4860::8888
# Check IPv6 DNS resolution
host -t AAAA google.com
dig google.com AAAA
# Check the DHCPv6 client
show dhcpv6 client leases
# Logs for IPv6 problems
show log | match -i ipv6
show log | match -i icmp6
show log | match -i neighborTroubleshooting
1. IPv6 Forwarding Does Not Work
Symptoms: Clients cannot access the IPv6 Internet through VyOS.
Check:
# Check IPv6 forwarding
sysctl net.ipv6.conf.all.forwarding
# Should be: net.ipv6.conf.all.forwarding = 1
# Check the VyOS configuration
show configuration system ipv6
# Should not contain: disable-forwardingSolution:
# Remove disable-forwarding if present
delete system ipv6 disable-forwarding
commit
save
# Check in the kernel
sudo sysctl -w net.ipv6.conf.all.forwarding=1
# Check the firewall (it may block IPv6 forwarding)
show firewall2. Duplicate Address Detection (DAD) Failures
Symptoms: The interface does not obtain an IPv6 address; the logs show “duplicate address detected”.
Check:
# Check the state of the addresses
ip -6 addr show
# If an address is marked as "dadfailed":
# inet6 2001:db8:1::1/64 scope global tentative dadfailed
# Check the logs
show log | match "duplicate"
dmesg | grep -i "duplicate address"
# Check the neighbor table for the conflicting address
show ipv6 neighbors | grep 2001:db8:1::1Solution:
# Option 1: Change the address to a unique one
delete interfaces ethernet eth1 address 2001:db8:1::1/64
set interfaces ethernet eth1 address 2001:db8:1::2/64
commit
save
# Option 2: Find and fix the device with the duplicate address
# Use tcpdump to search
sudo tcpdump -i eth1 -nn 'icmp6 and ip6[40] == 136'
# The Neighbor Advertisement will reveal the MAC address of the conflicting device
# Option 3: Temporarily disable strict-dad to recover
delete system ipv6 strict-dad
commit
# After fixing the conflict - re-enable it
set system ipv6 strict-dad
commit
save3. Neighbor Table Overflow
Symptoms: “Neighbor table overflow” in the logs, inability to discover new IPv6 hosts.
Check:
# Current number of neighbors
ip -6 neigh show | wc -l
# Check the thresholds
sysctl net.ipv6.neigh.default.gc_thresh1
sysctl net.ipv6.neigh.default.gc_thresh2
sysctl net.ipv6.neigh.default.gc_thresh3
# If the number of neighbors is close to gc_thresh3 - there is a problemSolution:
# Increase the neighbor table size via VyOS
set system ipv6 neighbor table-size 16384
commit
save
# Temporarily increase via sysctl
sudo sysctl -w net.ipv6.neigh.default.gc_thresh1=4096
sudo sysctl -w net.ipv6.neigh.default.gc_thresh2=8192
sudo sysctl -w net.ipv6.neigh.default.gc_thresh3=16384
# Persistent configuration
sudo tee /etc/sysctl.d/99-ipv6-neighbor-fix.conf > /dev/null <<'EOF'
net.ipv6.neigh.default.gc_thresh1 = 4096
net.ipv6.neigh.default.gc_thresh2 = 8192
net.ipv6.neigh.default.gc_thresh3 = 16384
EOF
sudo sysctl -p /etc/sysctl.d/99-ipv6-neighbor-fix.conf
# Flush STALE entries
sudo ip -6 neigh flush dev eth1 nud stale4. ECMP Does Not Balance Traffic Evenly
Symptoms: All IPv6 traffic goes over a single path despite ECMP being present.
Check:
# Check for multipath routes
show ipv6 route
# You should see multiple next-hops
# Example:
# S> 2001:db8:100::/48 [1/0] via 2001:db8:1::1, eth0
# via 2001:db8:1::2, eth1
# Check the multipath hash policy
sysctl net.ipv6.fib_multipath_hash_policy
# 0 = layer3 (bad for balancing)
# 1 = layer4 (good)
# Check the VyOS configuration
show configuration system ipv6 | grep multipathSolution:
# Enable layer4-hashing
set system ipv6 multipath layer4-hashing
commit
save
# Verify that it was applied
sysctl net.ipv6.fib_multipath_hash_policy
# Should be: 1
# If it still does not work - check the route weights
# BGP: verify that the paths have the same weight
show bgp ipv6 <prefix>
# Static routes: check the distance
show ipv6 route static5. Rogue Router Advertisement
Symptoms: Clients receive incorrect default routes; the network is unstable.
Check:
# Monitor RAs on the network
sudo tcpdump -i eth1 -nn 'icmp6 and ip6[40] == 134' -v
# Check where the RAs come from
# The output will show the source MAC and link-local address
# Check the client routes
# On the client:
ip -6 route show | grep default
# There should be only one default route from the legitimate routerSolution:
# Option 1: Block RAs on the firewall
set firewall name LAN_IN rule 10 action drop
set firewall name LAN_IN rule 10 protocol ipv6-icmp
set firewall name LAN_IN rule 10 icmpv6 type 134
set firewall name LAN_IN rule 10 description 'Block rogue RA from LAN'
set firewall interface eth1 in name LAN_IN
commit
save
# Option 2: Use RA Guard (requires switch support)
# Configure RA Guard on a managed switch to block RAs from client ports
# Option 3: Locate the source of the rogue RA
# Use the tcpdump output to determine the MAC address
# Disable the port on the switch or the device
# Option 4: Enable RA Guard via ebtables (Linux bridge)
# If VyOS acts as a bridge:
sudo ebtables -A FORWARD -p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type router-advertisement -j DROP6. ICMPv6 “Packet Too Big” Is Ignored (PMTUD failure)
Symptoms: Large packets are not delivered; connections hang after the handshake.
Check:
# Test with a large packet
ping6 -M do -s 1400 2001:4860:4860::8888
# If it times out - PMTUD is not working
# Check the firewall
show firewall
# ICMPv6 type 2 (Packet Too Big) must be allowedSolution:
# Allow ICMPv6 Type 2 (Packet Too Big) in the firewall
set firewall name WAN6_IN rule 100 action accept
set firewall name WAN6_IN rule 100 protocol ipv6-icmp
set firewall name WAN6_IN rule 100 icmpv6 type 2
set firewall name WAN6_IN rule 100 description 'Allow Packet Too Big for PMTUD'
set firewall name WAN6_LOCAL rule 100 action accept
set firewall name WAN6_LOCAL rule 100 protocol ipv6-icmp
set firewall name WAN6_LOCAL rule 100 icmpv6 type 2
commit
save
# Alternative: MSS clamping for TCP
# set firewall modify MSS_CLAMP rule 10 action modify
# set firewall modify MSS_CLAMP rule 10 protocol tcp
# set firewall modify MSS_CLAMP rule 10 tcp flags syn
# set firewall modify MSS_CLAMP rule 10 set tcp-mss 1380Best Practices
1. IPv6 Forwarding
- Keep it enabled on all routers (default)
- Disable it only on pure endpoint systems
- Verify it after every VyOS upgrade
2. Strict DAD
- Enable it in production environments to prevent conflicts
- Mandatory in cloud environments (Yandex Cloud, VK Cloud)
- Monitor the logs for DAD failures
3. Multipath Layer4 Hashing
- Always enable it when using ECMP
- Provides per-flow balancing
- Prevents TCP packet reordering
4. Neighbor Table Size
- Choose the size based on the number of hosts on the network
- For routers running BGP: increase it to 16384-32768
- Monitor the fill level of the neighbor cache
5. Nexthop Tracking
- Enable
no-resolve-via-defaultin BGP networks - Prevents false-positive peer reachability
- Critical for IBGP with loopback addresses
6. Security
- Block rogue Router Advertisements on the LAN
- Allow only the necessary ICMPv6 types
- Disable RA acceptance on routers (accept_ra=0)
- Disable source routing and redirects
7. Router Advertisement
- Use the managed-flag for DHCPv6 addressing
- Configure reasonable lifetime values
- Do not send RAs on WAN interfaces
8. Performance
- Increase the neighbor/route table for large networks
- Tune TCP parameters for WAN > 100 Mbps
- Use BBR congestion control
- Optimize GC intervals for the neighbor table
9. Monitoring
- Monitor neighbor table usage
- Track DAD failures
- Verify ECMP balancing
- Log rogue RA attempts
10. Documentation
- Document all sysctl changes
- Store configuration in /etc/sysctl.d/
- Use descriptive file names (99-ipv6-*.conf)
- Test changes in staging before production
Conclusion
Proper configuration of system IPv6 parameters in VyOS ensures a stable, high-performance and secure IPv6 network. Tuning forwarding, strict DAD, multipath hashing, the neighbor table and other parameters lets you optimize the router for specific requirements - from a simple dual-stack gateway for a small office to a high-performance IPv6 router for a Data Center or ISP network.
Key takeaways:
- Forwarding must be enabled on routers (default in VyOS)
- Strict DAD prevents address conflicts in automated environments
- Layer 4 hashing is critical for ECMP to work correctly
- Neighbor table size must match the size of the network
- Security hardening through sysctl and the firewall protects against attacks
- Monitoring lets you catch problems before they affect production
Following best practices and monitoring regularly ensure reliable operation of IPv6 infrastructure in modern cloud and enterprise networks.