So what options are there? One way is to repeat the same rule for different sources or destinations, but this can quickly get messy, especially if there’s multiple ports involved. If there was a way we could group things together and keep them tidy, maintaining the rulebase would be a lot easier. This is where MARK comes in.
The MARK target lets us set a 32-bit value (or 0xFFFFFFFF) on a packet, which we can then look for later with the mark match. This in itself can be useful, but where it gets really handy is adding the values together.
Starting out
To start off with, here’s an exampleSo what we have now are three chains, which do the following# Create a new chain, which will in effect be our source 'group' iptables -N S-TRUSTED # Add our sources iptables -A S-TRUSTED -s 192.168.1.1/32 -j MARK --set-xmark 0x8/0x0 iptables -A S-TRUSTED -s 192.168.2.0/24 -j MARK --set-xmark 0x8/0x0 iptables -A S-TRUSTED -s 192.168.3.3/29 -j MARK --set-xmark 0x8/0x0 # Create a chain for the destination group iptables -N D-DMZ # Add our DMZ machines iptables -A D-DMZ -d 10.1.1.1/32 -j MARK --set-xmark 0x4/0x0 iptables -A D-DMZ -d 10.1.2.0/24 -j MARK --set-xmark 0x4/0x0 # Create a chain for the services iptables -N D-SRV-MGMT # Add our service iptables -A D-SRV-MGMT -p tcp -m tcp --dport 22 -j MARK --set-xmark 0x2/0x0 iptables -A D-SRV-MGMT -p tcp -m tcp --dport 80 -j MARK --set-xmark 0x2/0x0
- If the source matches, add 0×8 to the packet mark
- If the destination matches, add 0×4 to the packet mark
- If the service matches, add 0×2 to the packet mark
Making the rule
Hopefully you’ll see where we’re going with this with the next example, which is our actual ruleAnd there we have it – if the packet matches the source, destination and service, the packet mark will be 0xE. If, say, it matches everything except the destination, it’ll come out as 0xC, which won’t match and so netfilter will carry on along the rest of the rules. If you want processing to stop here, you could always add a LOG and REJECT/DROP target at the end of the R-ALLOW-DMZ-MGMT chain.# Create a new chain for our rule and add it to our FORWARD chain iptables -N R-ALLOW-DMZ-MGMT iptables -A FORWARD -j R-ALLOW-DMZ-MGMT # Zero out the packet mark to make sure no previous rules interfere iptables -A R-ALLOW-DMZ-MGMT -j MARK --set-xmark 0x0/0x0 # Jump to our 'source group' chain iptables -A R-ALLOW-DMZ-MGMT -j S-TRUSTED # Jump to our 'destination group' chain iptables -A R-ALLOW-DMZ-MGMT -j D-DMZ # Jump to our 'service group' chain iptables -A R-ALLOW-DMZ-MGMT -j D-SRV-MGMT # If the packet mark matches 0xE, then ACCEPT iptables -A R-ALLOW-DMZ-MGMT -m mark --mark 0xE -j ACCEPT
Negation
Sometimes we want to be able to say ‘everything but that particular network’, whether it be for accepting or dropping packets. We can do that with this, tooTo use it, simply drop it in the R-ALLOW-DMZ-MGMT rule above after the jump to the S-TRUSTED chain, and if S-TRUSTED matched, it won’t any more, and vice versa. To negate the destination and service matches, you’ll need to create similar chains for (for example) D-NEGATE and D-SRV-NEGATE, replacing the 0×8 with 0×4 and 0×2 respectively.# Add a new chain for negating the source iptables -N S-NEGATE # XOR the current packet mark with 0x8 - our 'source match' identifier iptables -A S-NEGATE -j MARK --xor-mark 0x8
Things to note
One downside of this method is that because of the way IPTables works, if you want to use the same set of networks and hosts as a source and a destination, you’ll need to duplicate them, but match on the source or destination as appropriate. Using the example given above, if we wanted a group with the same entries as S-TRUSTED, but matching on traffic going to them, we’d need to create another group (for example, D-TRUSTED), which will be identical save for the IP matches (which will need changing to -d) and the mask (which will need setting to 0×4 instead of 0×8).Also, be careful if you’re using packet marks to do something outside of netfilter (say, for traffic control – which I’ll cover in a future post). One way round this is the facility to save the current packet mark to the current connection mark, or vice versa – if you go down this path then having a look at the iptables manpage for the MARK and CONNMARK targets will be useful.
Conclusions
This is an effective way of grouping hosts, networks and services within IPTables. It can be quite a bit of work to start with to add all the groups, but once in place it makes writing rules a lot more logical.Taking things further
One way which you could take this further would be to group interfaces together in a similar fashion, say by adding 0×10 to the packet, and then matching on 0x1E rather than 0xE.Usefully, if you send the packet out to syslog with the LOG target, netfilter will print out the current packet mark at the end of the log message as MARK=0xN, which can be useful when debugging.
Courtesy : http://andys.org.uk/bits/2010/01/27/iptables-fun-with-mark/