iptables redirect local connections to remote system / port

I'm not completely sure if I understood, but I think you're just in the wrong chain. :-) I was confused, too, when I used iptables the first time. But the way to forward the local port ${LOCAL UNPRIV PORT} is the statement below:

$IPT -t nat -A PREROUTING -i eth0 -p tcp --dport ${LOCAL UNPRIV PORT} 
     -j DNAT --to ${ANOTHER SYSTEM}:${REMOTE PORT}

It is a mixture between a semantic problem and the way netfilter works: In the old days forwarding a local port involved a connection to the box that is forwarding, plus a second connection to the destination. Iptables does this in one step. So instead of two connections - you are forwarding the the traffic to that port directly to the destination. Netfilter does all the sanity checks and bookkeeping: only packets that belong to a valid connection are NATted and can therefore be forwarded.

Enabling DNAT doesn't allow any packets to be forwarded. You also have to add a rule:

$IPT -N INET-PRIV
$IPT -A FORWARD -i eth0 -o eth1 -j INET-PRIV
$IPT -A FORWARD -j DROP

$IPT -A INET-PRIV -p tcp -d ${ANOTHER SYSTEM} --dport ${REMOTE PORT} -j ACCEPT

$IPT -A INET-PRIV -j DROP

And you have to enable forwarding of course.

echo "1" > /proc/sys/net/ipv4/ip_forward

Pro iptables: more secure, more flexible, less memory and CPU used per connection

Contra iptables: forwarding a connection from a internal machine to a internal machine (feed it back into the eth0) doesn't make sense with iptables (of course you can always connect directly), forwarding traffic that is generated locally doesn't work (a port forwarding daemon might help - but usually doesn't make sense)

Exactly this might be the problem: you try to use NAT on a non-router, so you should use a forwarding daemon or skip this extra port forwarding completely and do:

ssh -L 1234:${ANOTHER SYSTEM}:${REMOTE PORT} special-vpn-box

On special-vpn-box you can only allow incoming connections from the router and outgoing connections to ${ANOTHER SYSTEM}:${REMOTE PORT} using iptables. That way users of the special-vpn-box can only access ${ANOTHER SYSTEM}:${REMOTE PORT} and won't be able to do anything else if they aren't trusted.


Here is what I do specifically for localhost forwarding:

iptables -t nat -A OUTPUT -m addrtype --src-type LOCAL --dst-type LOCAL -p tcp --dport 3306 -j DNAT --to-destination ip.ip.ip.ip
iptables -t nat -A POSTROUTING -m addrtype --src-type LOCAL --dst-type UNICAST -j MASQUERADE

sysctl -w net.ipv4.conf.all.route_localnet=1

Make sure you substitute ip.ip.ip.ip for your real public IP and also the --dport 3306 for the port you want to forward.

Finally run the sysctl command and also update your /etc/sysctl.conf

You can update sysctl.ctl to allow the routing of localhost with the following command:

echo "net.ipv4.conf.all.route_localnet=1" >> /etc/sysctl.conf

Now this all seems simple and good but it did take some research and hunting down. Be warned and understand that forwarding localhost/127.0.0.1 requires this method and the typical other examples do not work. Some examples of solutions that do not work with localhost:

iptables -t nat -A PREROUTING -p tcp --dport 3306 -j DNAT --to ip.ip.ip.ip:3306
iptables -t nat -A POSTROUTING -d ip.ip.ip.ip -j MASQUERADE

http://realtechtalk.com/iptables_how_to_forward_localhost_port_to_remote_public_IP-1788-articles


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

iptables -t nat -A PREROUTING  -p tcp \
--dport ${LOCAL UNPRIV PORT} -j DNAT --to-destination ${ANOTHER SYSTEM}:${REMOTE PORT}

iptables -t nat -A POSTROUTING -p tcp \
--dst ${ANOTHER SYSTEM} --dport ${REMOTE PORT} -j SNAT --to-source ${LOCAL SYSTEM}