Linux – Using IPTables to forward port for incoming eth1(local) to outgoing ppp0 (vpn) to specific ip address

iptableslinuxport-forwarding

So I have a VPN on ppp0 and I setup so I can use either ppp0 or eth1 to connect out with the default route being eth1.

Both reply to "ping google.com" (uses eth1) and "ping -I ppp0 google.com" (uses VPN)

Goal: If I connect to eth1 on port 12345 it will forward out ppp0 to a specific ip address (123.123.123.123).

eth1: local network
ppp0: vpn service
local network: 10.10.1.0/24
forwarding ip: 123.123.123.123
port: 12345

ports can be different the same doesnt matter, if it works 🙂

iptables -t nat -A PREROUTING -p tcp -i eth1 -d 10.10.1.0/24 --dport 12345 -j DNAT --to-destination 123.123.123.123:12345
iptables -A FORWARD -p tcp -o ppp0 -d 123.123.123.123 --dport 12345 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT

After searching this is what most people say. Use the PREROUTE to set new destination. Then forward out ppp0. But its not working and I don't know how to actually see what its doing.

Best Answer

iptables -t nat -A PREROUTING -p tcp -i eth1 -d 10.10.1.0/24 \
  --dport 12345 -j DNAT --to-destination 123.123.123.123:12345

Locally generated traffic will never pass through the PREROUTING chain. You can verify this by adding a rule like this:

iptables -t nat -A PREROUTING -j log -m limit --limit 1/s

If you're not familiar with iptables, the above rule means:

  • Log (at a maximum rate of 1 message/second) any packets traversing the PREROUTING chain.

Watch your log files while you make outbound connections, and you'll see that nothing is passing through this chain. The PREROUTING chain only comes into play for traffic coming into your system from an outside source.

You might think you could do this in the OUTPUT chain:

iptables -t nat -A OUTPUT ... -j DNAT ...

But by the time a packet hits the OUTPUT chain the routing decision has already been made. You can probably get you want by using a REDIRECT rule in the OUTPUT chain and then running a tcp proxy on a local port that redirects connections to your destination. That is, you can add a rule like this:

iptables -t nat -A OUTPUT -p tcp -d 10.10.1.0/24 --dport 12345 \
  -j REDIRECT --to-ports 12345

And then run a tcp proxy locally on port 12345.