License:
----------
RatRoute  - a routing table manipulator
Copyright (C) 2005  Roelf Diedericks

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USAt


Overview:
----------

RatRoute is a perl script to simplify the maintenance of gateways
and routing tables in situations where multiple paths to the internet
are available. It does this by manipulating the Linux kernel routing
tables using the iproute2 utility and information from a configuration
file.

iproute2 has an advantage over the normal linux 'route' utility in that
it's syntax allows one to more accurately control the kernel routing 
table, setup multiple default gateways and lists of routing table rules
to order kernel routing decisions.

Unfortunately, iproute's syntax and ideology makes it a tool that isn't
easily understood by end-users. Linux Kernel routing rules makes 


Pre-Requisites:
---------------
- RatRoute requires the CPAN Module LockFile::Simple

wget http://search.cpan.org/CPAN/authors/id/R/RA/RAM/LockFile-Simple-0.2.5.tar.gz
tar xvfz LockFile-Simple-0.2.5.tar.gz
cd LockFile-Simple-0.2.5
perl Makefile.PL
make install

- You must have a reasonably modern (preferably 2.6.8+) series kernel
- You must have patched said kernel with an appropriate patch for the
  kernel revision with a the routes- patch by Julian Anastov.
  http://www.ssi.bg/~ja/#routes-2.6

- You must have iproute2 version ss041019 or higher
- Your kernel must be configured as an advanced router (CONFIG_IP_ADVANCED_ROUTER)
- Appropriate masquarading rules if you intend to masquerade an internal network
  via the loadbalanced gateways. E.g.: 
  	iptables -t nat -A POSTROUTING -o ppp+ -j MASQUERADE
  The "ppp+" bit indicates to the kernel that all traffic outbound via any PPP interface
  is to be masqueraded.


Installation:
--------------
- Must be done as root
- Unpack the tarball
box:~ tar xvfz ratroute-0.2.tar.gz


- Copy the binary and config file

Example:

box:~/ratroute-0.1# cp ratroute /usr/bin
box:~/ratroute-0.1# cp ratroute.conf /etc

- Create symlinks to ratroute
 so that it can trap PPP up/down events

box:~# ln -s /usr/bin/ratroute /etc/ppp/ip-up.d/ratroute
box:~# ln -s /usr/bin/ratroute /etc/ppp/ip-down.d/ratroute

The scripts in /etc/ppp/ip-*.d/ is run by run-parts everytime
a ppp connection is established or torn down on debian systems.

Configuration:
---------------

The sample /etc/ratroute.conf file includes an example to configure
two DSL connections for loadbalanced traffic.

The most crucial part of the configuration for each interface is the
"linkname/ipparam" parameter. This has to exactly match the ipparam
and linkname options in your /etc/ppp/peers/dsl1 configuration file.
Each interface must have unique ipparam/linkname parameters so that
ratroute can figure out on which interface a routing event has been
generated.

Detail of operation:
--------------------

The following example explains the event flow for a debian-like 
system with two interfaces: 'dsl1' and 'dsl2'.

/etc/ppp/ppp_on_boot is run automatically at bootup by
the /etc/init.d/ppp script.

ppp_on_boot in turns activates each of the dsl connections
dsl1, and dsl2 by running 'pon dsl1' or 'pon dsl2'. This starts
the ppp daemon with the appropriate configuration file from 
/etc/ppp/peers which contains the ISP/PPPoE link specific information.
Examples of these can be found in the ppp-peer-samples/ directory
within the tarball.

Important parameters in the peers/* files are the "ipparam" and 
"linkname" parameters. These parameters get passed to ratroute
and is ratroute's only means of identifying the interface on
which the event ocurred. 

Additional boot-up adsl connections can be configured here by
simply adding them to ppp_on_boot.

Apparently the /etc/ppp/ppp_on_boot and /etc/init.d/ppp method
is now deprecated in Debian 3.1 so it would probably be a good
idea to move the startup of these interfaces to /etc/network/interfaces
at some point in the future as described in 
/usr/share/doc/ppp/README.Debian.gz and interfaces(5) man page.

After a PPP connection has been establish, ratroute is triggered
by the symlinks in /etc/ppp/ip-up.d

Various environment variables that have been set by pppd is then
used to determine how to configure the kernel routing table.

In our example, after both PPPoE connections have been established
the kernel routing table will look like this.

The kernel routing table is made up out of 'rules' and 'tables'
Rules, are configured in order of preference.

box:~# ip rule list
0:      from all lookup local 
30:     from 165.146.35.96 lookup dsl1_reverse 
30:     from all lookup dsl1 
31:     from 165.146.46.74 lookup dsl2_reverse 
31:     from all lookup dsl2 
51:     from all lookup main 
52:     from all lookup balancedpool 
32766:  from all lookup main 
32767:  from all lookup default 

The kernel will start looking for routes in the 
various rules by starting at 0.

The 'local' table contains routes to directly attached network interfaces
such as the ethernet network, and the routes to the actual ppp devices 
themselves.

The "dsl1" and "dsl2" rules and their counterpart *_reverse rules
contain routes that are to be direclty handled by each respective
PPP interface. The "_reverse" routes is where the secret of multipath
balanced gateways lie. The reverse rules explain to the kernel that
incoming traffic from an interface needs to be sent back out on the 
same interface, instead of going via the loadbalanced routes.

The 'balancedpool' table contains a multipath loadbalanced route for
the two dsl interfaces. 

These are essentially the default gateways for the system.

box:~# ip route show table balancedpool
default 
        nexthop dev ppp1 weight 1
        nexthop dev ppp0 weight 1

Whenever ratroute detects that an interface has gone down, it will
readjust this balancedpool table to ensure that the dead interface
is removed from the pool. This negates most of the need for kernel
patches for dead-gateway-detection.

When an interface goes down, the ip-down.d symlink to ratroute takes
care of deleting any routes that were added and also removes the dead
gateway from the balancedpool table.

To test whether loadbalancing is actually ocurring:

box:~# ip route get 66.249.85.99
66.249.85.99 dev ppp0  src 165.146.35.96 
    cache  mtu 1492 advmss 1452 hoplimit 64

box:~# ip route get 66.249.85.100
66.249.85.100 dev ppp1  src 165.146.35.96 
    cache  mtu 1492 advmss 1452 hoplimit 64

If loadbalancing is ocurring correctly, then each request for a new
route will cause the kernel to choose a different interface. Note that
once a route has been established, the same route will be preferred
until the route drops out of the route cache, or the route cache is
flushed

To flush the route cache, issue the 'ip route flush cache' command.
Ratroute automatically flushes all routes whenever an interface
event is detected.

Weighting can be assigned to the various interfaces by changing the
values in /etc/ratroute.conf as described in said file.



INTERNET SOLUTIONS CONFIGURATION
---------------------------------

A custom /etc/network/interfaces file has been added to show operation
of a non-directly attached router, using ratroute. This is used in the
case where an ISP, such as Internet Solutions provides a managed Cisco
ADSL router, and a set of static IP adresses.

Due to the fact that these interfaces are not directly attached, a monitor
script "rateventd" has been created. rateventd, will ping a predefined
IP address using a direct ICMP ping on the interface that is directly
connected to the Cisco router. In this way, traffic can be load balanced
accross multiple directly attached Cisco routers from a machine running
ratroute. It's important to note that each Cisco must be DIRECTLY attached
to a Ethernet port on the box running ratroute, e.g eth2, and eth3.

Some extra parameters needs to be defined in the debian /etc/network/interfaces
file on the system. The example file is called debian_network_interfaces_sample

An example ratroute.conf file (ratroute.conf.cisco_lines) is also included
to show how the /etc/ratroute.conf file has to be configured.

How this works:

The script /usr/bin/rateventd has to be running constantly, in order for
the system to work. In the example configuration, it is started up
from ifup/ifdown by placing "/usr/bin/ratroute" as a "up" script into
/etc/network/interfaces. This means that a copy of rateventd will be
start whenever the interfaces attached to the cisco's are brought up.

rateventd will check if a copy of itself is already running, and startup a 
new copy if it is not yet running.

Rateventd then pings the ping_hosts configured in the interfaces file
and generates ratroute events should the ping_host become unavailble,
which hopefully means that the Cisco has gone down (for whatever reason).

The example configuration starts rateventd on the Virtual Terminal 9
accessed using Alt-F9 from the linux console. It also logs events
to the syslog.

Upon startup rateventd changes it's process name to rateventd_running
thus to find the process do a "ps -ef | grep rateventd_running"


Files accessed:
-----------
/etc/ratroute.conf
/var/lock/ratroute.lock
/var/state/ratroute.weights
/proc/net/dev

Contact:
----------

email: <rodent at rodent dot za do net>
post:
	Roelf Diedericks
	6 Hagen Road
	Greenside
	2193
	Johannesburg, Gauteng
	Republic of South Africa

