How to Redirect All Traffic from Secondary Public IP to Internal IP Using iptables DNAT Rules


3 views

When working with dedicated servers that have multiple public IP addresses, a common requirement is to forward all traffic from a secondary public IP to an internal virtual machine. This is particularly useful when you want to expose services running on VMs (like web servers) through a dedicated public IP while keeping your main server's IP clean.

For complete traffic forwarding, you'll need three essential iptables rules:

# 1. DNAT rule for incoming traffic
iptables -t nat -A PREROUTING -d 8.8.8.8 -j DNAT --to-destination 192.168.1.101

# 2. Allow forwarded traffic
iptables -A FORWARD -d 192.168.1.101 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

# 3. SNAT for response packets
iptables -t nat -A POSTROUTING -s 192.168.1.101 -j SNAT --to-source 8.8.8.8

The most frequent issues I've encountered when setting up full traffic forwarding:

1. Missing FORWARD chain rules: Many forget that after DNAT, packets still need to be allowed through the FORWARD chain.

2. Routing asymmetries: Ensure your VM's default gateway points to your host server's internal IP.

3. IP forwarding disabled: Verify it's enabled with:

sysctl net.ipv4.ip_forward=1

Here's a tested configuration that works for full traffic forwarding:

# Enable IP forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward

# Flush existing NAT rules
iptables -t nat -F

# DNAT all traffic for secondary IP
iptables -t nat -A PREROUTING -d 8.8.8.8 -j DNAT --to-destination 192.168.1.101

# Allow forwarded traffic
iptables -A FORWARD -d 192.168.1.101 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -s 192.168.1.101 -m state --state ESTABLISHED,RELATED -j ACCEPT

# SNAT for return traffic
iptables -t nat -A POSTROUTING -s 192.168.1.101 -j SNAT --to-source 8.8.8.8

To confirm everything works:

# Check NAT rules
iptables -t nat -L -n -v

# Test connectivity
curl --interface 8.8.8.8 ifconfig.me  # Should return 8.8.8.8
telnet 8.8.8.8 80  # Should connect to your VM's service

For production environments, you might want to:

# Rate limiting to prevent abuse
iptables -A FORWARD -d 192.168.1.101 -m limit --limit 100/minute -j ACCEPT

# Logging for debugging
iptables -N LOG_DROP
iptables -A LOG_DROP -j LOG --log-prefix "[IPTABLES DROP] "
iptables -A LOG_DROP -j DROP
iptables -A FORWARD -d 192.168.1.101 -j LOG_DROP

In this scenario, we have a dedicated server with:

  • Primary public IP (e.g., 1.1.1.1)
  • Secondary public IP (e.g., 8.8.8.8)
  • Private LAN (192.168.1.0/24) with multiple VMs
  • Bridge interface connecting physical server to VMs

The existing outbound NAT rule works correctly:

iptables -t nat -A POSTROUTING -s 192.168.1.101 -j SNAT --to-source 8.8.8.8

While the DNAT rule you've tried is fundamentally correct:

iptables -t nat -A PREROUTING -d 8.8.8.8 -j DNAT --to-destination 192.168.1.101

There are several additional considerations needed for full functionality:

Here's the full set of rules needed:

# Enable IP forwarding at kernel level
echo 1 > /proc/sys/net/ipv4/ip_forward

# DNAT rule for incoming traffic
iptables -t nat -A PREROUTING -d 8.8.8.8 -j DNAT --to-destination 192.168.1.101

# Allow forwarding between interfaces
iptables -A FORWARD -i eth0 -o br0 -d 192.168.1.101 -j ACCEPT
iptables -A FORWARD -i br0 -o eth0 -s 192.168.1.101 -j ACCEPT

# Optional: MASQUERADE for return traffic (alternative to SNAT)
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

To test the configuration:

  1. Run tcpdump on both physical and virtual interfaces
  2. Check connection tracking: conntrack -L
  3. Verify routing with: ip route get 8.8.8.8

For production environments, you might want to:

  • Add rate limiting to prevent abuse
  • Implement connection tracking helpers for specific protocols
  • Set up logging for troubleshooting
# Example logging rule
iptables -A FORWARD -d 192.168.1.101 -j LOG --log-prefix "IP-FWD: "

If connections still time out:

  1. Check VM firewall rules (iptables/nftables)
  2. Verify bridge interface configuration
  3. Ensure ARP filtering is disabled: echo 0 > /proc/sys/net/ipv4/conf/all/arp_filter