Understanding routing

Post date: May 06, 2013 12:27:3 AM

On Linux and UNIX systems, information on how packets are to be forwarded is stored in a kernel structure called a routing table. You need to manipulate this table when configuring your computer to talk to other computers across a network. The routing table can be used for both static and dynamic routing. Dynamic routing consists of the kernel making decisions as to which route, out of multiple present routes, a packet should take. Since dedicated routers and ISPs generally deal more with dynamic routing, I won’t go into detail, as it is beyond the scope of this Daily Drill Down. In this Daily Drill Down, however, I will focus on static routing because it is the most common.

You can examine the routing table by using the netstat program like this:

netstat -r

This will print out a routing table that may look something like the one in Table A.

Kernel IP routing table

The Destination column identifies the destination network. The Gateway column identifies the defined gateway for the specified network. An asterisk (*) appears in this column if no forwarding gateway is needed for the network. The Genmask column shows the netmask for the network; in this case, it is 255.255.255.0. The Iface column shows the network interface. If you had more than one interface, you would see lo (for loopback), eth0 (first Ethernet device), and eth1 (for the second Ethernet device), and so on for the number of interfaces you have installed. Under the Flags section, the U flag means the route is up, and the G flag means that specified gateway should be used for this route. There are other flags that you may see, which include: D for dynamically installed, M for modified, and R for reinstated. These three flags indicate that the route was created or modified by a routing daemon after encountering an ICMP Redirect message. (Usually, you won’t see these flags unless you use dynamic routing.) Finally, you may see a ! flag, which indicates a rejecting route.

The MSS column indicates the default Maximum Segment Size for TCP connections over this route. The Window column indicates the default window size for TCP connections over this route, and the Irtt column indicates the Initial Round Trip Time for this route. The kernel uses this to select values for certain TCP parameters without having to wait for potentially slow answers from remote hosts. These three columns you will normally not need to worry about unless performance is suffering and you're trying to find a way to tweak it. Under most circumstances, you will not redefine the defaults here.

As you can see, I have defined a route for 127.0.0.0, which is the loopback network. The loopback network is handled locally, so no forwarding gateway is required. I also have a defined route for 192.168.10.0, which is the network that the eth0 interface is attached to. It also does not require a forwarding gateway because this is the local network. The last line contains a Destination of default, sometimes shown as 0.0.0.0, which means everything else not already classified. In this case, everything not destined for the loopback network or the 192.168.10.0 network will be sent to the 192.168.10.1 address—which is the forwarding gateway—and the route to the Internet.

Changing static routes

Now that I’ve shown you how to display currently defined routes, you’ll need to know how to change them. This can be done easiest using the Linuxconf program under Red Hat or Linux-Mandrake and similar administration programs under other Linux variants. Some variants, however, do not have tools like Linuxconf to handle defining routes, so let’s take a look at the "old school" method, instead. To do this configuration by hand, you'll have to learn how to use theroute command.

The first argument passed to route will be either add or del, which will tell route if it is adding or deleting a route from the routing table. The rest of the arguments that route uses are dependant upon which action you have chosen.

Let's take a look at creating the routing table so that we have defined the same routes, as shown in the previous example. The first thing you need to do is add the network to which you belong by using:

route add -net 192.168.10.0 netmask 255.255.255.0 dev eth0

This will add the network 192.168.10.0/255.255.255.0 to the Ethernet device eth0. This corresponds with the first line shown in the netstat output.

To add the loopback network, you would use:

route add -net 127.0.0.0 netmask 255.0.0.0 lo

This adds the network 127.0.0.0/255.0.0.0 to the Ethernet device lo, which represents the loopback (or local) network. It is not necessary to do this if you’re using Linux kernels 2.2 or higher, as those kernels will handle this automatically.

Finally, you need to add the default gateway using:

route add default gw 192.168.10.1

This creates the final entry shown by netstat and tells Linux to route all packets not destined for the 192.168.10.0 network or the loopback network to the defined gateway, in this case 192.168.10.1.

In the same way, you can delete networks using the del command with route like this:

route del -net 192.168.10.0

This will delete the routing table entry for the 192.168.10.0 network.

Multinetwork routing

So what happens if you have a more complicated network? Let's assume for a moment that you have two LANs, the first with the 10.0.0.0 network and a second with the 192.168.10.0 network. There is a firewall between the two networks, with two network cards: eth0 is attached to the 10.0.0.0 network, while eth1 is attached to the 192.168.10.0 network. This firewall needs to route packets from the 10.0.0.0 network through the 192.168.10.0 network, which will in turn forward packets to the Internet.

In this scenario, you’d set up the firewall system with two IP addresses: 10.0.0.1 on eth1 and 192.168.10.25 on eth0. The gateway to the Internet on the 192.168.10.0 network is still 192.168.10.1. On the firewall system, you would run route with the following commands:

route add -net 192.168.10.0 netmask 255.255.255.0 dev eth1

route add default gw 192.168.10.1

route add -net 10.0.0.0 netmask 255.0.0.0 dev eth0

On the router, this defines both networks: 192.168.10.0 on eth1 and 10.0.0.0 on eth0. It also assigns 192.168.10.1 as the default gateway.

On the computers in the 10.0.0.0 network, you would use route like this:

route add -net 10.0.0.0 netmask 255.0.0.0 dev eth0

route add default gw 10.0.0.1

This tells each computer that the default gateway is 10.0.0.1, which is your firewall/router.

With both the firewall and the 10.0.0.0 network set up, you should be able to route all packets from the 10.0.0.0 network to the Internet and to the 192.168.10.0 network. So what happens if you have a system in the 192.168.10.0 network you want to be able to talk to systems in the 10.0.0.0 network?

On each system in the 192.168.10.0 network, you will have to configure your routing table a little differently. Here, you would traditionally use:

route add -net 192.168.10.0 netmask 255.255.255.0 dev eth0

route add default gw 192.168.10.1

This configures the network and the default gateway. However, in this case, 192.168.10.1 knows nothing about the 10.0.0.0 network, so your packets would get lost because 192.168.10.1 has no idea where to send the packets and will attempt to send them through the default gateway. You need to add another routing statement to each system in the 192.168.10.0 network like this:

route add -net 10.0.0.0 netmask 255.0.0.0 gw 192.168.10.25

This command tells the kernel to route all packets destined for the 10.0.0.0 network to 192.168.10.25, which it defines as a gateway. So now, by using the three route commands, your kernel will know where to send packets. In this situation, a few things happen:

Packets to 192.168.10.0 are handled without a gateway.

Packets to 10.0.0.0 are sent to the defined gateway, 192.168.10.25.

Packets traveling anywhere else are sent to the default gateway, 192.168.10.1.

Using Linuxconf

Routing can be configured in a more intuitive way if you have the Linuxconf program, or something similar, available to you.

With Linuxconf, you can easily set up routing. To do so, fire up Linuxconf and select the Networking section. Click on Routing And Gateways. Here, you have a few options from which you can choose.

You’ll first need to set the defaults. Click the Defaults button, and define your default gateway by entering 192.168.10.1. If this were a router you were configuring, you would click Enable Routing to tell the kernel to allow packets from other systems to be routed through your system to the defined gateway.

Here, you can also define routes to other networks, routes to other hosts, and routes to alternate local networks. To define routes to other networks, you would use the route command. Click Route To Other Networks, and you will be given a list of the currently defined routes. Click Add to add a new route.

In the Add New Route window, you define the gateway to the other network, the destination network, and the netmask, which is an optional setting. In this case, you might set 192.168.10.25 as the gateway with 10.0.0.0 as the destination. You could optionally select 255.0.0.0 as thenetmask. Click Accept to save the routing definition.

You can similarly define the route to another host. For instance, if you only wanted to be able to reach the computer at IP address 10.0.0.28, you might select the Route To Other Hosts option and add a new route with the gateway of 192.168.10.25 and the destination of 10.0.0.28. In this way, you don't have to do blanket routing, because you would only be dealing with the one host. If you want to deal with more than one host in the 10.0.0.0 network, you probably want to define a route to the entire network. This is handy if you have multiple gateways routing to different parts of the same network. For instance, if 10.0.0.28 was located behind a gateway at 192.168.10.125, while the rest of the 10.0.0.0 network you need was located behind 192.168.10.25, you might define the gateway here of 192.168.10.125 for the destination 10.0.0.28 and have the blanket route to 10.0.0.0 defined in the Route To Other Networks section. Since the packet will always be routed with the best match (or shortest path), it is safe to define routing in this fashion.

Finally, you can define other local networks in the Route To Alternate Local Networks section. Unlike the previous definitions, this does not work by going through a defined network but by broadcasting through the defined Ethernet interface. For instance, if you were configuring your router, the defined local network may be 192.168.10.0 for eth0 and 10.0.0.0 for eth1. You could define the interface as eth1, the destination as 10.0.0.0, and the netmask as 255.0.0.0. This would tell the kernel to route all traffic to the 10.0.0.0 network directly over the eth1 interface instead of through a gateway.

Another likely interface would be running a multilayered network where your primary address is in the 192.168.10.0 network with a secondary address as an alias in the 10.0.0.0 network. For instance, your primary eth0 address might be 192.168.10.12 and your alias—which would be listed as eth0:0—might be 10.0.0.12. You would define the interface as eth0, the destination as 10.0.0.0, and the netmask as 255.0.0.0. Your system would then handle traffic for both the 192.168.10.0 and 10.0.0.0 networks transparently.

More often than not, however, you won't need to make use of this unless you are configuring a router or you have a rather large and complex LAN.

After you've made your changes in Linuxconf, simply exit and save your changes. Then, restart your network using:

/etc/rc.d/init.d/network restart