Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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

  • eth1:
  • eth2:

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 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 dev eth2

which send all 192.168.1.x on eth2, except for which is still routed internally. May be I could then do NAT forwarding of all traffic directed to fake on eth1, rerouted to 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!


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?

share|improve this question
Are you saying you want all traffic mirrored through interface 1 and 2 but only be returned to interface 2 from another router? Couldn't that do some pretty weird stuff on the network? Would it be better to direct mirrored traffic from interface 2 to another system that just dropped traffic and then you can monitor it, or use virtualization software to capture the traffic? Maybe I'm missing something in the description. – Bart Silverstrim Mar 30 '10 at 12:25
It sounds like he wants to generate a packet to, say, which is the IP of eth1. But instead of the Linux stack receiving that packet entirely internally he wants the packet forced out eth2 (which will be delivered externally back into eth1 and then the Linux stack). I'm not sure if this is possible; once the network layer detects the address is an internal interface it will have little reason to look at routing tables. Someone else may know better. – PP. Mar 30 '10 at 13:59
up vote 9 down vote accepted

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 -s -j SNAT --to-source
iptables -t nat -A PREROUTING  -d -i eth0           -j DNAT --to-destination
iptables -t nat -A POSTROUTING -d -s -j SNAT --to-source
iptables -t nat -A PREROUTING  -d -i eth1           -j DNAT --to-destination

The rules do the following:

  1. Rewrite source to on outgoing packets
  2. Rewrite destination to on incoming packets
  3. Rewrite source to on outgoing packets
  4. Rewrite destination to on incoming packets

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

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 via $ROUTER_2_SUBNET_IP 
ip route 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.

share|improve this answer
Much better your way! Note that I also need an ip_forward to have the ARP stuff working: echo 1 > /proc/sys/net/ipv4/ip_forward – calandoa Apr 2 '10 at 17:28
up vote 22 down vote

I successfully used the following on Linux to test throughput on a new dual-port 10Gbps card in "loopback" mode, that is, one port plugged directly into the other. This is all just a bit of voodoo just to force packets out the wire, but if you don't, Linux will just short-circuit the traffic through the kernel (hence the OP's question). In Casey's answer above, I'm not sure if it was really necessary to have an external router or not above, but the following is completely self-contained. The two interfaces are eth2 and eth3.

Give IPs to the interfaces, and put them on separate networks:

ifconfig eth2
ifconfig eth3

Next we'll set up a double NAT scenario: two new fake networks used to reach the other. On the way out, source NAT to your fake network. On the way in, fix the destination. And vice versa for the other network:

# nat source IP -> when going to
iptables -t nat -A POSTROUTING -s -d -j SNAT --to-source

# nat inbound ->
iptables -t nat -A PREROUTING -d -j DNAT --to-destination

# nat source IP -> when going to
iptables -t nat -A POSTROUTING -s -d -j SNAT --to-source

# nat inbound ->
iptables -t nat -A PREROUTING -d -j DNAT --to-destination

Now tell the system how to get to each fake network, and prepopulate the arp entries (be sure to substitute your MAC addresses, don't use mine):

ip route add dev eth2
arp -i eth2 -s 00:1B:21:C1:F6:0F # eth3's mac address

ip route add dev eth3 
arp -i eth3 -s 00:1B:21:C1:F6:0E # eth2's mac address

This fools Linux enough to actually put packets onto the wire. For example:


goes out eth2, the source IP gets NATted to, and as it comes into eth3 the destination gets NATted to And the reply takes a similar journey.

Now use iperf to test throughput. Bind to the correct IPs, and be certain which IP you're contacting (the other end's fake address):

# server
./iperf -B -s

# client: your destination is the other end's fake address
./iperf -B -c -t 60 -i 10

Make sure traffic is really going out to the wire:

tcpdump -nn -i eth2 -c 500

You can also watch /proc/interrupts just to be absolutely sure the card is being used:

while true ; do egrep 'eth2|eth3' /proc/interrupts ; sleep 1 ; done

Anyhow, I found this post searching for how to do this, thanks for the Q&A guys, and hope this helps anyone else finding this post in the future.

share|improve this answer
+1 Great solution - this does not even require to activate ip-forwarding! This is just what I needed right now (for 10GB testing via loopback). – Nils Mar 5 '13 at 15:21
Wow, thanks @Nils for the bounty! – Steve Kehlet Mar 6 '13 at 23:53

Ok, I finally succeeded in setting up my config.

The idea is to use another fake address, to force the route of this fake address to the interface 2 , then to translate the fake address with the real address 2 with NAT/iptables.

My set up is actually made of one router I can telnet between IF1 (interface 1) and IF2

In my set up, FAKE_ADDR and IF1_ADDR are on the same subnet.

ifconfig $IF1 $IF1_ADDR netmask
ifconfig $IF2 $IF2_ADDR netmask

iptables -t nat -A PREROUTING -d $FAKE_ADDR -i $IF2 -j DNAT --to-destination $IF2_ADDR
iptables -t nat -A POSTROUTING -s $IF2_ADDR -d $IF1_ADDR/24 -j SNAT --to-source $FAKE_ADDR

route add $FAKE_ADDR gw $ROUTER_ADDR

And on the router:

route add $FAKE_ADDR gw $IF2_ADDR

If I send something to FAKE_ADDR, pkt is forwarded through IF1 to the router, forwarded again to IF2, then FAKE_IP is replaced by IF2_ADDR. The packet is processed by the server, the result is send back to IF1_ADDR, from IF2_ADDR which is replaced by FAKE_ADDR.

May be it is possible to use a simpler configuration with just one crossover cable, but as I didnot tried I prefer to give my working solution.

share|improve this answer
if the router is sending $FAKE_ADDR to $IF2_ADDR, doesn't your DNAT rule need to be "-i $IF2" instead of "-i $IF1"? – cmcginty Mar 31 '10 at 5:33
You are right Casey, correction done. – calandoa Mar 31 '10 at 14:13

It sounds like you want to turn your linux box into a router/bridge/gateway/firewall type box. The following resources may be what you are looking for:

The Linux Router Project

List of router or firewall distributions

Linux LiveCD Router

Linux Journal - The Linux Router

Update based upon further information:

I don't think you are going to be able to do what you want. The OS is always going to look at its internal routing table and 'see' both IP addresses locally. It will then route the traffic within the OS and never put it on the wire. You will need a second machine or two virtual machines (check out Xen).

share|improve this answer

A lot of stuff to go through here, so I can't totally guarantee my accuracy, but the original question seems to be looking for what's known as "send to self" technique. Linked search shows what I think is the best maintained kernel patch as top link + discussions and patches with other approaches on various mailing lists, esp. LKML.

I think one should also look at network namespaces, done with iproute2's "ip netns". This also takes some extra interface and routing magic, so might not even be less complex than the massive iptables hoopla in the other answers.

Comments definitely welcome if anyone found something useful with these - the how, the what, the where about your implementation.

share|improve this answer

Check this article. Here the detailed steps is mentioned for enabling internet access to a virtualbox vm using NAT forwarding.

share|improve this answer
Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference. – Scott Pack Nov 3 '12 at 21:51

here is how i got it working for IPV6

assigned static ips

/sbin/ifconfig eth1 inet6 add 2001:db8::1/127 
/sbin/ifconfig eth3 inet6 add 2001:db8::2/127 

set up host only routes to "FAKE" addresses

ip -6 route add 2001:db8::2/128 dev eth1 metric 1
ip -6 route add 2001:db8::1/128 dev eth3 metric 1

populated the Neighbor table the arp

ip -6 neighbor add 2001:db8::1 lladdr 90:e2:ba:0d:75:e8 dev eth3 # eth1's mac address
ip -6 neighbor add 2001:db8::2 lladdr 90:e2:ba:0d:75:e9 dev eth1 # eth3's mac address

added the ip6tables entries

ip6tables -t nat -A POSTROUTING -s 2001:db8::1 -d 2013::2 -j SNAT --to-source 2001:db8::1
ip6tables -t nat -A PREROUTING -d 2001:db8::1 -j DNAT --to-destination 2001:db8::1
ip6tables -t nat -A POSTROUTING -s 2001:db8::2 -d 2013::1 -j SNAT --to-source 2001:db8::2
ip6tables -t nat -A PREROUTING -d 2001:db8::2 -j DNAT --to-destination 2001:db8::2
share|improve this answer
What distribution are you using? Last time I checked, the kernel does not have a NAT table for IPv6. – fukawi2 Dec 11 '14 at 23:05

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.