Practical iptables NAT Port Forwarding: Access External Services via Intermediate Server


4 views

Let's break down the scenario with the three machines:

  • Local PC: Public IP 1.2.3.4
  • Ubuntu Server: eth0 with public IP 5.6.7.8
  • Target Server: Slashdot at 216.34.181.45

To forward traffic from your Ubuntu server (5.6.7.8:8080) to Slashdot (216.34.181.45:80), use these iptables rules:

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

# PREROUTING rule to change destination
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 216.34.181.45:80

# POSTROUTING rule for response routing
iptables -t nat -A POSTROUTING -p tcp -d 216.34.181.45 --dport 80 -j SNAT --to-source 5.6.7.8

If Slashdot were on the same LAN as your Ubuntu box:

  1. The destination IP would be a private address (e.g., 192.168.1.100)
  2. You might not need SNAT if routing works without it
  3. Simpler rule would suffice:
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.100:80

MASQUERADE isn't strictly needed here since:

  • We know our outgoing interface's IP (5.6.7.8)
  • SNAT is more efficient when IP is static
  • Use MASQUERADE only if your public IP changes dynamically:
iptables -t nat -A POSTROUTING -p tcp -d 216.34.181.45 --dport 80 -j MASQUERADE

After applying rules:

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

# Test connectivity
curl http://5.6.7.8:8080

# Monitor traffic
tcpdump -i eth0 port 8080 -n

To make rules survive reboots on Ubuntu:

# Install persistence package
apt-get install iptables-persistent

# Save current rules
iptables-save > /etc/iptables/rules.v4

# Enable IP forwarding permanently
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p

Add these security measures:

# Restrict source IP if possible
iptables -t nat -A PREROUTING -p tcp -s 1.2.3.4 --dport 8080 -j DNAT --to-destination 216.34.181.45:80

# Rate limiting to prevent abuse
iptables -A FORWARD -p tcp --dport 80 -m limit --limit 50/minute --limit-burst 100 -j ACCEPT

Let's break down the network setup:

  • Local PC: Public IP 1.2.3.4
  • Ubuntu Server: eth0 with public IP 5.6.7.8
  • Target Server: External website (e.g., Slashdot at 216.34.181.45)

To access Slashdot via your Ubuntu server's port 8080, you'll need these iptables rules:

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

# PREROUTING rule to redirect incoming traffic
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 216.34.181.45:80

# POSTROUTING rule for response packets
iptables -t nat -A POSTROUTING -p tcp -d 216.34.181.45 --dport 80 -j SNAT --to-source 5.6.7.8

If Slashdot was on the same LAN as your Ubuntu box, the setup would differ:

# For LAN target, use the internal IP in DNAT
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.100:80

# POSTROUTING can be simplified
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

While basic port forwarding can work with just PREROUTING/POSTROUTING, MASQUERADE is often better for:

  • Dynamic IP addresses
  • Simpler configuration when the source IP might change
  • Cases where you don't know the exact outgoing interface IP

Example using MASQUERADE:

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

After setting up the rules, test with:

curl http://5.6.7.8:8080

Check your rules with:

iptables -t nat -L -v -n

On Ubuntu, save your rules permanently with:

iptables-save > /etc/iptables.rules

Then add this to /etc/rc.local (before 'exit 0'):

iptables-restore < /etc/iptables.rules