I have a host that sends packets to virtual machine say on with either or as the destination IP. I'm trying to set up the virtual machine as a NAT. It routes the packets, changing the destination IP, depending on the original destination IP so I wasn't able to only use SNAT as the original IP was getting switched in PREROUTING. What I've been trying to use is the --set-mark flag to flag the packets with either 11 or 12 so the POSTROUTING rules will know what SNAT rule to use. Here are my rules:

iptables -t mangle -A PREROUTING --destination -j MARK --set-mark 11
iptables -t nat -A PREROUTING -m mark --mark 11 -i eth0 -j DNAT --to
iptables -t nat -A POSTROUTING -m mark --mark 11 -o eth1 -j SNAT --to-source


iptables -t mangle -A PREROUTING --destination -j MARK --set-mark 12
iptables -t nat -A PREROUTING -m mark --mark 12 -i eth0 -j DNAT --to
iptables -t nat -A POSTROUTING -m mark --mark 12 -o eth1 -j SNAT --to-source

My first two rules are being incremented if I watch iptables -t mangle/nat -nvL but the POSTROUTING rule never gets matched. Any ideas on why this would be?

I just thought of this while writing this. The first network is /24 subnet and I have then second network currently set up as a /8 subnet. Would this affect this in any way?


To make things a little more clear.

This first step is the host sends either or from to the virtual machine like so.

                     Destination IPs
     HOST           ================
===============  +--* *--+  ======
* *---  ================  ---* VM *
===============  +--* *--+  ======

I then want the virtual machine to forward these packets with both of the destination IP changed to Then have the source IP change to either or depending on what the original destination IPs were. Like so.

            Source IPs w/ as Destination IP 
======  +--* *--+   ============
* VM *---  ==============  ---* Test rig *
======  +--* *--+   ============

Also to be clear this is a NAT on a private network. There is no internet connection here. Just Host <--> VM <--> Test rig


One more drawing to make it a little more clear.

                  Destination IPs     Source IPs
     HOST         ==============    ===============        Test rig
=============  +--**-+  | *--+  ==============
**---  ============== +--* VM          |  +--* *
=============  +--**-+  | *--+  ==============
                  ==============    ===============
  • What exactly is your topology? Outside world <-> <> <-><>? – EvilTorbalan Dec 15 '15 at 23:04
  • Host <-> VM <-> Test PC. See the 'EDIT' I made. – jesse Dec 16 '15 at 14:48
  • It does not really matter if its connected to the internet or not. So all requests come from or it is acting as a gateway between 192.168.0/24 and some other network and forwarding packets? – EvilTorbalan Dec 16 '15 at 14:53
  • The VM is forwarding packets. It's purpose is to act as a simulator for networking traffic to change packets for the test rig as they would be in the field. Forwarding what's coming out of the host (where lab tools are located) to the test rig. – jesse Dec 16 '15 at 14:58

Your rules look right, check if you have bridges setup, these can make packet's in/out interfaces to be messed up. You can also add -j LOG rules to watch what gets matched in your logs.

| improve this answer | |
  • I'm not sure if I have a gateway but I could be wrong. I want a VM on the host to 'simulate' packets for a test rig by forwarding packets from the host to the test rig. See the EDIT I made above. – jesse Dec 16 '15 at 14:51
  • 2
    My issue is this. I can't use just SNAT and DNAT because the outgoing source depends on the incoming destination (from the point of view of the VM). This is because the incoming destination was changed in PREROUTING and now we want to determine the outgoing source in POSTROUTING based on the incoming destination. That's why I started looking into marking the packets when they arrive so I can match them on their way out. This match on the way out is not catching any packets. – jesse Dec 16 '15 at 14:53
  • 1
    Yes, but that's what connection tracking is for. Its tracking each connection and remembers how it was NAT'ed and when packets come on this connection it knows how to handle them. Checkout /proc/net/ip_conntrack – EvilTorbalan Dec 16 '15 at 14:55
  • Connection tracking as in using conntrack? – jesse Dec 16 '15 at 14:59
  • 1
    I didn't have ipv4 forwarding enables and now I'm seeing the POSTROUTING rule being incremented! HA! I'm going to go test it out. Thank you for your help and confirming my rules are correct. Starting to feel more confident with this now. – jesse Dec 16 '15 at 16:05

Have you enabled IP forwarding on the host? If not then your second rules will never get matched because forwarded packets will be ignored by the kernel.

You can check with a cat /proc/sys/net/ipv4/ip_forward. If the output is zero, you can try echo 1 > /proc/sys/net/ipv4/ip_forward to see if that solves your problem. If so, echo net.ipv4.ip_forward = 1 >> /etc/sysctl.conf will make the setting survive a reboot.

I wanted to make this a comment but my reputation was too small. Sorry to post such an obvious answer but this has caught me out so many times that it's worth posting!

| improve this answer | |
  • I myself have missed this many times – EvilTorbalan Dec 17 '15 at 23:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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