How to Redirect Local Connections to Remote Ports Using iptables and SSH Tunneling


8 views

Many sysadmins and developers need to securely expose services behind firewalls using encrypted tunnels. A common approach involves redirecting local connections through SSH port forwarding to a remote system. However, older iptables NAT techniques like:

iptables -A OUTPUT -t nat --dport ${LOCAL_UNPRIV_PORT} \
    -j DNAT ${REMOTE_SYSTEM}:${REMOTE_PORT}

no longer work in modern Linux kernels due to the removal of implicit source local NAT support (the IP_NF_NAT_LOCAL kernel module). The kernel logs typically show:

kernel: NAT: no longer support implicit source local NAT

Here's a more maintainable approach using SSH tunnels and proper iptables rules:

# On the RedHat server (jump host):
ssh -N -L 0.0.0.0:${UNPRIV_PORT}:localhost:${UNPRIV_PORT} user@localhost

# On the client machine:
ssh -N -R ${UNPRIV_PORT}:${TARGET_IP}:3389 user@jump_host

For systems where you must use iptables, configure these rules instead:

# Enable IP forwarding
sysctl -w net.ipv4.ip_forward=1

# NAT rule for incoming connections
iptables -t nat -A PREROUTING -p tcp --dport ${UNPRIV_PORT} \
    -j DNAT --to-destination ${TARGET_IP}:3389

# Masquerade outgoing traffic
iptables -t nat -A POSTROUTING -j MASQUERADE

# Allow forwarded traffic
iptables -A FORWARD -p tcp --dport 3389 -j ACCEPT

When iptables proves problematic, socat provides a reliable alternative:

# On the jump host:
socat TCP-LISTEN:${UNPRIV_PORT},fork TCP:${TARGET_IP}:3389

# With SSH tunneling:
ssh -L ${UNPRIV_PORT}:localhost:${UNPRIV_PORT} user@jump_host

Always remember to:

  • Restrict source IPs in your iptables rules
  • Use SSH key authentication
  • Consider fail2ban for brute force protection
  • Monitor tunnel connections
# Example restricted iptables rule:
iptables -A INPUT -p tcp --dport ${UNPRIV_PORT} \
    -s ${TRUSTED_IP} -j ACCEPT

When troubleshooting, check these essential tools:

# Check NAT table:
iptables -t nat -L -v -n

# Monitor connections:
ss -tulpn | grep ${UNPRIV_PORT}

# Check kernel messages:
dmesg | grep NAT

# Verify SSH tunnels:
lsof -i -n | egrep '\<ssh\>'

When attempting to create specialized SSH port forwarding for RDP access behind firewalls, many admins hit a snag with modern Linux kernels. The traditional approach using:

iptables -A OUTPUT -t nat --dport ${LOCAL_PORT} \
    -j DNAT ${REMOTE_IP}:${REMOTE_PORT}

now triggers the kernel message "NAT: no longer support implicit source local NAT". This change dates back to kernel 2.6.10's removal of IP_NF_NAT_LOCAL support.

Modern kernels prevent DNAT operations on locally-generated packets in the OUTPUT chain due to security concerns about loopback interface manipulation. The packets never hit the PREROUTING chain where NAT typically occurs.

Here are three validated methods to achieve local-to-remote forwarding:

Method 1: Loopback Interface Redirection

# Enable routing of local packets
sysctl -w net.ipv4.conf.all.route_localnet=1

# Redirect local port to remote
iptables -t nat -A PREROUTING -p tcp --dport 3389 -j DNAT --to-destination 10.0.0.5:5000
iptables -t nat -A POSTROUTING -p tcp -d 10.0.0.5 --dport 5000 -j SNAT --to-source ${LOCAL_IP}

Method 2: SSH Double Tunnel

# On client machine
ssh -L 5000:localhost:5000 user@jump_host

# On jump host
ssh -L 5000:target_host:3389 user@target_host

Method 3: socat Relay

# On intermediate host
socat TCP4-LISTEN:5000,fork TCP4:target_host:3389

When implementing these solutions:

  • Always restrict source IPs using iptables -s filters
  • Consider rate limiting to prevent brute force attacks
  • Use SSH key authentication exclusively
  • Monitor connection attempts in your firewall logs

The socat method typically shows 15-20% lower latency than iptables redirects for RDP traffic, but consumes more CPU. For high-availability scenarios, consider using HAProxy with health checks:

listen rdp_gateway
    bind :5000
    mode tcp
    server target1 10.0.0.5:3389 check inter 2000

Remember to test any solution thoroughly in a staging environment before deploying to production. The optimal approach depends on your specific network topology and security requirements.