Comprehensive Guide: Setting Up Dual-Stack IPv4/IPv6 OpenVPN with TAP Device Routing


2 views

Your existing setup shows a properly configured IPv4 OpenVPN tunnel using TAP devices, but IPv6 connectivity faces routing challenges. The key components are:

Server Configuration:
- Physical interface: eth0 (2001:db8::1:2:3:4/64)
- VPN interface: tap0 (2001:db8::100:abc:1/112)
- Default gateway: 2001:db8::1

Client Configuration:
- VPN interface: tap0 (2001:db8::100:abc:2/112)
- Gateway: 2001:db8::100:abc:1

The core issue lies in proper neighbor discovery and routing advertisement. Here's how to fix it:

# On the server (Debian):
sysctl -w net.ipv6.conf.all.forwarding=1
sysctl -w net.ipv6.conf.all.proxy_ndp=1
sysctl -w net.ipv6.conf.all.accept_ra=2

# Add static NDP proxy entry for client
ip -6 neigh add proxy 2001:db8::100:abc:2 dev eth0

Your server.conf needs these IPv6-specific directives:

server-ipv6 2001:db8::100:abc:0/112
push "route-ipv6 2001:db8::100:0:0/96"
push "route-ipv6 2000::/3"
tun-ipv6
dev tap0

The client.ovpn should include:

client
dev tap0
proto udp
remote your.server.ip 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
tun-ipv6
route-ipv6 2000::/3

When testing connectivity, use these diagnostic commands:

# On client:
ping6 2001:db8::100:abc:1
traceroute6 ipv6.google.com

# On server:
tcpdump -i eth0 icmp6 and host 2001:db8::100:abc:2
ip -6 route show

Essential firewall rules for IPv6 (using ip6tables):

ip6tables -A FORWARD -i tap0 -j ACCEPT
ip6tables -A FORWARD -o tap0 -j ACCEPT
ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
ip6tables -A INPUT -i tap0 -j ACCEPT

For Debian servers, add to /etc/network/interfaces:

iface tap0 inet6 static
    address 2001:db8::100:abc:1
    netmask 112
    post-up ip -6 neigh add proxy 2001:db8::100:abc:2 dev eth0

Let's examine the network configuration where we have:

Server (VPS):
- eth0: 2001:db8::1:2:3:4/64 (public IPv6)
- tap0: 2001:db8::100:abc:1/112 (VPN gateway)
- Default gateway: 2001:db8::1

Client (Home laptop):
- tap0: 2001:db8::100:abc:2/112
- VPN gateway: 2001:db8::100:abc:1

Server configuration (server.conf):

dev tap0
proto udp
server-ipv6 2001:db8::100:abc:0/112
push "route-ipv6 2000::/3"
push "redirect-gateway ipv6"
keepalive 10 120
comp-lzo
persist-key
persist-tun
user nobody
group nogroup

Client configuration (client.conf):

client
dev tap0
proto udp
remote your-server-ip 1194
resolv-retry infinite
nobind
persist-key
persist-tun
comp-lzo
verb 3

The core issue lies in the server not responding to Neighbor Discovery Protocol (NDP) requests:

# Enable proxy NDP on the server
sysctl -w net.ipv6.conf.all.proxy_ndp=1
ip -6 neigh add proxy 2001:db8::100:abc:2 dev eth0

Essential server-side routing setup:

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

# Disable RA acceptance on VPN interface
sysctl -w net.ipv6.conf.tap0.accept_ra=0

# Firewall rules (example for UFW)
ufw allow in on tap0
ufw route allow in on tap0 out on eth0

After implementation, verify with:

# From client
ping6 -c4 ipv6.google.com
traceroute6 ipv6.google.com

# Debugging commands
tcpdump -i tap0 -n ip6
tcpdump -i eth0 -n icmp6

If connectivity fails, check:

# Verify NDP entries
ip -6 neigh show

# Check routing tables
ip -6 route show

# Test MTU issues
ping6 -M do -s 1472 ipv6.google.com

For persistent proxy NDP entries, create a systemd service:

[Unit]
Description=Add IPv6 proxy NDP entry
After=network.target

[Service]
Type=oneshot
ExecStart=/sbin/ip -6 neigh add proxy 2001:db8::100:abc:2 dev eth0

[Install]
WantedBy=multi-user.target