<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Tumbleweed Rants</title>
  <subtitle>Stefano's World</subtitle>
  <link rel="alternate" type="text/html" href="http://tumbleweed.org.za/2007/09/01/local-only-dsl"/>
  <link rel="self" type="application/atom+xml" href="http://tumbleweed.org.za/node/87/atom/feed"/>
  <id>http://tumbleweed.org.za/node/87/atom/feed</id>
  <updated>2008-12-12T21:35:57+00:00</updated>
  <entry>
    <title>Local only DSL</title>
    <link rel="alternate" type="text/html" href="http://tumbleweed.org.za/2007/09/01/local-only-dsl" />
    <id>http://tumbleweed.org.za/2007/09/01/local-only-dsl</id>
    <published>2007-09-01T21:06:15+00:00</published>
    <updated>2008-12-12T21:35:57+00:00</updated>
    <author>
      <name>tumbleweed</name>
    </author>
    <category term="internet" />
    <category term="linux" />
    <category term="openwrt" />
    <category term="split-routing" />
    <summary type="html"><![CDATA[<p><strong>Update</strong>: <a href="/2008/09/19/split-routing-debianubuntu">Debian/Ubuntu version</a></p>

<p>I've finally jumped onto the local only DSL bandwagon. If you haven't done it yet, it's a great way to save some bucks. The idea is that you get a local only account like <a href="http://www.webafrica.co.za/adsl/is_local/">this</a>, which costs a fraction per GiB compared to normal account. Then you get your router to connect to both simultaneously, and route intelligently between them.</p>

<p>Most ADSL routers won't let you connect 2 concurrent ADSL connections on the same ATM circuit. The solution is to use a separate modem and router. I'm using a basic Billion modem, in bridged mode, and a WRT54GL, running <a href="http://www.openwrt.org/">OpenWRT/kamikaze</a>, as the router.</p>

<p>OpenWRT doesn't support 2 PPPoE connections out of the box, but I've found the problems, and got a few changes committed upstream, that solve them:</p>

<ul>
<li>Configurable default route: <a href="https://dev.openwrt.org/changeset/8569">changeset 8569</a></li>
<li>Allow specifying ppp unit numbers: <a href="https://dev.openwrt.org/changeset?new=trunk%408564&amp;old=trunk%408562">changeset 8563+8564</a></li>
<li>Support for multiple interfaces in UpdateDD (a DynDNS client): <a href="https://dev.openwrt.org/ticket/2294">bug 2294</a></li>
</ul>

<p>The firewall (<span class="geshifilter"><code class="geshifilter-text">/etc/init.d/firewall</code></span>) needs to be modified with "WAN=ppp+" somewhere near the top, so that it masquerades <em>all</em> the ppp connections. This was a hack, apparently the firewall is being re-written soon.</p>

<p>There is also a bug that resets existing PPPoE connections on a ethernet interface when you fire up a new connection. This will apparently be fixed by the future interface aliasing support. For now, I just hacked around it in <span class="geshifilter"><code class="geshifilter-text">/lib/network/config.sh</code></span>:</p>

<div class="geshifilter"><div class="bash geshifilter-bash" style="font-family:monospace;">prepare_interface<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">iface</span>=<span class="st0">&quot;$1&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">config</span>=<span class="st0">&quot;$2&quot;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co0">#SR: We don't want to reset any pppoe connections</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; config_get proto <span class="st0">&quot;<span class="es2">$config</span>&quot;</span> proto<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#91;</span> <span class="st0">&quot;<span class="es2">$proto</span>&quot;</span> = <span class="st0">&quot;pppoe&quot;</span> <span class="br0">&#93;</span> <span class="sy0">&amp;&amp;</span> <span class="kw3">return</span> <span class="nu0">0</span></div></div>

<p>and <span class="geshifilter"><code class="geshifilter-text">/sbin/ifdown</code></span>:</p>

<div class="geshifilter"><div class="bash geshifilter-bash" style="font-family:monospace;">config_get ifname <span class="st0">&quot;<span class="es2">$cfg</span>&quot;</span> ifname<br />
config_get device <span class="st0">&quot;<span class="es2">$cfg</span>&quot;</span> device<br />
<br />
<span class="br0">&#91;</span> .<span class="st0">&quot;<span class="es3">${proto%oe}</span>&quot;</span> == .<span class="st0">&quot;ppp&quot;</span> <span class="br0">&#93;</span> <span class="sy0">&amp;&amp;</span> <span class="re2">device</span>=<br />
<span class="br0">&#91;</span> .<span class="st0">&quot;<span class="es2">$device</span>&quot;</span> <span class="sy0">!</span>= .<span class="st0">&quot;<span class="es2">$ifname</span>&quot;</span> <span class="br0">&#93;</span> <span class="sy0">||</span> <span class="re2">device</span>=<br />
<span class="kw1">for</span> dev <span class="kw1">in</span> <span class="re1">$ifname</span> <span class="re1">$device</span>; <span class="kw1">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">ifconfig</span> <span class="st0">&quot;<span class="es2">$dev</span>&quot;</span> 0.0.0.0 down <span class="sy0">&gt;/</span>dev<span class="sy0">/</span>null <span class="nu0">2</span><span class="sy0">&gt;/</span>dev<span class="sy0">/</span>null<br />
<span class="kw1">done</span></div></div>

<p>I got my local routes list from <a href="http://alm.za.net/ip/localroutes4.txt">alm.za.net</a>, saved it as a list in CDIR format. OpenWRT already has a static routing configuration system, but it's very verbose. So I wrote my own, adding the new configuration option <span class="geshifilter"><code class="geshifilter-text">routefile</code></span>. I used these hotplug scripts to set up routing and source routing, with the help of iproute2:</p>

<div class="geshifilter"><div class="text geshifilter-text" style="font-family:monospace;">$ ipkg install ip<br />
<br />
$ mkdir /etc/localroutes<br />
$ wget http://alm.za.net/ip/localroutes4.txt -O - | awk '{print $4}' &gt; /etc/routes/zaroutes</div></div>

<p><span class="geshifilter"><code class="geshifilter-text">/etc/config/network</code></span>:</p>

<div class="geshifilter"><div class="text geshifilter-text" style="font-family:monospace;"># ...local interfaces...<br />
<br />
#### WAN configuration<br />
config interface &nbsp; &nbsp;wan<br />
&nbsp; &nbsp; &nbsp; &nbsp; option ifname &nbsp; &quot;eth0.1&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; option proto &nbsp; &nbsp;pppoe<br />
&nbsp; &nbsp; &nbsp; &nbsp; option username &quot;xxxxx@international.co.za&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; option password &quot;xxxxxx&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; option routefile &quot;/etc/routes/exceptions&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; option defaultroute 1<br />
<br />
config interface &nbsp; &nbsp;localdsl<br />
&nbsp; &nbsp; &nbsp; &nbsp; option ifname &nbsp; &quot;eth0.1&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; option proto &nbsp; &nbsp;pppoe<br />
&nbsp; &nbsp; &nbsp; &nbsp; option username &quot;xxxxx@local.co.za&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; option password &quot;xxxxxx&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; option routefile &quot;/etc/routes/zaroutes&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; option defaultroute 0</div></div>

<p><span class="geshifilter"><code class="geshifilter-text">/etc/iproute2/rt_tables</code></span>:</p>

<div class="geshifilter"><div class="text geshifilter-text" style="font-family:monospace;">#<br />
# reserved values<br />
#<br />
255 &nbsp; &nbsp; local<br />
254 &nbsp; &nbsp; main<br />
253 &nbsp; &nbsp; default<br />
0 &nbsp; &nbsp; &nbsp; unspec<br />
#<br />
# local<br />
#<br />
1 &nbsp; wan<br />
2 &nbsp; localdsl</div></div>

<p><span class="geshifilter"><code class="geshifilter-text">/etc/hotplug.d/iface/20-split-routes</code></span>:</p>

<div class="geshifilter"><div class="bash geshifilter-bash" style="font-family:monospace;"><span class="kw1">case</span> <span class="st0">&quot;<span class="es2">$ACTION</span>&quot;</span> <span class="kw1">in</span><br />
&nbsp; ifup<span class="br0">&#41;</span><br />
&nbsp; &nbsp; . <span class="sy0">/</span>etc<span class="sy0">/</span>functions.sh<br />
&nbsp; &nbsp; include <span class="sy0">/</span>lib<span class="sy0">/</span>network<br />
&nbsp; &nbsp; scan_interfaces<br />
&nbsp; &nbsp; config_get routefile <span class="st0">&quot;<span class="es2">$INTERFACE</span>&quot;</span> routefile<br />
<br />
&nbsp; &nbsp; <span class="co0"># Does this interface have custom routes?</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#91;</span> <span class="re5">-e</span> <span class="st0">&quot;<span class="es2">$routefile</span>&quot;</span> <span class="br0">&#93;</span>; <span class="kw1">then</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span class="co0"># Add routes for this interface</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw2">cat</span> <span class="st0">&quot;<span class="es2">$routefile</span>&quot;</span> <span class="sy0">|</span> <span class="kw1">while</span> <span class="kw2">read</span> route; <span class="kw1">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ip route add <span class="st0">&quot;<span class="es2">$route</span>&quot;</span> dev <span class="st0">&quot;<span class="es2">$DEVICE</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">done</span> &nbsp;<br />
<br />
&nbsp; &nbsp; &nbsp; <span class="co0"># Set up source routing</span><br />
&nbsp; &nbsp; &nbsp; <span class="re2">peer</span>=<span class="sy0">`</span>ip addr show dev <span class="re1">$DEVICE</span> <span class="sy0">|</span> <span class="kw2">sed</span> <span class="re5">-n</span> <span class="st_h">'/inet/ s#.* peer \([0-9.]*\)/.*#\1# p'</span><span class="sy0">`</span><br />
&nbsp; &nbsp; &nbsp; <span class="re2">address</span>=<span class="sy0">`</span>ip addr show dev <span class="re1">$DEVICE</span> <span class="sy0">|</span> <span class="kw2">sed</span> <span class="re5">-n</span> <span class="st_h">'/inet/ s/.* inet \([0-9.]*\) .*/\1/ p'</span><span class="sy0">`</span><br />
<br />
&nbsp; &nbsp; &nbsp; ip route add <span class="st0">&quot;<span class="es2">$peer</span>&quot;</span> dev <span class="st0">&quot;<span class="es2">$DEVICE</span>&quot;</span> src <span class="st0">&quot;<span class="es2">$address</span>&quot;</span> table <span class="st0">&quot;<span class="es2">$INTERFACE</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; ip route add default via <span class="st0">&quot;<span class="es2">$peer</span>&quot;</span> table <span class="st0">&quot;<span class="es2">$INTERFACE</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; ip rule add from <span class="st0">&quot;<span class="es2">$address</span>&quot;</span> table <span class="st0">&quot;<span class="es2">$INTERFACE</span>&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">fi</span><br />
<br />
&nbsp; &nbsp; <span class="co0"># Make sure this interface is present in all the custom routing tables:</span><br />
&nbsp; &nbsp; <span class="re2">route</span>=<span class="sy0">`</span>ip route show dev <span class="st0">&quot;<span class="es2">$DEVICE</span>&quot;</span> <span class="sy0">|</span> <span class="kw2">awk</span> <span class="st_h">'/scope link &nbsp;src/ {print $1}'</span><span class="sy0">`</span><br />
&nbsp; &nbsp; <span class="kw2">awk</span> <span class="st_h">'/^[0-9]/ {if ($1 &gt; 0 &amp;&amp; $1 &lt; 250) print $2}'</span> <span class="sy0">/</span>etc<span class="sy0">/</span>iproute2<span class="sy0">/</span>rt_tables <span class="sy0">|</span> <span class="kw1">while</span> <span class="kw2">read</span> table; <span class="kw1">do</span><br />
&nbsp; &nbsp; &nbsp; ip route add <span class="st0">&quot;<span class="es2">$route</span>&quot;</span> dev <span class="st0">&quot;<span class="es2">$DEVICE</span>&quot;</span> table <span class="st0">&quot;<span class="es2">$table</span>&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">done</span><br />
&nbsp; &nbsp; <span class="sy0">;;</span><br />
<span class="kw1">esac</span></div></div>

<p><span class="geshifilter"><code class="geshifilter-text">/etc/hotplug.d/net/20-split-routes</code></span>:</p>

<div class="geshifilter"><div class="bash geshifilter-bash" style="font-family:monospace;"><span class="kw1">case</span> <span class="st0">&quot;<span class="es2">$ACTION</span>&quot;</span> <span class="kw1">in</span><br />
&nbsp; register<span class="br0">&#41;</span><br />
&nbsp; &nbsp; . <span class="sy0">/</span>etc<span class="sy0">/</span>functions.sh<br />
&nbsp; &nbsp; include <span class="sy0">/</span>lib<span class="sy0">/</span>network<br />
&nbsp; &nbsp; scan_interfaces<br />
<br />
&nbsp; &nbsp; <span class="co0"># If this interface doesn't have a link local route, we don't need to bother</span><br />
&nbsp; &nbsp; <span class="re2">route</span>=<span class="sy0">`</span>ip route show dev <span class="st0">&quot;<span class="es2">$INTERFACE</span>&quot;</span> <span class="sy0">|</span> <span class="kw2">awk</span> <span class="st_h">'/scope link &nbsp;src/ {print $1}'</span><span class="sy0">`</span><br />
&nbsp; &nbsp; <span class="br0">&#91;</span> .<span class="st0">&quot;<span class="es2">$route</span>&quot;</span> = .<span class="st0">&quot;&quot;</span> <span class="br0">&#93;</span> <span class="sy0">&amp;&amp;</span> <span class="kw3">return</span> <span class="nu0">0</span><br />
<br />
&nbsp; &nbsp; <span class="co0"># Add this interface's route to all custom routing tables</span><br />
&nbsp; &nbsp; <span class="kw2">awk</span> <span class="st_h">'/^[0-9]/ {if ($1 &gt; 0 &amp;&amp; $1 &lt; 250) print $2}'</span> <span class="sy0">/</span>etc<span class="sy0">/</span>iproute2<span class="sy0">/</span>rt_tables <span class="sy0">|</span> <span class="kw1">while</span> <span class="kw2">read</span> table; <span class="kw1">do</span><br />
&nbsp; &nbsp; &nbsp; ip route add <span class="st0">&quot;<span class="es2">$route</span>&quot;</span> dev <span class="st0">&quot;<span class="es2">$INTERFACE</span>&quot;</span> table <span class="st0">&quot;<span class="es2">$table</span>&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">done</span><br />
&nbsp; &nbsp; <span class="sy0">;;</span><br />
<span class="kw1">esac</span></div></div>

<p>Now, lastly, it won't bring up both interfaces by default. That will be fixed by aliasing in the future, but for now:</p>

<p><span class="geshifilter"><code class="geshifilter-text">/etc/init.d/network-multiwan</code></span>:</p>

<div class="geshifilter"><div class="bash geshifilter-bash" style="font-family:monospace;"><span class="co0">#!/bin/sh</span><br />
ifup wan<br />
ifup localdsl</div></div>

<div class="geshifilter"><div class="text geshifilter-text" style="font-family:monospace;">$ chmod 755 /etc/init.d/network-multiwan<br />
$ ln -s ../init.d/network-multiwan /etc/rc.d/S49network-multiwan</div></div>

<p>That's it, and it's working beautifully :-)</p>

<p>What is source routing, people ask? The problem is that your router now has 2 WAN IP addresses. IP1 is used for local traffic, and IP2 for international. So if somebody in ZA tries to connect to IP2, the reply (local destination) will go out of Interface 1. The ISP on the other end of Interface 1 will drop this reply, because it's not coming from IP1.</p>

<p>Source routing tells the router that replies must go out of the same interface that the request came in on. I'm doing it by creating separate routing tables for traffic origionating from each WAN interface.</p>

<h2>Gotchas</h2>

<ul>
<li>If you are using 2 different ISPs (say SAIX international and IS local), you must make sure that DNS queries get routed out the right interface. SAIX won't accept queries on their servers from IS, and vice versa.</li>
<li>SAIX Web proxies, Mail servers, and News servers don't accept traffic from local accounts. (especially from another ISP)</li>
</ul>
    ]]></summary>
    <content type="html"><![CDATA[<p><strong>Update</strong>: <a href="/2008/09/19/split-routing-debianubuntu">Debian/Ubuntu version</a></p>

<p>I've finally jumped onto the local only DSL bandwagon. If you haven't done it yet, it's a great way to save some bucks. The idea is that you get a local only account like <a href="http://www.webafrica.co.za/adsl/is_local/">this</a>, which costs a fraction per GiB compared to normal account. Then you get your router to connect to both simultaneously, and route intelligently between them.</p>

<p>Most ADSL routers won't let you connect 2 concurrent ADSL connections on the same ATM circuit. The solution is to use a separate modem and router. I'm using a basic Billion modem, in bridged mode, and a WRT54GL, running <a href="http://www.openwrt.org/">OpenWRT/kamikaze</a>, as the router.</p>

<p>OpenWRT doesn't support 2 PPPoE connections out of the box, but I've found the problems, and got a few changes committed upstream, that solve them:</p>

<ul>
<li>Configurable default route: <a href="https://dev.openwrt.org/changeset/8569">changeset 8569</a></li>
<li>Allow specifying ppp unit numbers: <a href="https://dev.openwrt.org/changeset?new=trunk%408564&amp;old=trunk%408562">changeset 8563+8564</a></li>
<li>Support for multiple interfaces in UpdateDD (a DynDNS client): <a href="https://dev.openwrt.org/ticket/2294">bug 2294</a></li>
</ul>

<p>The firewall (<code>/etc/init.d/firewall</code>) needs to be modified with "WAN=ppp+" somewhere near the top, so that it masquerades <em>all</em> the ppp connections. This was a hack, apparently the firewall is being re-written soon.</p>

<p>There is also a bug that resets existing PPPoE connections on a ethernet interface when you fire up a new connection. This will apparently be fixed by the future interface aliasing support. For now, I just hacked around it in <code>/lib/network/config.sh</code>:</p>

<div class="geshifilter"><div class="bash geshifilter-bash" style="font-family:monospace;">prepare_interface<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">iface</span>=<span class="st0">&quot;$1&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">local</span> <span class="re2">config</span>=<span class="st0">&quot;$2&quot;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co0">#SR: We don't want to reset any pppoe connections</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; config_get proto <span class="st0">&quot;<span class="es2">$config</span>&quot;</span> proto<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#91;</span> <span class="st0">&quot;<span class="es2">$proto</span>&quot;</span> = <span class="st0">&quot;pppoe&quot;</span> <span class="br0">&#93;</span> <span class="sy0">&amp;&amp;</span> <span class="kw3">return</span> <span class="nu0">0</span></div></div>

<p>and <code>/sbin/ifdown</code>:</p>

<div class="geshifilter"><div class="bash geshifilter-bash" style="font-family:monospace;">config_get ifname <span class="st0">&quot;<span class="es2">$cfg</span>&quot;</span> ifname<br />
config_get device <span class="st0">&quot;<span class="es2">$cfg</span>&quot;</span> device<br />
<br />
<span class="br0">&#91;</span> .<span class="st0">&quot;<span class="es3">${proto%oe}</span>&quot;</span> == .<span class="st0">&quot;ppp&quot;</span> <span class="br0">&#93;</span> <span class="sy0">&amp;&amp;</span> <span class="re2">device</span>=<br />
<span class="br0">&#91;</span> .<span class="st0">&quot;<span class="es2">$device</span>&quot;</span> <span class="sy0">!</span>= .<span class="st0">&quot;<span class="es2">$ifname</span>&quot;</span> <span class="br0">&#93;</span> <span class="sy0">||</span> <span class="re2">device</span>=<br />
<span class="kw1">for</span> dev <span class="kw1">in</span> <span class="re1">$ifname</span> <span class="re1">$device</span>; <span class="kw1">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">ifconfig</span> <span class="st0">&quot;<span class="es2">$dev</span>&quot;</span> 0.0.0.0 down <span class="sy0">&gt;/</span>dev<span class="sy0">/</span>null <span class="nu0">2</span><span class="sy0">&gt;/</span>dev<span class="sy0">/</span>null<br />
<span class="kw1">done</span></div></div>

<p>I got my local routes list from <a href="http://alm.za.net/ip/localroutes4.txt">alm.za.net</a>, saved it as a list in CDIR format. OpenWRT already has a static routing configuration system, but it's very verbose. So I wrote my own, adding the new configuration option <code>routefile</code>. I used these hotplug scripts to set up routing and source routing, with the help of iproute2:</p>

<div class="geshifilter"><div class="text geshifilter-text" style="font-family:monospace;">$ ipkg install ip<br />
<br />
$ mkdir /etc/localroutes<br />
$ wget http://alm.za.net/ip/localroutes4.txt -O - | awk '{print $4}' &gt; /etc/routes/zaroutes</div></div>

<p><code>/etc/config/network</code>:</p>

<div class="geshifilter"><div class="text geshifilter-text" style="font-family:monospace;"># ...local interfaces...<br />
<br />
#### WAN configuration<br />
config interface &nbsp; &nbsp;wan<br />
&nbsp; &nbsp; &nbsp; &nbsp; option ifname &nbsp; &quot;eth0.1&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; option proto &nbsp; &nbsp;pppoe<br />
&nbsp; &nbsp; &nbsp; &nbsp; option username &quot;xxxxx@international.co.za&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; option password &quot;xxxxxx&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; option routefile &quot;/etc/routes/exceptions&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; option defaultroute 1<br />
<br />
config interface &nbsp; &nbsp;localdsl<br />
&nbsp; &nbsp; &nbsp; &nbsp; option ifname &nbsp; &quot;eth0.1&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; option proto &nbsp; &nbsp;pppoe<br />
&nbsp; &nbsp; &nbsp; &nbsp; option username &quot;xxxxx@local.co.za&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; option password &quot;xxxxxx&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; option routefile &quot;/etc/routes/zaroutes&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; option defaultroute 0</div></div>

<p><code>/etc/iproute2/rt_tables</code>:</p>

<div class="geshifilter"><div class="text geshifilter-text" style="font-family:monospace;">#<br />
# reserved values<br />
#<br />
255 &nbsp; &nbsp; local<br />
254 &nbsp; &nbsp; main<br />
253 &nbsp; &nbsp; default<br />
0 &nbsp; &nbsp; &nbsp; unspec<br />
#<br />
# local<br />
#<br />
1 &nbsp; wan<br />
2 &nbsp; localdsl</div></div>

<p><code>/etc/hotplug.d/iface/20-split-routes</code>:</p>

<div class="geshifilter"><div class="bash geshifilter-bash" style="font-family:monospace;"><span class="kw1">case</span> <span class="st0">&quot;<span class="es2">$ACTION</span>&quot;</span> <span class="kw1">in</span><br />
&nbsp; ifup<span class="br0">&#41;</span><br />
&nbsp; &nbsp; . <span class="sy0">/</span>etc<span class="sy0">/</span>functions.sh<br />
&nbsp; &nbsp; include <span class="sy0">/</span>lib<span class="sy0">/</span>network<br />
&nbsp; &nbsp; scan_interfaces<br />
&nbsp; &nbsp; config_get routefile <span class="st0">&quot;<span class="es2">$INTERFACE</span>&quot;</span> routefile<br />
<br />
&nbsp; &nbsp; <span class="co0"># Does this interface have custom routes?</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#91;</span> <span class="re5">-e</span> <span class="st0">&quot;<span class="es2">$routefile</span>&quot;</span> <span class="br0">&#93;</span>; <span class="kw1">then</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span class="co0"># Add routes for this interface</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw2">cat</span> <span class="st0">&quot;<span class="es2">$routefile</span>&quot;</span> <span class="sy0">|</span> <span class="kw1">while</span> <span class="kw2">read</span> route; <span class="kw1">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ip route add <span class="st0">&quot;<span class="es2">$route</span>&quot;</span> dev <span class="st0">&quot;<span class="es2">$DEVICE</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">done</span> &nbsp;<br />
<br />
&nbsp; &nbsp; &nbsp; <span class="co0"># Set up source routing</span><br />
&nbsp; &nbsp; &nbsp; <span class="re2">peer</span>=<span class="sy0">`</span>ip addr show dev <span class="re1">$DEVICE</span> <span class="sy0">|</span> <span class="kw2">sed</span> <span class="re5">-n</span> <span class="st_h">'/inet/ s#.* peer \([0-9.]*\)/.*#\1# p'</span><span class="sy0">`</span><br />
&nbsp; &nbsp; &nbsp; <span class="re2">address</span>=<span class="sy0">`</span>ip addr show dev <span class="re1">$DEVICE</span> <span class="sy0">|</span> <span class="kw2">sed</span> <span class="re5">-n</span> <span class="st_h">'/inet/ s/.* inet \([0-9.]*\) .*/\1/ p'</span><span class="sy0">`</span><br />
<br />
&nbsp; &nbsp; &nbsp; ip route add <span class="st0">&quot;<span class="es2">$peer</span>&quot;</span> dev <span class="st0">&quot;<span class="es2">$DEVICE</span>&quot;</span> src <span class="st0">&quot;<span class="es2">$address</span>&quot;</span> table <span class="st0">&quot;<span class="es2">$INTERFACE</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; ip route add default via <span class="st0">&quot;<span class="es2">$peer</span>&quot;</span> table <span class="st0">&quot;<span class="es2">$INTERFACE</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; ip rule add from <span class="st0">&quot;<span class="es2">$address</span>&quot;</span> table <span class="st0">&quot;<span class="es2">$INTERFACE</span>&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">fi</span><br />
<br />
&nbsp; &nbsp; <span class="co0"># Make sure this interface is present in all the custom routing tables:</span><br />
&nbsp; &nbsp; <span class="re2">route</span>=<span class="sy0">`</span>ip route show dev <span class="st0">&quot;<span class="es2">$DEVICE</span>&quot;</span> <span class="sy0">|</span> <span class="kw2">awk</span> <span class="st_h">'/scope link &nbsp;src/ {print $1}'</span><span class="sy0">`</span><br />
&nbsp; &nbsp; <span class="kw2">awk</span> <span class="st_h">'/^[0-9]/ {if ($1 &gt; 0 &amp;&amp; $1 &lt; 250) print $2}'</span> <span class="sy0">/</span>etc<span class="sy0">/</span>iproute2<span class="sy0">/</span>rt_tables <span class="sy0">|</span> <span class="kw1">while</span> <span class="kw2">read</span> table; <span class="kw1">do</span><br />
&nbsp; &nbsp; &nbsp; ip route add <span class="st0">&quot;<span class="es2">$route</span>&quot;</span> dev <span class="st0">&quot;<span class="es2">$DEVICE</span>&quot;</span> table <span class="st0">&quot;<span class="es2">$table</span>&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">done</span><br />
&nbsp; &nbsp; <span class="sy0">;;</span><br />
<span class="kw1">esac</span></div></div>

<p><code>/etc/hotplug.d/net/20-split-routes</code>:</p>

<div class="geshifilter"><div class="bash geshifilter-bash" style="font-family:monospace;"><span class="kw1">case</span> <span class="st0">&quot;<span class="es2">$ACTION</span>&quot;</span> <span class="kw1">in</span><br />
&nbsp; register<span class="br0">&#41;</span><br />
&nbsp; &nbsp; . <span class="sy0">/</span>etc<span class="sy0">/</span>functions.sh<br />
&nbsp; &nbsp; include <span class="sy0">/</span>lib<span class="sy0">/</span>network<br />
&nbsp; &nbsp; scan_interfaces<br />
<br />
&nbsp; &nbsp; <span class="co0"># If this interface doesn't have a link local route, we don't need to bother</span><br />
&nbsp; &nbsp; <span class="re2">route</span>=<span class="sy0">`</span>ip route show dev <span class="st0">&quot;<span class="es2">$INTERFACE</span>&quot;</span> <span class="sy0">|</span> <span class="kw2">awk</span> <span class="st_h">'/scope link &nbsp;src/ {print $1}'</span><span class="sy0">`</span><br />
&nbsp; &nbsp; <span class="br0">&#91;</span> .<span class="st0">&quot;<span class="es2">$route</span>&quot;</span> = .<span class="st0">&quot;&quot;</span> <span class="br0">&#93;</span> <span class="sy0">&amp;&amp;</span> <span class="kw3">return</span> <span class="nu0">0</span><br />
<br />
&nbsp; &nbsp; <span class="co0"># Add this interface's route to all custom routing tables</span><br />
&nbsp; &nbsp; <span class="kw2">awk</span> <span class="st_h">'/^[0-9]/ {if ($1 &gt; 0 &amp;&amp; $1 &lt; 250) print $2}'</span> <span class="sy0">/</span>etc<span class="sy0">/</span>iproute2<span class="sy0">/</span>rt_tables <span class="sy0">|</span> <span class="kw1">while</span> <span class="kw2">read</span> table; <span class="kw1">do</span><br />
&nbsp; &nbsp; &nbsp; ip route add <span class="st0">&quot;<span class="es2">$route</span>&quot;</span> dev <span class="st0">&quot;<span class="es2">$INTERFACE</span>&quot;</span> table <span class="st0">&quot;<span class="es2">$table</span>&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">done</span><br />
&nbsp; &nbsp; <span class="sy0">;;</span><br />
<span class="kw1">esac</span></div></div>

<p>Now, lastly, it won't bring up both interfaces by default. That will be fixed by aliasing in the future, but for now:</p>

<p><code>/etc/init.d/network-multiwan</code>:</p>

<div class="geshifilter"><div class="bash geshifilter-bash" style="font-family:monospace;"><span class="co0">#!/bin/sh</span><br />
ifup wan<br />
ifup localdsl</div></div>

<div class="geshifilter"><div class="text geshifilter-text" style="font-family:monospace;">$ chmod 755 /etc/init.d/network-multiwan<br />
$ ln -s ../init.d/network-multiwan /etc/rc.d/S49network-multiwan</div></div>

<p>That's it, and it's working beautifully :-)</p>

<p>What is source routing, people ask? The problem is that your router now has 2 WAN IP addresses. IP1 is used for local traffic, and IP2 for international. So if somebody in ZA tries to connect to IP2, the reply (local destination) will go out of Interface 1. The ISP on the other end of Interface 1 will drop this reply, because it's not coming from IP1.</p>

<p>Source routing tells the router that replies must go out of the same interface that the request came in on. I'm doing it by creating separate routing tables for traffic origionating from each WAN interface.</p>

<h2>Gotchas</h2>

<ul>
<li>If you are using 2 different ISPs (say SAIX international and IS local), you must make sure that DNS queries get routed out the right interface. SAIX won't accept queries on their servers from IS, and vice versa.</li>
<li>SAIX Web proxies, Mail servers, and News servers don't accept traffic from local accounts. (especially from another ISP)</li>
</ul>
    ]]></content>
  </entry>
</feed>
