Dual_internet_connections
Contents |
Introduction
Sometimes you may have access to multiple internet connections on a single machine. It is very handy to be able to use both internet connections for various reasons:
- Dual internet = more bandwidth (though most tasks will only use a single connection, such as a file download, the speed is seen when downloading several files and having half download on one connection and the other half using the other connection. This is similar to multi-CPU system speed increases when multitasking.)
- Redundancy; if one connection goes down you have another
- Bragging rights
- In some cases, static IP addresses are only available through DSL, but DSL is slower than cable internet options in the area. You may wish to have both, with the DSL providing a static IP address and the cable providing the speed.
Packages
As far as I can tell the only package you need for this is sys-apps/iproute2. To install it, simply emerge iproute2
Kernel Options
You do need to set the following kernel options to make use of dual connections. These options are for the 2.6.x kernel.
| Linux Kernel Configuration: Routing options (2.6.x kernel) |
Networking --->
Networking support --->
Networking options --->
TCP/IP networking
[*] IP: advanced router
[*] IP: policy routing
[*] IP: equal cost multipath
|
or, if you prefer doing things manually:
CONFIG_IP_ADVANCED_ROUTER=y CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_ROUTE_MULTIPATH=y
Configuration
| FIXME: This configuration makes use of a new init script seperate from the Gentoo networking scripts. It would be welcome if anyone would modify this to use the standard Gentoo networking init scripts. |
Step 1: Check interface configuration
First of all, you need to make sure that each Internet connection you wish to use actually works. This can be achieved through the Gentoo standard network scripts by following the Gentoo guide for configuring your network on each interface. Another option is to use the ifconfig utility to create each interface:
/sbin/ifconfig ethX xxx.xxx.xxx.xxx netmask xxx.xxx.xxx.xxx
Step 2: Create the initscript
Use your favorite text editor (e.g. nano -w) to open and create /etc/init.d/dualnet
Initial empty script
First let's create an empty initscript:
| File: /etc/init.d/multinet |
#!/sbin/runscript
start() {
ebegin "Configuring multinet"
# Interface 1
# Interface 2
# Other interfaces...
# Final Routing instructions
}
restart() {
svc_stop
svc_start
}
|
Device sections
Basic device section
Now we need to flesh it out. Each interface will have its own section that will follow this template:
/sbin/ip route add NETMASK dev DEVICE src IPADDRESS table # /sbin/ip route add default via GATEWAY table # /sbin/ip rule add from IPADDRESS table #
Variables:
- DEVICE
- the device used for this connection, e.g. eth0
- IPADDRESS
- the IP address used by this interface, e.g. 192.168.0.2
- #
- the table number to use. Each interface will have its own table, so for eth0 you might use 1
- GATEWAY
- the IP address of the gateway this interface uses, e.g. 192.168.0.1
- NETMASK
- the mask of the network that the interface is connected to, e.g. 192.168.0.0/24
So, what does this all do?
- Initial configuration for the table
- Specify the gateway this table should use
- Make sure this interface is used to respond to any connection made to it, this ensures that if someone connects to that interface, the response will go out using the same interface. We do not want a connection to come in on eth0 and have the response sent out on eth1.
You will need one section per interface.
Calculating netmask
An IP address can be represented as a 32-bit (4-byte) value, and a netmask specifies how many bits are used to identify the network, and how many are used to identify the specific machine. For instance a netmask of 255.255.255.0 has the first 3 bytes of an IP address used for the network, and the last byte for the machine. For netmasks that have only 255's and 0's as their sections it is easy to calculate the bit value at the end (/xx). Each section is 8 bits, and /xx is the total number of bits used for the network portion, so simply multiply the number of 255s by 8:
255.0.0.0 255's: 1 1 * 8 = 8 /8 255.255.0.0 255's: 2 2 * 8 = 16 /16 255.255.255.0 255's: 3 3 * 8 = 24 /24 (Fairly common) 255.255.255.255 255's: 4 4 * 8 = 32 /32 (This will never happen, as it specifies just one IP address in the subnet, and at least 4 IP addresses are needed in a standard network setup)
For more complex subnet masks, you have two choices. The first solution is to run ip route as root, which will show you the proper CIDR masks for all interfaces that are up and running.
# ip route 192.168.0.0/24 dev eth1 proto kernel scope link src 192.168.0.2 127.0.0.0/8 via 127.0.0.1 dev lo scope link
The other way to do it is with a little bit of binary conversion and a shortcut. Because of the way CIDR works, at least three of the four numbers will be 0 or 255, and the 255s will always be grouped on the left and 0s on the right. For example:
255.255.248.0 --- binary ---> 1111 1111.1111 1111.1111 1000.0000 0000
This has 2 × 8 1's from the first two bytes, then 5 from the second, giving a total of 21 bits, so if this were applied to the network 192.168.0.0, then you would have 192.168.0.0/21 (meaning that valid addresses are from 192.168.0.0 - 192.168.7.255).
Note: This is called Classless Inter-Domain Routing (CIDR pronounced 'cider') notation and allows subnets which do not start and end on byte boundaries.
Example: two interfaces
# Interface 1: /sbin/ip route add 192.168.0.0/24 dev eth0 src 192.168.0.2 table 1 /sbin/ip route add default via 192.168.0.1 table 1 /sbin/ip rule add from 192.168.0.2 table 1 # Interface 2: /sbin/ip route add 192.168.1.0/24 dev eth1 src 192.168.1.2 table 2 /sbin/ip route add default via 192.168.1.1 table 2 /sbin/ip rule add from 192.168.1.2 table 2
Final Routing Instructions
Single Outbound Route
Normally a system will have a single default gateway. This gateway is used for any connection where no pre-defined routing path can be found. If you simply want each interface to respond to its own connections, but only have one connection used for outbound traffic then you simply need to specify the default gateway:
# route add default gw GATEWAY DEVICE
If, however, you want to utilise the bandwidth of more than one connection then you must specify the route differently.
Load Balancing
Before you start load balancing, you will want to know what your current default gateways are. If you don't know what these are, then they are probably automatically set up for you. Gateways appear in your routing table with a "G" flag, as shown below:
# route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 192.168.0.0 * 255.255.255.0 U 0 0 0 eth1 loopback Abydos.open-exo 255.0.0.0 UG 0 0 0 lo default xxx.xxx.xxx.xxx 0.0.0.0 UG 0 0 0 eth0 default xxx.xxx.xxx.xxx 0.0.0.0 UG 0 0 0 eth1
The columns in the routing table above are, in order, target address type, gateway address (or * if none required), network mask (described above), flags, some advanced information, and then the interface to which the line refers.
First you want to make sure there are no existing default gateway routes. This means that you have to edit your startup scripts and make sure you never specify a gateway for the interfaces you have configured. This information can be found in /etc/conf.d/net and will usually be a line similar to:
| File: /etc/conf.d/net |
routes_eth0=( "default via xxx.xxx.xxx.xxx" ) |
and it may or may not have "dev eth0" at the end. This line should be commented for all interfaces that you wish to use in this way.
Alternatively (although it's not recommended) you can manually remove existing gateway routes. To manually remove default gateways, you need to find them first, as described above.
To remove a gateway:
# route del default DEVICE
Make sure they are all removed.
If you still wish to do this, edit your multinet init script that we wrote above, and above each interface section insert this line:
/sbin/route del default DEVICE &> /dev/null
This will do the job, but it is not recommended. If the default route exists it will be deleted, but if not the command will generate an error.
Now we have removed our gateways, we must specify our default route.
/sbin/ip route add default scope global\
nexthop via GATEWAY1 dev DEVICE1 weight W1\
nexthop via GATEWAY2 dev DEVICE2 weight W2
Variables:
- All previously defined terms are still used, with the same meanings.
- W
- Weight, numerical value 1 or greater. A higher weight will result in that connection being used more often. If both of your connections are the same speed, use 1 for each. If one connection is twice as fast as the other use 2 for its weight, and it will be used more often.
Each device will have its own line:
nexthop via GATEWAY dev DEVICE weight W
Each line except the last should have the "\" escape character to tell the script that the next line is still part of the same command.
The last piece of information the system needs is the nameserver to use when resolving hostnames to IP addresses. The nameserver address is stored in /etc/resolv.conf and should have an entry like this:
| File: /etc/resolv.conf |
nameserver 192.168.0.1 |
To specify the nameserver simply run the following:
# echo "nameserver GATEWAY" >> /etc/resolv.conf
| FIXME: I know there is a way to stop this, but I can't remember it offhand. One way is to edit /etc/conf.d/net and add/edit the dhcpcd_iface lines to include the -R option, which stops dhcpcd replacing /etc/resolv.conf. phyreskull 22:25, 25 March 2007 (UTC) |
If you do not have anything that creates this line in the file that is all you need. However if you already have the nameserver line in there for some reason on reboot, I recommend you find out why and prevent it from happening. An alternative way to do this is to execute the following command before the echo given above:
# sed -i -e '/^nameserver/d'
This will remove all "nameserver" lines from /etc/resolv.conf while preserving the other important lines.
Most gateways will run a DNS server of some kind, so you can probably use the IP address of any of your Internet gateways, but it is best to check. Optionally you can specify all of them:
# echo "nameserver GATEWAY1" >> /etc/resolv.conf # echo "nameserver GATEWAY2" >> /etc/resolv.conf # echo "nameserver GATEWAY3" >> /etc/resolv.conf
Example of final script
Here is a script as an example. It uses both DSL and cable modem connections. Note that IP addresses have been stripped for security.
| FIXME: I'll come up with a more general script with better integration to the Gentoo net scripts and more progress information when I have some time later. phyreskull 22:53, 25 March 2007 (UTC) |
| File: /etc/init.d/multinet |
#!/sbin/runscript
start() {
ebegin "Configuring multinet"
# I do not use the Gentoo net scripts, so I start the interface here
/sbin/ifconfig eth0 aaa.aaa.aaa.aaa netmask 255.255.255.248
/sbin/ip route add aaa.aaa.aaa.aaa/29 dev eth0 src aaa.aaa.aaa.aaa table 1
/sbin/ip route add default via bbb.bbb.bbb.bbb table 1
/sbin/ip rule add from aaa.aaa.aaa.aaa table 1
# I do not use the Gentoo net scripts, so I start the interface here
/sbin/ifconfig eth1 192.168.0.2 netmask 255.255.255.0
/sbin/ip route add 192.168.0.0/24 dev eth1 src 192.168.0.2 table 2
/sbin/ip route add default via 192.168.0.1 table 2
/sbin/ip rule add from 192.168.0.2 table 2
/sbin/ip route add default scope global\
nexthop via bbb.bbb.bbb.bbb dev eth0 weight 1\
nexthop via 192.168.0.1 dev eth1 weight 3
# cable modem is 3 times faster than my dsl
##################################
# This method is not recommended #
##################################
# Wipe out the file and give it the first nameserver
echo "nameserver 192.168.0.1" > /etc/resolv.conf
# Add the second nameserver afterwards
echo "nameserver bbb.bbb.bbb.bbb" >> /etc/resolv.conf
eend $?
}
restart() {
svc_stop
svc_start
}
|
Note on DHCP and dynamic IPs
The Note
| FIXME: TODO: work out how this should all fit together with dynamic IPs. phyreskull 11:31, 29 March 2007 (UTC) |
If any of your connections are dynamically assigned via DHCP, you have a problem. Basically everything laid out above is for static IP addresses. One solution is to have your dynamically assigned interfaces initialise before the script, then grab the info from the system and use it in the script. The original author did not have this issue and has not worked out all the fine details of doing this. Basically you need to follow these steps though:
- Establish the dynamic connections
- Grab the information (IP, Network, and gateway)
- Remove the default route created by the connection
- Run the script using the information that has been grabbed
Helpful script
| FIXME: Note to self: Carry on from here. phyreskull 11:31, 29 March 2007 (UTC) |
I am a nice guy, while I have not gone through and written the script for dynamic addresses I have created a utility to help anyone that wants to try.
The perl script below allows you to grab the IP and gateway of an established interface.
#!/usr/bin/perl
use strict;
my $IP;
my $GW;
my $IF = $ARGV[0];
my $Data;
exit(1) if ((!($ARGV[0])) || (!($ARGV[1])));
if ($ARGV[1] eq 'ip')
{
$Data = `/sbin/ifconfig $IF`;
$Data =~ m/inet addr:[0-9\.]+/i;
my $IP = $&;
$IP =~ s/inet addr://ig;
print("$IP");
} elsif ($ARGV[1] eq 'gw')
{
$Data = `/sbin/route`;
$Data =~ m/default.*$IF/ig;
$GW = $&;
$GW =~ s/default\s*//ig;
$GW =~ s/\s+.*//ig;
print("$GW");
}
Simply save the script to a file such as info.pl, and give it the proper permissions using chmod.
[Camel] The above script returns the FQDN of my gateway; this is a simple fix:
$Data = `/sbin/ip route | grep $IF`;
$Data =~ m/default.*via.*/ig;
$GW = $&;
$GW =~ s/default via\s*//ig;
$GW =~ s/\s+.*//ig;
print("$GW");
Syntax:
./Script.pl <DEVICE> <Info to get>
Example: Getting IP of eth0
./Script.pl eth0 ip
Example: Getting Gateway of eth0
./Script.pl eth0 GW
To use this in a script:
$IP = `/path/to/script.pl eth0 ip`
the ip address of eth0 will now be inside the $IP variable, you can then use that wherever you need it. The script does not return a newline, so the variable should be uncluttered.
Hope that helps.
Sources/Links
[1] - 4.2 Routing for multiple uplinks/providers section of Linux Advanced Routing & Traffic Control HOWTO
Created by NickStallman.net, His Dark Materials - The Golden Compass, Luxury Homes Australia Apartments Queensland Monopoly City Streets Forum
