<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>bits &#124; andy smith&#039;s blog &#187; mark</title>
	<atom:link href="http://andys.org.uk/bits/tag/mark/feed/" rel="self" type="application/rss+xml" />
	<link>http://andys.org.uk/bits</link>
	<description>random stuff from the mind of a twenty-something professional geek</description>
	<lastBuildDate>Sat, 21 Jan 2012 18:36:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>IPTables: Fun with MARK</title>
		<link>http://andys.org.uk/bits/2010/01/27/iptables-fun-with-mark/</link>
		<comments>http://andys.org.uk/bits/2010/01/27/iptables-fun-with-mark/#comments</comments>
		<pubDate>Wed, 27 Jan 2010 13:52:45 +0000</pubDate>
		<dc:creator>Andy Smith</dc:creator>
				<category><![CDATA[IPTables/Netfilter]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[group]]></category>
		<category><![CDATA[iptables]]></category>
		<category><![CDATA[mark]]></category>
		<category><![CDATA[netfilter]]></category>

		<guid isPermaLink="false">http://andys.org.uk/bits/?p=10</guid>
		<description><![CDATA[One thing that&#8217;s always bugged me about IPTables is the lack of a way to use groups when writing rules, which can complicate things if you&#8217;ve got a potentially large rulebase. One way round this is to use something like fwbuilder, which gives you a graphical interface not unlike Checkpoint&#8216;s SmartDashboard GUI for their Firewall-1 [...]]]></description>
			<content:encoded><![CDATA[<p>One thing that&#8217;s always bugged me about <a href="http://www.netfilter.org">IPTables</a> is the lack of a way to use groups when writing rules, which can complicate things if you&#8217;ve got a potentially large rulebase. One way round this is to use something like <a href="http://www.fwbuilder.org">fwbuilder</a>, which gives you a graphical interface not unlike <a href="http://www.checkpoint.com/">Checkpoint</a>&#8216;s <a href="http://www.checkpoint.com/products/smartcenter/smartcenter_management.html">SmartDashboard</a> GUI for their Firewall-1 devices. The downside to this, though, is that the resulting IPTables ruleset is far from legible &#8211; which, to be fair, isn&#8217;t the goal of fwbuilder &#8211; and this makes hacking about with the rules nearly impossible.</p>
<p>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&#8217;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 <strong>MARK</strong> comes in.</p>
<p><span id="more-10"></span>The MARK target lets us set a 32-bit value (or 0xFFFFFFFF) on a packet, which we can then look for later with the <strong>mark</strong> match. This in itself can be useful, but where it gets really handy is adding the values together.</p>
<h3>Starting out</h3>
<p>To start off with, here&#8217;s an example</p>
<blockquote>
<pre># Create a new chain, which will in effect be our source 'group'
iptables -N <span style="color: #000080;">S-TRUSTED</span>
# Add our sources
iptables -A <span style="color: #000080;">S-TRUSTED</span> -s 192.168.1.1/32 -j MARK --set-xmark <span style="color: #008000;">0x8/0x0</span>
iptables -A <span style="color: #000080;">S-TRUSTED</span> -s 192.168.2.0/24 -j MARK --set-xmark <span style="color: #008000;">0x8/0x0</span>
iptables -A <span style="color: #000080;">S-TRUSTED</span> -s 192.168.3.3/29 -j MARK --set-xmark <span style="color: #008000;">0x8/0x0</span>

# Create a chain for the destination group
iptables -N <span style="color: #000080;">D-DMZ</span>
# Add our DMZ machines
iptables -A <span style="color: #000080;">D-DMZ</span> -d 10.1.1.1/32 -j MARK --set-xmark <span style="color: #008000;">0x4/0x0</span>
iptables -A <span style="color: #000080;">D-DMZ</span> -d 10.1.2.0/24 -j MARK --set-xmark <span style="color: #008000;">0x4/0x0</span>

# Create a chain for the services
iptables -N <span style="color: #000080;">D-SRV-MGMT</span>
# Add our service
iptables -A <span style="color: #000080;">D-SRV-MGMT</span> -p tcp -m tcp --dport 22 -j MARK --set-xmark <span style="color: #008000;">0x2/0x0</span>
iptables -A <span style="color: #000080;">D-SRV-MGMT</span> -p tcp -m tcp --dport 80 -j MARK --set-xmark <span style="color: #008000;">0x2/0x0</span></pre>
</blockquote>
<p>So what we have now are three chains, which do the following</p>
<ul>
<li>If the source matches, add <span style="color: #008000;"><strong>0&#215;8</strong></span> to the packet mark</li>
<li>If the destination matches, add <span style="color: #008000;"><strong>0&#215;4</strong></span> to the packet mark</li>
<li>If the service matches, add <span style="color: #008000;"><strong>0&#215;2</strong></span> to the packet mark</li>
</ul>
<p>If you know your hexadecimal, you&#8217;ll already know that if all of these are true, we&#8217;ll come out with <strong><span style="color: #008000;">0xE</span></strong> (or 14, in decimal).</p>
<h3>Making the rule</h3>
<p>Hopefully you&#8217;ll see where we&#8217;re going with this with the next example, which is our actual rule</p>
<blockquote>
<pre># Create a new chain for our rule and add it to our FORWARD chain
iptables -N <span style="color: #000080;">R-ALLOW-DMZ-MGMT</span>
iptables -A FORWARD -j <span style="color: #000080;">R-ALLOW-DMZ-MGMT</span>
# Zero out the packet mark to make sure no previous rules interfere
iptables -A <span style="color: #000080;">R-ALLOW-DMZ-MGMT</span> -j MARK --set-xmark <span style="color: #008000;">0x0/0x0</span>
# Jump to our 'source group' chain
iptables -A <span style="color: #000080;">R-ALLOW-DMZ-MGMT</span> -j <span style="color: #000080;">S-TRUSTED</span>
# Jump to our 'destination group' chain
iptables -A <span style="color: #000080;">R-ALLOW-DMZ-MGMT</span> -j <span style="color: #000080;">D-DMZ</span>
# Jump to our 'service group' chain
iptables -A <span style="color: #000080;">R-ALLOW-DMZ-MGMT</span> -j <span style="color: #000080;">D-SRV-MGMT</span>
# If the packet mark matches <strong><span style="color: #008000;">0xE</span></strong>, then ACCEPT
iptables -A <span style="color: #000080;">R-ALLOW-DMZ-MGMT</span> -m mark --mark <span style="color: #008000;">0xE</span> -j <span style="color: #000080;">ACCEPT</span></pre>
</blockquote>
<p>And there we have it &#8211; if the packet matches the source, destination and service, the packet mark will be <strong><span style="color: #008000;">0xE</span></strong>. If, say, it matches everything except the destination, it&#8217;ll come out as <strong><span style="color: #008000;">0xC</span></strong>, which won&#8217;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 <strong>LOG</strong> and <strong>REJECT</strong>/<strong>DROP</strong> target at the end of the <strong><span style="color: #000080;">R-ALLOW-DMZ-MGMT</span></strong> chain.</p>
<h3>Negation</h3>
<p>Sometimes we want to be able to say &#8216;everything but that particular network&#8217;, whether it be for accepting or dropping packets. We can do that with this, too</p>
<blockquote>
<pre># Add a new chain for negating the source
iptables -N <span style="color: #000080;">S-NEGATE</span>
# XOR the current packet mark with <strong><span style="color: #008000;">0x8</span></strong> - our 'source match' identifier
iptables -A <span style="color: #000080;">S-NEGATE</span> -j MARK --xor-mark <span style="color: #008000;">0x8</span></pre>
</blockquote>
<p>To use it, simply drop it in the <strong><span style="color: #000080;">R-ALLOW-DMZ-MGMT</span></strong> rule above after the jump to the <strong><span style="color: #000080;">S-TRUSTED</span></strong> chain, and if <span style="color: #000080;"><strong>S-TRUSTED</strong></span> matched, it won&#8217;t any more, and vice versa. To negate the destination and service matches, you&#8217;ll need to create similar chains for (for example) <strong><span style="color: #000080;">D-NEGATE</span></strong> and <strong><span style="color: #000080;">D-SRV-NEGATE</span></strong>, replacing the <strong><span style="color: #008000;">0&#215;8</span></strong> with <strong><span style="color: #008000;">0&#215;4</span></strong> and <strong><span style="color: #008000;">0&#215;2</span></strong> respectively.</p>
<h3>Things to note</h3>
<p>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&#8217;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 <strong><span style="color: #000080;">S-TRUSTED</span></strong>, but matching on traffic going to them, we&#8217;d need to create another group (for example, <strong><span style="color: #000080;">D-TRUSTED</span></strong>), which will be identical save for the IP matches (which will need changing to <strong>-d</strong>) and the mask (which will need setting to <strong><span style="color: #008000;">0&#215;4</span></strong> instead of <strong><span style="color: #008000;">0&#215;8</span></strong>).</p>
<p>Also, be careful if you&#8217;re using packet marks to do something outside of netfilter (say, for <a href="http://lartc.org/">traffic control</a> &#8211; which I&#8217;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 &#8211; if you go down this path then having a look at the iptables manpage for the MARK and CONNMARK targets will be useful.</p>
<h3>Conclusions</h3>
<p>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.</p>
<h3>Taking things further</h3>
<p>One way which you could take this further would be to group interfaces together in a similar fashion, say by adding <strong><span style="color: #008000;">0&#215;10</span></strong> to the packet, and then matching on <strong><span style="color: #008000;">0x1E</span></strong> rather than <strong><span style="color: #008000;">0xE</span></strong>.</p>
<p>Usefully, if you send the packet out to syslog with the <strong><span style="color: #000080;">LOG</span></strong> target, netfilter will print out the current packet mark at the end of the log message as <strong><span style="color: #ff0000;">MARK=0xN</span></strong>, which can be useful when debugging.</p>
]]></content:encoded>
			<wfw:commentRss>http://andys.org.uk/bits/2010/01/27/iptables-fun-with-mark/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

