These scripts exist so that I can connect and disconnect from third party networks such as 3's UTMS network without worrying that data intended for their network will disappear up the internet pipe instead when disconnecting the mobile phone. We also avoid the idiosyncrasy of having overlapping routes in the routing tables.. I.e. a default route would overlap with everything, incuding localhost and routes back to the LAN.
The routes are made by inverting an Internet drop list.
Drop lists can be obtained from the bogons reference page or the more thorough but more frequently changing DROP list. Go for the aggregated CIDR/bit notation format. Beware that sometimes a broken list is published, such as including overlapping prefixes. Inverse detects this and aborts. Then the old route table would be left in place.
Also by not having a default route, we can remove the multicast destinations except for those we generate locally. The system currently requires they are maintained by a system service process, and can have multiple output interfaces for a single input interface.
This script combines drop entries from the Internet URL with your own routes to exclude to produce a list of desired external routes. Usage: getroutes <URL> <own excludes file> <file to write routes to>
It requires a program inverse that can be compiled as gcc -o inverse inverse.c
The file <own excludes file> is like this: (Only include entries that are not in the URL file)
010.000.000.000/08 |
127.000.000.000/08 |
172.016.000.000/12 |
192.168.000.000/16 |
224.000.000.000/04 |
It is padded as shown so the sort / comm utilities sort the entries correctly. Others can be added to block off certain IP's /32 or networks.
This example shows how to use inverse to obtain and format a route list
first parameter is URL of excludes
second is padded private excludes to drop in textfile, that arent in the excludes file i.e. 192.000.002.000/24
third is where to save the result, pad out addresses for correct sortability
#!/bin/sh function presort () { IFS=" " tr -s "./" " " | while read do case "$REPLY" in \#*) ;; *) printf %03u.%03u.%03u.%03u/%03u\\n $REPLY ;; esac done } # make list of current routes wget -O - $1 | presort | sort -g - $2 | /usr/local/sbin/inverse | presort > $3 exit $?
This program applies the difference between two files full of routes to the system routing table. Usage: routes <old routes file> <new routes file> [echo]
#!/bin/sh # this example shows how to use inverse to apply routes # compress addresses for route function pack () { sed -s 's/^0*\(.*[0-9]\)\.0*\(.*[0-9]\)\.0*\(.*[0-9]\)\.0*\(.*[0-9]\)\/0*\(.*[0-9]\)$/\1.\2.\3.\4\/\5/' } # generate commands to add or remove routes to match current IFS="/" comm -3 "$2" "$3" | cut -s -f2 | pack | while read IP BITS do [ -n "$4" ] && echo "+"$IP/$BITS case $BITS in 0) route add default dev $1 ;; 32) route add -host $IP dev $1 ;; *) route add -net $IP/$BITS dev $1 ;; esac if [ "$?" != "0" ] then exit -1 fi done comm -3 "$2" "$3" | cut -f1 | cut -s -d"/" -f1-2 | pack | while read IP BITS do [ -n "$4" ] && echo "-"$IP/$BITS case $BITS in 0) route -v del default dev $1 ;; 32) route -v del -host $IP dev $1 ;; *) route -v del -net $IP/$BITS dev $1 ;; esac if [ "$?" != "0" ] then exit -1 fi done [ -n "$4" ] && echo All done logger "Routes All Done"
A script can be made to get new routes and apply them to the system in one go. Just change the URL and create the mine-complete file.
#!/bin/sh N=http://localhost/bogons.txt M=/var/local/routes/mine-complete.txt NE=/var/local/routes/new.txt C=/var/local/routes/current.txt O=/var/local/routes/old.txt /usr/local/sbin/getroutes $N $M $NE cp $C $O mv $NE $C /usr/local/sbin/routes w1ad $O $C echo
The sangoma S518 card needed to have the routes loaded after it brings up ppp. After having installed hotplug, do
echo WAN_ACTION=\"addroutes\" >> /etc/wanpipe/wanrouter.rc
ln --symbolic /etc/wanpipe/scripts/addroutes /etc/wanpipe/scripts/wanpipe1-addroutes
ln --symbolic /etc/wanpipe/scripts/addroutes /etc/wanpipe/scripts/wanpipe1-w1ad-addroutes
Now /etc/wanpipe/scripts/addroutes is invoked whenever wanpipe brings up the link. e.g. after the line has been re-connected.
#!/bin/sh logger "ADDROUTES ON: $@" /usr/local/sbin/routes w1ad /var/local/routes/null.txt /var/local/routes/current.txt >/dev/null 2>/dev/null & pid=$! disown $pid #wondershaper w1ad 500 100
This script produces a list of domains with IP addresses from an IPv6 squid access log
if [ ! -f /dev/shm/stage1 ] then cat /dev/shm/access.log | cut -c23- | cut -d" " -f1,5,7 | \ sed 's/^\([^ ]*\) \([^ ]*\) \([^ ]*\)$/\1 \3 \2/g' | \ cut -d"/" -f1-4 > /dev/shm/stage1 fi if [ ! -f /dev/shm/stage2 ] then uniq /dev/shm/stage1 > /dev/shm/stage2 fi if [ ! -f /dev/shm/stage3 ] then cat /dev/shm/stage2 | sed ' s/^\([^ ]* DIRECT\/::ffff:\)\([0-9]\{1\}\)\(\.\)/\100\2\3/g s/^\([^ ]* DIRECT\/::ffff:\)\([0-9]\{2\}\)\(\.\)/\10\2\3/g s/^\([^ ]* DIRECT\/::ffff:[^.]*\.\)\([0-9]\{1\}\)\(\.\)/\100\2\3/g s/^\([^ ]* DIRECT\/::ffff:[^.]*\.\)\([0-9]\{2\}\)\(\.\)/\10\2\3/g s/^\([^ ]* DIRECT\/::ffff:[^.]*\.[^.]*\.\)\([0-9]\{1\}\)\(\.\)/\100\2\3/g s/^\([^ ]* DIRECT\/::ffff:[^.]*\.[^.]*\.\)\([0-9]\{2\}\)\(\.\)/\10\2\3/g s/^\([^ ]* DIRECT\/::ffff:[^.]*\.[^.]*\.[^.]*\.\)\([0-9]\{1\}\)\( \)/\100\2\3/g s/^\([^ ]* DIRECT\/::ffff:[^.]*\.[^.]*\.[^.]*\.\)\([0-9]\{2\}\)\( \)/\10\2\3/g ' > /dev/shm/stage3 fi if [ ! -f /dev/shm/stage4 ] then cat /dev/shm/stage3 | sort | uniq > /dev/shm/stage4 fi
I use the following to have a complete IPv6 routing table after having dropped the default route that sit0 likes to setup. This allows the site and rfc 4193 local ranges to be unroutable and hence safe to use for local experiments.
If you are not on 6to4 you'll substitute ommission of 2002 for your own netblock.
#!/bin/sh # wget http://www.iana.org/assignments/ipv6-unicast-address-assignments -O /var/local/routes/ipv6.txt cat /var/local/routes/ipv6.txt | grep -v ^2002 | grep ^....\: | cut -f1 -d" " | while read do route -A inet6 $1 $REPLY gw ::192.88.99.1 dev $2 done
In 2018 I noticed an extensive routes file can be obtained from the RIPE RIS. Having fetched files to local mirror
To get ipv4 routes instead, omit the -v, and to get both, omit the entire grep element in the pipeline.
It is time to configure the routing tables
It is possible to provide a set of routes via a DHCP option, which gives the advantage of end-stations knowing immediately that certain private addresses are unreachable, and for an experiment it can load a new route in.
If using an operating system that recognises only a single instance of the route option, you can offer only a few routes (about 40 at most), so I have paired down the null “martian” list to the bare essentials. Of course, it is possible to have a more complete table elsewhere.
0.0.0.0/8 10.0.0.0/8 127.0.0.0/8 172.16.0.0/12 192.168.0.0/16 224.0.0.0/4 240.0.0.0/4
Inverted, it gives this table for dhcpd, replace 192,0,2,1 with the IP address of your router.
option rfc3442-classless-static-routes code 121 = array of unsigned integer 8; option rfc3442-classless-static-routes-microsoft code 249 = array of unsigned integer 8; option rfc3442-classless-static-routes 8,1,192,0,2,1, 7,2,192,0,2,1, 6,4,192,0,2,1, 7,8,192,0,2,1, 8,11,192,0,2,1, 6,12,192,0,2,1, 4,16,192,0,2,1, 3,32,192,0,2,1, 3,64,192,0,2,1, 4,96,192,0,2,1, 5,112,192,0,2,1, 6,120,192,0,2,1, 7,124,192,0,2,1, 8,126,192,0,2,1, 3,128,192,0,2,1, 5,160,192,0,2,1, 6,168,192,0,2,1, 12,172,0,192,0,2,1, 11,172,32,192,0,2,1, 10,172,64,192,0,2,1, 9,172,128,192,0,2,1, 8,173,192,0,2,1, 7,174,192,0,2,1, 4,176,192,0,2,1, 9,192,0,192,0,2,1, 11,192,128,192,0,2,1, 13,192,160,192,0,2,1, 16,192,169,192,0,2,1, 15,192,170,192,0,2,1, 14,192,172,192,0,2,1, 12,192,176,192,0,2,1, 10,192,192,192,0,2,1, 8,193,192,0,2,1, 7,194,192,0,2,1, 6,196,192,0,2,1, 5,200,192,0,2,1, 4,208,192,0,2,1;
Having DHCP supply a static routing table does not allow it to modify the routing table whilst the lease is active. Therefore, arrange for each DHCP clients to launch an instance of BIRD which runs a BGP session to BIRD running on the main router.
This has the advantage that availability or not of routes is immediately communicated to clients using a rather well known routing protocol.
The server BIRD has a passive BGP entry for every possible IP address, and awaits BGP sessions from clients.
DHCP clients are hooked to each launch an instance of BIRD, connecting to the primary BIRD route server to get their routes via BGP. When the client application wants to exit, it tells BIRD to disconnect, and then DHCP releases the lease.
We generate the "protocol bgp" sections of bird.conf for the server programatticaly, it has the ASN of fc01h and as there are many private ASN to use, we can give each client its own ASN.
The server needs to learn its routes, and for now I use static routes, but rather than use "protocol static", instead use "protocol kernel" and pick an unused number in "/etc/iproute2/rt_tables.d/", you get serveral advantages:
One problem I came across is that BIRD would not allow passive BGP sessions to come up again after the "client", that is to say the DHCP managed BIRD instances, pulled them down.
It was possible to work around this by patching the source code of BIRD2 like this:
In proto/bgp/bgp.c, replace p->start_state = BSS_PREPARE; with p->start_state = p->passive ? BSS_CONNECT : BSS_PREPARE; and recompile.