Linux – Force local IP traffic to an external interface

command-line-interfaceipiptableslinuxnetworking

I have a machine with several interfaces that I can configure as I want, for instance:

  • eth1: 192.168.1.1
  • eth2: 192.168.2.2

I would like to forward all the traffic sent to one of these local addresses through the other interface. For instance, all requests to an iperf, ftp, http server at 192.168.1.1 should be not just routed internally, but forwarded through eth2 (and the external network will take care of re-routing the packet to eth1).

I tried and looked at several commands, like iptables, ip route, etc… but nothing worked.

The closest behavior I could get was done with:

ip route change to 192.168.1.1/24 dev eth2

which send all 192.168.1.x on eth2, except for 192.168.1.1 which is still routed internally.
May be I could then do NAT forwarding of all traffic directed to fake 192.168.1.2 on eth1, rerouted to 192.168.1.1 internally? I am actually struggling with iptables, but it is too tough for me.

The goal of this setup is to do interface driver testing without using two PCs.

I am using Linux, but if you know how to do that with Windows, I'll buy it!

Edit:

The external network is just a crossover cable between eth1 and eth2.
Let's say I have an http server on my machine.
Now I want to access this server from the same machine, but I want to force the TCP/IP traffic to go through this eth1/eth2 cable. How should I configure my interfaces for this?

Best Answer

I expanded on caladona's answer since I could not see response packets. For this example:

  1. On my local PC I have NIC's on different subnets, 192.168.1/24, 192.168.2/24
  2. There is an external router/PC that has access to both subnets.
  3. I want to send bi-directional traffic over the NICs on the local PC.
  4. The configuration requires two unused IP addresses for each subnet.

Local PC iptable routes are set to SNAT and DNAT outgoing traffic to the 'fake' IP.

iptables -t nat -A POSTROUTING -d 192.168.1.100 -s 192.168.2.0/24 -j SNAT --to-source      192.168.2.100
iptables -t nat -A PREROUTING  -d 192.168.1.100 -i eth0           -j DNAT --to-destination 192.168.1.1
iptables -t nat -A POSTROUTING -d 192.168.2.100 -s 192.168.1.0/24 -j SNAT --to-source      192.168.1.100
iptables -t nat -A PREROUTING  -d 192.168.2.100 -i eth1           -j DNAT --to-destination 192.168.2.1

The rules do the following:

  1. Rewrite 192.168.2.1 source to 192.168.2.100 on outgoing packets
  2. Rewrite 192.168.1.100 destination to 192.168.1.1 on incoming packets
  3. Rewrite 192.168.1.1 source to 192.168.1.100 on outgoing packets
  4. Rewrite 192.168.2.100 destination to 192.168.2.1 on incoming packets

To summarize, the local system now can talk to a 'virtual' machine with addresses 192.168.1.100 and 192.168.2.100.

Next you have to force your local PC to use the external router to reach your fake IP. You do this by creating a direct route to the IP's through via the router. You want to make sure that you force the packets onto the opposite of the destination subnet.

ip route 192.168.1.100 via $ROUTER_2_SUBNET_IP 
ip route 192.168.2.100 via $ROUTER_1_SUBNET_IP

Finally to make this all work, the external router needs to know how to reach the faked IPs on your local PC. You can do thins by turning on proxy ARPs on for your system.

echo 1 | sudo tee /proc/sys/net/ipv4/conf/all/proxy_arp
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward

With this setup, you can now treat the fake IPs as a real system on your local PC. Sending data to .1 subnet will force packets out the .2 interface. Sending data to the .2 subnet will force packets out the .1 interface.

ping 192.168.1.100
ping 192.168.2.100
Related Topic