Tunnels, Routes and Rules: They're Easier with iproute2
Last week's riveting installment covered the whys and wherefores of using iproute rather than the old standbys in the net-tools package ifconfig, route, arp, and the rest of the gang, and how to use the ip command to read routing tables, ARP tables, assign additional IPs to network interface devices, and view network interface information. Today we shall effortlessly build static routes, tunnels, and implement policy rules.
Setting a default static route is so easy you'll invite your mom and dad to watch. This sets a default route from a workstation to the local Internet gateway:
# ip route add default via 192.168.1.1
Deleting a default route is just as easy:
# ip route del default
Deleting a route is a more routine task than some of you hardbitten old network admins may realize. DSL users have long been accustomed to having a dialup modem as a backup when (not if) the DSL went down. The default route leftover from the DSL interface must be deleted to get a connection with the modem. If you don't, the modem will connect, but no bits will flow over the wire, so the user is left sitting there sad, mystified, and possibly cursing.
On workstations there is usually a default route that is either assigned statically in /etc/network/interfaces on Debian, /etc/sysconfig/network-scripts/ifcfg-ethX on Red Hat and Fedora, or via DHCP.
You may change an existing route, instead of deleting it then adding a new one:
# ip route chg default via 192.168.1.2
Setting up NAT (network address translation) (define) is done this way -- map an internal address to an external public IP:
# ip route add nat 192.168.1.15 via 184.108.40.206
iproute2 does not have the flexibility of iptables for configuring NAT -- it only permits one-to-one address mapping. But if your needs are very simple, it's a nice alternative to iptables.
Simple load-balancing across multiple interfaces is done like this, with the nexthop argument marking this as a multipath route:
#ip route add default scope global nexthop via 192.168.1.1 dev eth0
nexthop via 192.168.1.1 dev eth1
nexthop via 192.168.1.1 dev eth2
You may add the weight parameter if you want to give preference to one path, like this:
#ip route add default scope global nexthop via 192.168.1.1 dev eth0 weight 1
nexthop via 192.168.1.1 dev eth1 weight 2
Because of caching, this may or may not actually have any noticeable effect. The fun bit is if you have the luxury of multiple Internet service providers, this gives automatic failover if one of them goes down. If you do get multiple providers for fault tolerance be sure they connect to different backbones; if they both rely on UUNet, for example, and UUNet horks up a big hairball, you don't gain anything.
Another way to do this is to alternate the path that each successive packet takes:
# ip route add equalize default
nexthop via 192.168.1.1 dev eth0
nexthop via 192.168.1.2 dev eth0
What if the two links carry traffic at different speeds? Suppose the first one is twice as fast as the second. This is where using the weight parameter makes sense; set the first link to send twice as many packets as the second:
# ip route add equalize default
nexthop via 192.168.1.1 dev eth0 weight 2
nexthop via 192.168.1.2 dev eth0 weight 1
Cheap, Easy WAN With GRE Tunnels
Setting up GRE (Generic Routing Encapsulation) tunnels is easy with iproute2. GRE is really slick for connecting remote offices over the Internet, a cheap, easy way to build a WAN (wide-area network) without hassling with expensive types of connectivity or BGP (border gateway protocol) and other horrid, complex routing methods. What's really nice about GRE is you can connect several LANs that use the same private addressing class, like 192.168.1.0/24.
You can run VPN (virtual private network) protocols over GRE without having to rebuild all of your routers/gateways, so it's a nice way to test and transition to new protocols. GRE is so flexible you can stuff just about any packets over it. It even supports its own form of encryption. This shows how to build one end of a GRE tunnel:
# ip tunnel add tunnel1 mode gre remote 220.127.116.11 local 18.104.22.168
# ip link set tunnel1 up
# ip addr add 192.168.1.1 dev tunnel1
# ip route add 192.168.1.0/24 dev tunnel1
tunnel1 is the name of your tunnel. You may name it anything, so using a descriptive name like "portland_sales" or "queen_marys_domain" is helpful. mode gre defines the tunnel type. (iproute2 supports ipip, gre, and sit, or IPv6-over-IPv4, tunnels.) remote is given the address of the remote network gateway, and local of course is the local gateway. The second line activates the new tunnel, or "device" as iproute likes to call it.
Next the address 192.168.1.1 is assigned to the tunnel. This can be any address you like, so you can design an addressing scheme any way you like to suit your needs. Finally add the route, and you're almost done. To complete the tunnel run the same commands from the other end, substituting the correct IP addresses.
This is where iproute2 really shines. Using policy rules lets you route packets in a number of useful ways. (Adding iptables to the brew lets you slice and dice your traffic to the point of obsession, which is a fun topic for another day.)
iproute2 lets you match packets on the following fields:
- packet source address
- packet destination address
- TOS (type of service)
- incoming interface
$ ip rule list
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
These rules point to databases; you may view their contents with these commands:
$ ip route list table local
$ ip route list table main
$ ip route list table default
Here is a simple example of source-based routing. We don't want the Mailroom subnet to have access to the Engineering subnet, so we're going to silently block them:
# ip route add blackhole 192.168.2/24
Or we can send an ICMP "communication administratively prohibited" message instead:
# ip route add prohibit 192.168.2/24
This is handy for blocking unwanted Internet traffic, such as portscans and attempted attacks. Of course the source IPs for these things are a continually moving target, but blocking them at your border routers is quick and easy.
Linux routing is flexible and capable; do yourself a favor and dig into the references in Resources to learn more about it. You just might save a nice bundle of money by using Linux instead of an expensive commercial router.
- The Linux Advanced Routing & Traffic Control HOWTO
- See man (8) ip for complete ip command options and definitions of terms shown in the command outputs
- RFC 1123 - Requirements for Internet Hosts
- RFC 1812 - Requirements for IP Version 4 Routers
- IP Command Reference. This is also available locally at /usr/share/doc/iproute
- "Policy Routing With Linux" by Matthew G. Marsh is an excellent reference
- "The Protocols (TCP/IP Illustrated, Volume 1)", by W. Richard Stevens, is the all-time best book for understanding TCP/IP