What will you miss when this site closes?





204 votes ~ 6 comments

This site will turn read-only at the end of September 2017.

Supplying routing information using DHCP

Posted by endecotp on Wed 6 Dec 2006 at 10:11

This article describes how to use DHCP to supply information about static routes to the clients on your network. You may want to do this if you have two or more local networks with routers between them. The DHCP software doesn't support this out-of-the-box, but it can be configured to do so without too much effort.

The problem:

Imagine you have a small network using 192.168.1.* local IP addresses, connected to the outside world via a router. The machines on the network are all running Debian, of course. The router might be a Debian box, or maybe something lightweight like a WRT54G running OpenWRT. The router is also a DHCP server for the other machines. All is good and you are happy.

Then one day you decide you want another network, 192.168.2.*. (In my case I wanted to connect up some test systems with limited connectivity to the outside world.) So you add a second network interface to one of the machines which forwards between the two networks. Now you have something like this:

Internet <---> Router A <---> Network 1 <---> Router B <---> Network 2

For this to work the machines in Network 2 must be set up with Router B as their default router, while the machines in Network 1 must be set up with Router A as their default router. This can be done using DHCP or with static data in /etc/network/interfaces. Enable IP forwarding on Router B (/etc/sysctl.conf) and it will almost work, but not quite: you need to add rules on Router A and all the machines in Network 1 telling them how to reach Network 2. Here's what you need to do to set this up manually:

route add -net 192.168.2.0 netmask 255.255.255.0 gw router_b

Doing it manually on Router A is not a problem - it's only one machine. But it could be time consuming and error prone to do it manually on every machine in Network 1 - and where in /etc do I put these route commands anyway? Then, when a friend drops by with their laptop, you want it to be auto-configured, don't you?

The solution is to use DHCP to supply this extra routing information to the machines in Network 1. The complication is that this is not supported out-of-the-box. This article explains how I have done it. Hopefully some readers will be able to improve on this and maybe even get some of this included in the relevant Debian packages.

Routing information in DHCP

There is a DHCP option, static-routes, to supply routing information. Unfortunately it's only useable with single hosts since it doesn't include a subnet mask. So although it is described in dhcp-options(5) it isn't implemented by the DHCP client.

An improvement on this is described by RFC3442, "Classless Static Route Option for DHCPv4". This option does include a netmask (albeit in a slightly odd format) and is suitable for the problem we're solving here. Unfortunately there is no out-of-the-box support for it at all in any of the DHCP tools (as far as I can see - please correct me if I'm wrong). Luckily, however, the DHCP tools are all extensible, so we can add support just by editting a few files.

Format of the destination address and netmask

RFC3442 uses an unusual format to define an address and netmask: the first byte gives the number of significant bits, and the subsequent bytes - one to four of them - give the bytes containing those bits. So in our case the network address 192.168.2.0 and netmask 255.255.255.0 (also often written as 192.168.2.0/24) is encoded as 24.192.168.2.

I assume that you are using a /24 network in the rest of this article, because in this case the RFC3442 format has four bytes, the same as an IP address. If you have a smaller or much larger subnet it will have a different length which makes configuration more difficult. If someone would like to post a variation that works with arbitary subnet sizes that would be great.

Setting up dnsmasq

I use dnsmasq as DHCP server on "Router A". dnsmasq is available for Debian, though in my case I run it on OpenWRT. dnsmasq doesn't know about the classless-static-routes option, but it allows you to add arbitary options using their code number, as follows, in /etc/dnsmasq.conf:

dhcp-option=121,24.192.168.2.0,192.168.1.12

121 is the option code for classless-static-routes. 24.192.168.2 is the network address and netmask, encoded as described above. 192.168.1.12 is the IP address of Router B (unfortunatel you can't put a hostname there). Note that if you have more than one additional network you can add further pairs of addresses to the option.

The dnsmasq man page suggests that you should be able to write 192.168.2.0/24 and have it automatically encoded. This didn't work for me and it was sent as a string. That's quite possibly just because I don't have a sufficiently new version.

Note that in this case this will be served to all machines, which is wrong if this machine is also providing DHCP to Network 2. In that case you need to tell it to send this option only to machines in Network 1. This is possible; see the dnsmasq man page.

I imagine that other DHCP servers can be set up equally easily.

Setting up dhclient

You need to tell dhclient to request the classless-static-route option from the server. To do this, add it to the list of options in the "request" line in /etc/dhclient.conf or /etc/dhcp3/dhclient.conf. Since it knows nothing about the option by default you need to define it first:

option classless-static-routes code 121 = array of { ip-address, ip-address };

Adding the route

The dhclient program manages the communication with the DHCP server but uses an external program, dhclient-script, to perform the actual network configuration based on the data that it obtains. This is a shell script that receives the information from the server via environment variables.

In version 3 of dhclient, dhclient-script is customisable using scripts under /etc/dhcp3/dhclient-*-hooks.d. In earlier versions of dhclient, dhclient-script itself needs to be modified. I'll assume that you have the newer version.

All you need to do is to drop this script into /etc/dhcp3/dhclient-exit-hooks.d/configure_static_routes:

#!/bin/sh

function process_routes() {
  while [ $# -ne 0 ]
  do
    dest=$1
    gateway=$2
    shift; shift

    echo $dest | tr '.' ' ' | { 
      read a b c d
      if [ "$a" = "24" ]
      then
        netmask="255.255.255.0"
        netaddr="$b.$c.$d.0"
      else
        echo "Sorry, can't process destination with $a signficant bits"
        exit 1
      fi
      route add -net $netaddr netmask $netmask gw $gateway
    }
  done
}


if [ "$reason" = "BOUND" ]
then
  echo "classless_static_routes = $new_classless_static_routes"
  process_routes $new_classless_static_routes
fi

I hope this is useful. Do let me know if you have any feedback.

Is there any chance of any of this being supported by the packages?

 

 


Re: Supplying routing information using DHCP
Posted by spiney (85.125.xx.xx) on Wed 6 Dec 2006 at 11:25
Any way to use this with Windows clients? IIRC no, but maybe my memory is in need of a refresh.

Kind regards
Wolfgang Karall
--
Debian GNU/Linux on an IBM Thinkpad T43p

[ Parent | Reply to this comment ]

Re: Supplying routing information using DHCP
Posted by Anonymous (193.195.xx.xx) on Wed 6 Dec 2006 at 11:41
Erm... why would you not just put static routes onto your routers?

[ Parent | Reply to this comment ]

Re: Supplying routing information using DHCP
Posted by spiney (85.125.xx.xx) on Wed 6 Dec 2006 at 11:47
Because clients in network 1 need to have the route to network 2, otherwise (without the knowledge about router B) they would use their default gateway, ie. router A. Of course, one could let that router handle this, but it's unneccessary network traffic doubling compared to the direct way via router B, IMO.

Kind regards
WK
--
Debian GNU/Linux on an IBM Thinkpad T43p

[ Parent | Reply to this comment ]

Re: Supplying routing information using DHCP
Posted by TokenGoth (193.195.xx.xx) on Wed 6 Dec 2006 at 12:03
Not in my experience... and thats the way my network here is setup.

Our Windows machines learn the routes to networks when they try to reach the hosts as the routers send back redirects... and I'm pretty sure our Linux boxes get the same info, infact a quick test:

nephthys:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.1.0       0.0.0.0         255.255.255.0   U     0      0        0 eth0
0.0.0.0         192.168.1.12      0.0.0.0         UG    0      0        0 eth0

nephthys:~# traceroute bes
traceroute to bes (192.168.20.204), 30 hops max, 38 byte packets
 1  rt (192.168.1.12)  0.909 ms  0.888 ms  0.884 ms
 2  rt-vpn-policy (192.168.1.224)  2.113 ms  1.584 ms  1.618 ms
 3  bes (192.168.20.204)  32.685 ms  36.053 ms  32.565 ms

nephthys:~# traceroute bes
traceroute to bes (192.168.20.204), 30 hops max, 38 byte packets
 1  rt-vpn-policy (192.168.1.224)  0.846 ms  0.773 ms  0.757 ms
 2  bes (192.168.20.204)  32.460 ms  33.175 ms  35.103 ms


Yup, its learned to bypass the default gw.

[ Parent | Reply to this comment ]

Re: Supplying routing information using DHCP
Posted by spiney (85.125.xx.xx) on Wed 6 Dec 2006 at 12:14
Interesting, I need to test this in my environments with various machines/OS combinations.
--
Debian GNU/Linux on an IBM Thinkpad T43p

[ Parent | Reply to this comment ]

Re: Supplying routing information using DHCP
Posted by ajt (204.193.xx.xx) on Wed 6 Dec 2006 at 12:44
[ View Weblogs ]
This may be useful when you have a dumb router that you can't add a static route too, such as many of the cheap ADSL units that run their own primitive OS.

--
"It's Not Magic, It's Work"
Adam

[ Parent | Reply to this comment ]

Re: Supplying routing information using DHCP
Posted by lab (86.201.xx.xx) on Thu 7 Dec 2006 at 12:42
I am considering buying my first ADSL router.

1) What is a "dumb" router?

2) How can I tell whether a given router is or is not "dumb"?



L.A.B.

[ Parent | Reply to this comment ]

Re: Supplying routing information using DHCP
Posted by ajt (84.12.xx.xx) on Thu 7 Dec 2006 at 20:16
[ View Weblogs ]
Routers do a pretty basic job, and the most basic ADSL routers run a closed source operating system that you can't alter. If they don't offer a function that you want you are stuck.

The more powerful routers, or a PC running a linux/bsd based OS are usually more flexible, and configurable.

A PC running something like IP Cop and some commercial ADSL routers that can be flashed with a custom system, give you ultimate control.

Do a google search for ADSL routers and linux and you should get a few hits of the devices that can be tinkered with.

--
"It's Not Magic, It's Work"
Adam

[ Parent | Reply to this comment ]

Re: Supplying routing information using DHCP
Posted by endecotp (62.253.xx.xx) on Wed 6 Dec 2006 at 20:20
[ View Weblogs ]
The intro to RFC3442 has some background on this - there other mechanisms that may get the same result. In particular there is RFC1256 "ICMP Router Discovery Messages", and RFC1058 "Routing Information Protocol". I don't know to what extent either of these are supported by the available tools; google finds the "rdisc" daemon for the client end of RFC1256. Any more info anyone?

[ Parent | Reply to this comment ]

Re: Supplying routing information using DHCP
Posted by endecotp (62.253.xx.xx) on Wed 6 Dec 2006 at 23:38
[ View Weblogs ]
I believe that ICMP redirect can only supply routing information for single hosts, not for networks - there is no netmask information. This may or may not matter in practice.

[ Parent | Reply to this comment ]

Re: Supplying routing information using DHCP
Posted by Anonymous (66.179.xx.xx) on Wed 6 Dec 2006 at 21:38
This won't actually happen. Google for 'ICMP Redirect'.

[ Parent | Reply to this comment ]

Re: Supplying routing information using DHCP
Posted by spiney (85.125.xx.xx) on Thu 7 Dec 2006 at 07:01
I know what ICMP redirects are, I just didn't notice default installations really use them automatically. I stopped relying on them long ago, hence my surprise. And checking my network scripts for Linux, I see me disabling them explicitly in /proc/sys/net/ipv4/conf/default/accept_redirects, no wonder I haven't seen this behaviour in my networks. ;)

BTW, Google for 'ICMP Redirect Bad'.
--
Debian GNU/Linux on an IBM Thinkpad T43p

[ Parent | Reply to this comment ]

Re: Supplying routing information using DHCP
Posted by Anonymous (82.211.xx.xx) on Wed 6 Dec 2006 at 19:55
For MS Windows clients you can use the same option, but with number 249.
Some time ago i've created a patch for FreeBSD's dhclient and it works fine:
http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/99534

[ Parent | Reply to this comment ]

Re: Supplying routing information using DHCP
Posted by spiney (85.125.xx.xx) on Fri 8 Dec 2006 at 09:48
Thanks for sparking my interest on the topic again. :) Following your link and eventually finding http://www.xrx.ca/hexroute.htm, I actually can deliver static routes to Windows clients.

BTW, for ISC dhcpd v2.0 one can use
option option-249 <calculated output of hexroute>;
because hexroute itself uses v3.0 syntax.

Once again, thanks for the pointer.

WK
--
Debian GNU/Linux on an IBM Thinkpad T43p

[ Parent | Reply to this comment ]