<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Michael Gorven - cocooncrash</title>
  <link rel="alternate" type="text/html" href="http://michael.gorven.za.net/blog/2008/08/15/routing-port-number"/>
  <link rel="self" type="application/atom+xml" href="http://michael.gorven.za.net/node/44/atom/feed"/>
  <id>http://michael.gorven.za.net/node/44/atom/feed</id>
  <updated>2008-08-15T12:35:10+02:00</updated>
  <entry>
    <title>Routing by port number</title>
    <link rel="alternate" type="text/html" href="http://michael.gorven.za.net/blog/2008/08/15/routing-port-number" />
    <id>http://michael.gorven.za.net/blog/2008/08/15/routing-port-number</id>
    <published>2008-08-15T12:35:10+02:00</published>
    <updated>2008-08-15T12:35:10+02:00</updated>
    <author>
      <name>mgorven</name>
    </author>
    <category term="iptables" />
    <category term="linux" />
    <category term="openvpn" />
    <category term="routing" />
    <category term="technical" />
    <category term="ubuntu" />
    <summary type="html"><![CDATA[<p>Due to a very restrictive firewall at the <a href="http://www.chpc.ac.za/"><abbr title="Centre for High Performance Computing">CHPC</abbr></a>, I need to run a <a href="http://en.wikipedia.org/wiki/Virtual_private_network"><abbr title="Virtual Private Network">VPN</abbr></a> to get
access to things like email, <a href="http://en.wikipedia.org/wiki/Extensible_Messaging_and_Presence_Protocol">Jabber</a> and <a href="http://en.wikipedia.org/wiki/Secure_Shell"><abbr title="Secure Shell">SSH</abbr></a>. This however degrades my web
browsing experience, since that gets tunnelled as well. I therefore wanted a
setup where only ports which are blocked get tunnelled through the <abbr title="Virtual Private Network">VPN</abbr>, while
everything else goes out normally.</p>

<p>The routing part was fairly straightforward, which consists of an <a href="http://en.wikipedia.org/wiki/Iptables">iptables</a>
rule to mark certain packets, and an alternate routing table for these marked
packets. I first created a name for the new table by adding the following to
<span class="geshifilter"><code class="geshifilter-text">/etc/iproute2/rt_tables</code></span>.</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">10  vpn</pre></div></pre></p>

<p>I then added a default route to the new table specifying the IP address of the
<abbr title="Virtual Private Network">VPN</abbr> server and the <abbr title="Virtual Private Network">VPN</abbr> interface, and a rule to use this table for packets
marked by iptables.</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">ip route add default via 10.8.0.3 dev tun0 table vpn
ip rule add fwmark 0x1 table vpn</pre></div></pre></p>

<p>The following iptables rule will mark packets destined to the listed port
numbers. Note that this is for packets originating from the firewall host — if
you want this to apply to packets forwarded for other hosts it must be in the
<span class="geshifilter"><code class="geshifilter-text">PREROUTING</code></span> chain.</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">iptables -t mangle -A OUTPUT -p tcp -m multiport --dports 22,995,587,5223 -j MARK --set-mark 0x1</pre></div></pre></p>

<p>The actual routing worked, but packets were being sent with the wrong source IP.
I therefore needed to NAT packets going out on the <abbr title="Virtual Private Network">VPN</abbr> interface (the IP address
is the local IP of the <abbr title="Virtual Private Network">VPN</abbr> connection).</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">iptables -t nat -A POSTROUTING -o tun0 -j SNAT --to 10.8.0.4</pre></div></pre></p>

<p>I could then see packets going out on the <abbr title="Virtual Private Network">VPN</abbr> interface with the correct source
IP as well as the replies, but it still wasn't working. I eventually discovered
that <span class="geshifilter"><code class="geshifilter-text">rp_filter</code></span> must be disabled in order for this to work.</p>

<p><pre><div class="geshifilter"><pre class="geshifilter-text">echo 0 &amp;gt; /proc/sys/net/ipv4/conf/tun0/rp_filter</pre></div></pre></p>
    ]]></summary>
    <content type="html"><![CDATA[<p>Due to a very restrictive firewall at the <a href="http://www.chpc.ac.za/"><abbr title="Centre for High Performance Computing">CHPC</abbr></a>, I need to run a <a href="http://en.wikipedia.org/wiki/Virtual_private_network"><abbr title="Virtual Private Network">VPN</abbr></a> to get
access to things like email, <a href="http://en.wikipedia.org/wiki/Extensible_Messaging_and_Presence_Protocol">Jabber</a> and <a href="http://en.wikipedia.org/wiki/Secure_Shell"><abbr title="Secure Shell">SSH</abbr></a>. This however degrades my web
browsing experience, since that gets tunnelled as well. I therefore wanted a
setup where only ports which are blocked get tunnelled through the <abbr title="Virtual Private Network">VPN</abbr>, while
everything else goes out normally.</p>

<p>The routing part was fairly straightforward, which consists of an <a href="http://en.wikipedia.org/wiki/Iptables">iptables</a>
rule to mark certain packets, and an alternate routing table for these marked
packets. I first created a name for the new table by adding the following to
<code>/etc/iproute2/rt_tables</code>.</p>

<pre><code>10  vpn
</code></pre>

<p>I then added a default route to the new table specifying the IP address of the
<abbr title="Virtual Private Network">VPN</abbr> server and the <abbr title="Virtual Private Network">VPN</abbr> interface, and a rule to use this table for packets
marked by iptables.</p>

<pre><code>ip route add default via 10.8.0.3 dev tun0 table vpn
ip rule add fwmark 0x1 table vpn
</code></pre>

<p>The following iptables rule will mark packets destined to the listed port
numbers. Note that this is for packets originating from the firewall host — if
you want this to apply to packets forwarded for other hosts it must be in the
<code>PREROUTING</code> chain.</p>

<pre><code>iptables -t mangle -A OUTPUT -p tcp -m multiport --dports 22,995,587,5223 -j MARK --set-mark 0x1
</code></pre>

<p>The actual routing worked, but packets were being sent with the wrong source IP.
I therefore needed to NAT packets going out on the <abbr title="Virtual Private Network">VPN</abbr> interface (the IP address
is the local IP of the <abbr title="Virtual Private Network">VPN</abbr> connection).</p>

<pre><code>iptables -t nat -A POSTROUTING -o tun0 -j SNAT --to 10.8.0.4
</code></pre>

<p>I could then see packets going out on the <abbr title="Virtual Private Network">VPN</abbr> interface with the correct source
IP as well as the replies, but it still wasn't working. I eventually discovered
that <code>rp_filter</code> must be disabled in order for this to work.</p>

<pre><code>echo 0 &gt; /proc/sys/net/ipv4/conf/tun0/rp_filter
</code></pre>
    ]]></content>
  </entry>
</feed>
