Based on your ifconfig output, you have:
- eth0 with global IPv6 address 2607:f740:0:3f::eda/64
- tun0 with global IPv6 address 2607:f740:44:22::8/64
- IPv6 forwarding already enabled (net.ipv6.conf.all.forwarding = 1)
The main issue appears to be with your ip6tables rules and routing configuration. While you've set up basic forwarding rules, there are several critical elements missing:
# Missing NAT rule for outgoing traffic
ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# Missing reverse path forwarding
ip6tables -A FORWARD -i eth0 -o tun0 -m state --state RELATED,ESTABLISHED -j ACCEPT
Here's a complete working configuration for your scenario:
# Enable IPv6 forwarding
sysctl -w net.ipv6.conf.all.forwarding=1
# Flush existing rules
ip6tables -F
ip6tables -t nat -F
# Set default policies
ip6tables -P INPUT ACCEPT
ip6tables -P FORWARD ACCEPT
ip6tables -P OUTPUT ACCEPT
# Allow ICMPv6 (essential for IPv6 operation)
ip6tables -A INPUT -p icmpv6 -j ACCEPT
# Forwarding rules
ip6tables -A FORWARD -i tun0 -o eth0 -s 2607:f740:44:22::/64 -j ACCEPT
ip6tables -A FORWARD -i eth0 -o tun0 -m state --state RELATED,ESTABLISHED -j ACCEPT
# NAT for outgoing traffic
ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# Additional recommended settings
sysctl -w net.ipv6.conf.all.proxy_ndp=1
sysctl -w net.ipv6.conf.all.accept_ra=0
sysctl -w net.ipv6.conf.all.autoconf=0
To confirm your setup is working:
- Check packet counters on your rules:
ip6tables -L FORWARD -v
- Test connectivity from a client in tun0 network:
ping6 ipv6.google.com
- Verify route advertisements if using SLAAC:
tcpdump -i eth0 icmp6
- Ensure your IPv6 default route is correct:
ip -6 route show
- Check for conflicting firewall rules:
ip6tables-save
- Verify MTU settings match on both interfaces (1500 in your case)
For more complex scenarios, consider adding:
# Rate limiting for security
ip6tables -A FORWARD -p tcp --syn -m limit --limit 1/s -j ACCEPT
# Log dropped packets for debugging
ip6tables -N LOGGING
ip6tables -A INPUT -j LOGGING
ip6tables -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPv6 DROP: " --log-level 4
ip6tables -A LOGGING -j DROP
From your setup, I can see you have:
- eth0 with global IPv6 address 2607:f740:0:3f::eda/64
- tun0 with global IPv6 address 2607:f740:44:22::8/64
- IPv6 forwarding enabled at the kernel level
- Basic ip6tables rules configured
- Proper route entries for both interfaces
While you've done most things correctly, IPv6 forwarding requires some additional considerations compared to IPv4:
# First, ensure these sysctl settings are properly configured
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
echo 1 > /proc/sys/net/ipv6/conf/default/forwarding
echo 1 > /proc/sys/net/ipv6/conf/eth0/forwarding
echo 1 > /proc/sys/net/ipv6/conf/tun0/forwarding
Your current ip6tables rules need some enhancements for proper forwarding:
# Flush existing rules
ip6tables -F
ip6tables -X
ip6tables -Z
# Default policies
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT
# Allow loopback
ip6tables -A INPUT -i lo -j ACCEPT
# Allow ICMPv6 (essential for IPv6 operation)
ip6tables -A INPUT -p ipv6-icmp -j ACCEPT
ip6tables -A FORWARD -p ipv6-icmp -j ACCEPT
# Allow established connections
ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Forwarding rules specifically for tun0 to eth0
ip6tables -A FORWARD -i tun0 -o eth0 -s 2607:f740:44:22::/64 -m state --state NEW -j ACCEPT
ip6tables -A FORWARD -i eth0 -o tun0 -d 2607:f740:44:22::/64 -m state --state ESTABLISHED,RELATED -j ACCEPT
# NAT rules if needed (less common in IPv6 but sometimes required)
ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
To test if forwarding is working:
# On a client in tun0 network:
ping6 2607:f740:0:3f::1
# Check counters on the server:
ip6tables -L -v -n
ip -6 route show
ip -6 neigh show
1. Missing neighbor discovery proxy:
echo 1 > /proc/sys/net/ipv6/conf/eth0/proxy_ndp
ip -6 neigh add proxy 2607:f740:44:22::8 dev eth0
2. Router advertisements interfering:
echo 0 > /proc/sys/net/ipv6/conf/eth0/accept_ra
echo 0 > /proc/sys/net/ipv6/conf/tun0/accept_ra
3. Path MTU discovery issues:
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
echo 1280 > /proc/sys/net/ipv6/conf/all/mtu
To make these changes survive reboots:
# For Debian/Ubuntu systems:
echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.conf
echo "net.ipv6.conf.default.forwarding=1" >> /etc/sysctl.conf
sysctl -p
# Save iptables rules
apt install iptables-persistent
netfilter-persistent save
For CentOS/RHEL systems:
echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.conf
echo "net.ipv6.conf.default.forwarding=1" >> /etc/sysctl.conf
sysctl -p
# Save iptables rules
service ip6tables save
chkconfig ip6tables on