iptables – Mark by Destination and Change Destination/Source by Mark

iptableslinuxlinux-networking

I'm trying to use iptables to:

  1. Mark packets going to a destination IP
  2. Detect that mark to change the destination IP
  3. Detect that mark to change the source IP

These are the commands I'm trying to use to achieve that:

sudo iptables -t mangle -A PREROUTING --destination 192.0.2.0 -j MARK --set-mark 11
sudo iptables -t nat -A PREROUTING -m mark --mark 11 -j DNAT --to-destination ${DESTINATION_IP}
sudo iptables -t nat -A POSTROUTING -m mark --mark 11 -j SNAT --to-source ${SOURCE_IP}

It looks like the first MARK command is not picking up any packets to mark them:

sudo iptables -vL -t mangle
Chain PREROUTING (policy ACCEPT 11892 packets, 1184K bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 MARK       all  --  any    any     anywhere             192.0.2.0            MARK set 0xb

After that the later rules do not see any marked packets to modify.

Am I right in thinking that pkts being 0 for that rule means it hasn't matched any packets?

How should I be marking packets to later identify and modify?

Best Answer

Local-originated packets don't pass through PREROUTING chain, but through OUTPUT. So, if you try to test your rules from the same host, you should add the MARK rule into mangle/OUTPUT chain and the DNAT rule into nat/OUTPUT chain.

In result your rules will look like:

sudo iptables -t mangle -A OUTPUT --destination 192.0.2.0 -j MARK --set-mark 11
sudo iptables -t nat -A OUTPUT -m mark --mark 11 -j DNAT --to-destination ${DESTINATION_IP}
sudo iptables -t nat -A POSTROUTING -m mark --mark 11 -j SNAT --to-source ${SOURCE_IP}

Also, there is a way to avoid marking and refer to the original (before translation) addresses and port numbers.

sudo iptables -t nat -A OUTPUT --dst 192.0.2.0 -j DNAT --to ${DESTINATION_IP}
sudo iptables -t nat -A POSTROUTING -m conntrack --ctstate DNAT --ctorigdst 192.0.2.0 -j SNAT --to ${SOURCE_IP}

To get the options list of an iptables match or an iptables target you can use brief built-in help. For example:

iptables -m connmark --help
iptables -j DNAT --help

When you troubleshoot nat rules, you should know only first packet of new connection passes the nat table.

Other tools to troubleshoot issues are the tcpdump and the conntrack.