home January 01, 2017

dhclient tutorial


dhclient.con examples

Machines on a network have a few ways they can be set up with an ip address, routes and other information. They can be configured statically with all of the values saved locally on the clients. This is a bit inflexible. Another method is to use dhclient to retrieve information about the network from a DHCP server.

dhclient is the Dynamic Host Configuration Protocol (DHCP) Client one would use to allow a client to connect to a DHCP server. The server would then supply the ip address and any other information the client would need to use the network or to connect to the outside world.

The client machine running dhclient will broadcast packets out on the network. When the DHCP server receives the packets it will send a response back and that is when our client will negotiate the connection. Once connected the client will ask for the information listing in the config file. if the server supplies all the required values the client will configure the interface and be on the network.

Some network DHCP servers are better than others, but all can fail you at times. This configuration file is a bit aggressive in its timings. You may wish to edit the values to better suite your needs. If you are connecting to an ISP's DHCP server these values work quite well. Think of this config as an impatient user asking for information over and over and over until they get it. Our goal is to get a new ip address and the rest of the requested information NOW, so we can get on the network.

The following is an example dhclient.conf configuration file. You are welcome to copy and paste it as it is a fully working example. The default conf on your system might be located in /etc/dhclient.conf .

#
# moneyslow.com  dhclient.conf  DHCP Client Configuration
#

backoff-cutoff 2;
initial-interval 1;
link-timeout 10;
reboot 0;
retry 10;
select-timeout 0;
timeout 30;

interface "em0"
 {
  supersede host-name "spaceship";
  supersede domain-name "domain.home";
  prepend domain-name-servers 127.0.0.1;
  request subnet-mask,
          broadcast-address,
          routers,
          domain-name,
          domain-name-servers,
          host-name;
  require routers,
          subnet-mask,
          domain-name-servers;
 }

What does it all mean?

backoff-cutoff 2; The client uses an exponential backoff algorithm with some randomness, so that if many clients try to configure themselves at the same time, they will not make their requests in lockstep. The backoff-cutoff statement determines the maximum amount of time that the client is allowed to back off. It defaults to 15 seconds.

initial-interval 1; The initial-interval statement sets the amount of time between the first attempt to reach a server and the second attempt to reach a server. Each time a message is sent, the interval between messages is incremented by twice the current interval multiplied by a random number between zero and one. If it is greater than the backoff-cutoff amount, it is set to that amount. It defaults to ten seconds.

link-timeout 10; The link-timeout statement sets the amount of time to wait for an interface link before timing out. The default value is 10 seconds, but the special value 0 requests that dhclient not wait for a link state change before timing out.

reboot 0; When the client is restarted, it first tries to reacquire the last address it had. This is called the INIT-REBOOT state. If it is still attached to the same network it was attached to when it last ran, this is the quickest way to get started. The reboot statement sets the time that must elapse after the client first tries to reacquire its old address before it gives up and tries to discover a new address. By default, the reboot timeout is ten seconds.

retry 10; The retry statement determines the time that must pass after the client has determined that there is no DHCP server present before it tries again to contact a DHCP server. By default, this is five minutes (300).

select-timeout 0; The select-timeout is the time after the client sends its first lease discovery request at which it stops waiting for offers from servers, assuming that it has received at least one such offer. If no offers have been received by the time the select-timeout has expired, the client will accept the first offer that arrives. By default, the select-timeout is zero seconds - that is, the client will take the first offer it sees.

timeout 30; The timeout statement determines the amount of time that must pass between the time that the client begins to try to determine its address and the time that it decides that it's not going to be able to contact a server. By default, this timeout is sixty seconds. After the timeout has passed, if there are any static leases defined in the configuration file, or any leases remaining in the lease database that have not yet expired, the client will loop through these leases attempting to validate them, and if it finds one that appears to be valid, it will use that lease's address. If there are no valid static leases or unexpired leases in the lease database, the client will restart the protocol after the defined retry interval.

interface "em0" The interface lease statement is used to indicate the interface on which the lease is valid. If set, this lease will only be tried on a particular interface. When the client receives a lease from a server, it always records the interface number on which it received that lease. If predefined leases are specified in the dhclient.conf file, the interface should also be specified, although this is not required.

Supersede -- using our own values

supersede host-name "spaceship"; This machine will always override the host name sent from the DHCP server with the string listed here.

supersede domain-name "domain.home"; The domain name listed here will always override what the DHCP server sends.

Prepend -- putting our options at the top

prepend domain-name-servers 127.0.0.1; If you use your own local dns server or dns cache server then put its ip here. This example has a dns server running on localhost that we want our machine to use instead of the ones the DHCP server sends. If the DHCP server sends a DHCP server ip then it will be put under our listing in /etc/resolv.conf .

Request -- asking for what we want

The request directive asks the DHCP server for the values you specify. Note that this does not mean the server will send you these values, just that you will ask the server for them. The config file will ask for the following:

request subnet-mask,
          broadcast-address,
          routers,
          domain-name,
          domain-name-servers,
          host-name;

Require -- what we need to see

The require directive states the options that _must_ be returned from the DHCP server for the communication to be considered successful. If these values are not returned dhclient will log an error.

require routers,
          subnet-mask,
          domain-name-servers;

Executing the daemon

Manually testing dhclient

Once the configuration is in place you can start the daemon manually for testing. The binary "dhclient" is combined with the interface name, like "em0". With the following command dhclient will ask for all of the information specified in the /etc/dhclient.conf file and apply it to the interface em0.

dhclient em0

Starting dhclient on boot

Instead of executing dhclient manually you can configure the interface to use DHCP. On our example OpenBSD system the /etc/hostname.em0 file would contain the following, "dhcp NONE NONE NONE". This means when the interface is brought up it should execute "dhclient em0" and gets its information from the dhcp server.

/home/user/ ]  cat /etc/hostname.em0
dhcp NONE NONE NONE

Questions?

How do I get a new IP on Verizon's FIOS using dhclient on OpenBSD or FreeBSD?

Verizon FIOS requires that your external network interface (em0) have the same MAC as the Actiontec MI424 they provide you. So, you can not just randomize the MAC address. The second problem is the native version of dhclient that comes with OpenBSD. OpenBSD's version of dhclient is very secure, but does not have all of the options of the Internet Systems Consortium, Inc. (ISC) version of dhclient everyone else uses; the option "-r" for release for example. For this reason we will need to download the latest version of ISC's dhclient, compile it and keep the dhclient binary off to the side. We do not need to replace OpenBSD's dhclient because we like the tight security it offers. These steps are quite easy.

Download the latest version of dhclient from ISC's DHCP download page. and compile the source code with "./configure && make". Note, we are _NOT_ replacing the version of dhclient that comes with OpenBSD. Copy the dhclient binary found in the "Client" directory to a place you keep your scripts or tools. For our instructions we will put our copy in "/tools" and name it like so, "/tools/dhclient_isc". You do not need any of the other DHCP files and they can be removed.

Stop the currently running dhclient that comes with OpenBSD with "pkill dhclient" and remove the file, "/var/db/dhclient.leases.em0". We do not want OpenBSD's dhclient to know about the old ip that the leases files records when it starts again.

Next, execute the ISC dhclient so it renews the current ip. This step is so the ISC version knows what ip it needs to release. Just run "/tools/dhclient_isc em0". Then release the current ip with "/tools/dhclient_isc -r em0". The em0 interface will probably go offline now. Note that the "-r" flag will kill the process of ISC's dhclient as soon as it releases the current ip to the ISP's DHCP server. Clean up by removing the leases file the ISC version of dhclient made with the command, "rm -rf /var/db/dhclient.leases".

Finally, execute OpenBSD's dhclient to get a new ip and get back on-line using "dhclient em0". If you do an "ifconfig" now you should notice your ip is different.

So, in the end we have 4 steps to go through. Kill the running OpenBSD's dhclient, execute ISC's "dhclient_isc em0", release the ip using ISC with "dhclient_isc -r em0" and finally execute OpenBSD's "dhclient em0" to go get the new ip.

Lets make this even easier using a shell script:

#
## moneyslow.com FIOS - Get a new ip script 
##   (external interface is "em0")
#

## kill OpenBSD's dhclient and remove db file
pkill dhclient
rm -rf /var/db/dhclient.leases.em0
sleep 2

## use ISC's dhclient to renew, release and cleanup 
/tools/dhclient_isc em0
/tools/dhclient_isc -r em0
rm -rf /var/db/dhclient.leases
sleep 2

## start OpenBSD's dhclient and get back online
dhclient em0

## check on external interface
ifconfig em0

How can I see a history of dhclient negotiations?If you are using OpenBSD you can cat the dhclient database file. it will show you all of the successful communications between a DHCP server and client.

cat /var/db/dhclient.leases.em0 

dhclient seems to be ignoring DHCPOFFERS sometimes. Whats wrong?If you look at your dhclient logs you may see your client asking the dhcpd server for a new ip and the request seems to fail. For example, in this section of the dhclient logs:

# dhclient em0
DHCPDISCOVER on em0 to 255.255.255.255 port 67 interval 5
DHCPDISCOVER on em0 to 255.255.255.255 port 67 interval 7
DHCPDISCOVER on em0 to 255.255.255.255 port 67 interval 10
DHCPOFFER from 10.20.30.1
DHCPREQUEST on em0 to 255.255.255.255 port 67
DHCPREQUEST on em0 to 255.255.255.255 port 67
DHCPDISCOVER on em0 to 255.255.255.255 port 67 interval 5
DHCPDISCOVER on em0 to 255.255.255.255 port 67 interval 10

DHCP process goes:

  1. Discover - try to find a dhcpd server.
  2. Offer - the dhcpd server send your client an offer that it will supply an ip.
  3. Request - your client requests an ip from the dhcp server who offered.
  4. Ack - the dhcpd server acknowledges the request with the ip information.

In the above transaction log, the client sends out discovery packets trying to find a dhcpd server. The server from ip address 10.20.30.1 offers to supply our client with an ip. Our client then requests an acknowledgment of the information from the dhcpd server (lines 5 & 6), but never gets a response. So, our client then goes back to trying to find a working or non-busy dhcpd server.

The server at 10.20.30.1 made the offer, but did not respond to the client's request. Servers may offer the same address to multiple clients concurrently; clients can only use an address after it has been confirmed. Given that it can't use that address, the client goes back into discovery mode to find another dhcpd server.

This may happen id the dhcpd server is too busy or loaded or the request from our client may have been dropped by the network or the TCP stack of the receiving machine.