Many legacy systems still rely on IPv4-only configurations, while modern infrastructure increasingly adopts IPv6. Bridging these protocols becomes essential when you need to expose IPv6 services through IPv4-only backend servers. Let's explore how iptables can solve this.
Before implementing the solution, ensure your system meets these requirements:
- Linux kernel 2.6.32+ with IPv6 support
- iptables 1.4.7+ with ip6tables module
- IPv6 connectivity on the gateway machine
- Proper routing between the gateway and IPv4 server
We'll use a dual-stack server as a gateway to:
- Accept IPv6 incoming connections
- Translate them to IPv4
- Forward to the backend IPv4 server
- Route responses back to IPv6 clients
Here's the complete iptables configuration for forwarding TCP port 80 from IPv6 to IPv4:
# Enable IPv6 forwarding
sysctl -w net.ipv6.conf.all.forwarding=1
# IPv6 DNAT rule (assuming gateway's IPv6 is 2001:db8::1)
ip6tables -t nat -A PREROUTING -d 2001:db8::1 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.100:80
# IPv4 SNAT rule for return traffic
iptables -t nat -A POSTROUTING -d 192.168.1.100 -p tcp --dport 80 -j SNAT --to-source 192.168.1.1
# Forwarding between interfaces
iptables -A FORWARD -d 192.168.1.100 -p tcp --dport 80 -j ACCEPT
Verify the setup with these commands:
# Check NAT rules
ip6tables -t nat -L -n -v
iptables -t nat -L -n -v
# Test connectivity
curl -6 http://[2001:db8::1]
For UDP services or multiple ports, modify the rules accordingly:
# UDP port forwarding example
ip6tables -t nat -A PREROUTING -d 2001:db8::1 -p udp --dport 53 -j DNAT --to-destination 192.168.1.100:53
# Port range forwarding
ip6tables -t nat -A PREROUTING -d 2001:db8::1 -p tcp --dport 8000:9000 -j DNAT --to-destination 192.168.1.100:8000-9000
- Connection timeouts: Check IPv4 routing and firewall rules on the backend server
- Partial connectivity: Verify both IPv4 and IPv6 modules are loaded in kernel
- Rule not applying: Ensure the ip6tables service is running and rules persist after reboot
On most distributions, save rules with:
ip6tables-save > /etc/ip6tables.rules
iptables-save > /etc/iptables.rules
Then configure your init system to restore them at boot.
In some server setups, you might encounter a situation where a critical service is only accessible via IPv4, while your front-facing server supports IPv6. This can happen due to legacy configurations, hardware limitations, or network policies. The challenge is to bridge this gap without overhauling your entire infrastructure.
iptables remains a powerful tool for network address translation (NAT) in Linux systems, even in mixed IPv4/IPv6 environments. While newer tools like nftables exist, many administrators still rely on iptables for its widespread compatibility and familiar syntax.
Before implementing this solution, ensure:
- Your IPv6-capable server has IPv4 connectivity to the target server
- IPv6 forwarding is enabled (
net.ipv6.conf.all.forwarding=1
) - You have root access to configure iptables rules
Here's how to forward TCP port 80 traffic from IPv6 to an IPv4 server:
# Enable IPv6 forwarding
sysctl -w net.ipv6.conf.all.forwarding=1
# Allow incoming IPv6 connections
ip6tables -A INPUT -p tcp --dport 80 -j ACCEPT
# NAT the IPv6 traffic to IPv4
ip6tables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.1.100:80
# Allow the forwarded traffic
iptables -A FORWARD -p tcp -d 192.168.1.100 --dport 80 -j ACCEPT
# Masquerade the outgoing IPv4 traffic
iptables -t nat -A POSTROUTING -p tcp -d 192.168.1.100 --dport 80 -j MASQUERADE
For forwarding multiple ports (e.g., 80 and 443), you can use multiport:
ip6tables -t nat -A PREROUTING -p tcp -m multiport --dports 80,443 -j DNAT --to-destination 192.168.1.100
iptables -A FORWARD -p tcp -d 192.168.1.100 -m multiport --dports 80,443 -j ACCEPT
To make these changes permanent:
# Save iptables rules
iptables-save > /etc/iptables/rules.v4
ip6tables-save > /etc/iptables/rules.v6
# Enable persistent forwarding
echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.conf
sysctl -p
- Verify forwarding is working with
tcpdump -i eth0 ip6
andtcpdump -i eth0 ip
- Check kernel logs (
dmesg
) for NAT-related errors - Test connectivity from an IPv6 client using
curl -6 http://[your-ipv6-address]
When implementing this solution:
- Restrict source IPs if possible (
-s
flag in iptables) - Consider rate limiting to prevent abuse
- Monitor forwarded traffic for unusual patterns