DHCP is a network management tool to ease provisioning of hosts, not a blade in a network security Swiss army knife. However, the first and most important step in securing any network is developing the required transparency and insight to know exactly what hosts and devices are connected to it. Sadly, that kind of knowledge is out of reach in many networks. Why is it then that so many network administrators are so lazy in how they use DHCP? If the pay-off is knowledge that can lead to an improved security stance, why is the effort automatically considered either enormous or unworthy, and thus dismissed?

The most obvious reasons for such objections are:

  1. Any host can be hard-coded with an IP configuration matching the subnet to which it is attached, or,
  2. MAC address spoofing will allow a host to impersonate another legitimate host.

First, let’s examine how to use client classing for ISC’s DHCP server to restrict known clients to acquiring IP addresses on specific subnets only. In follow-up posts, I’ll look at what techniques and tools that might be used for detection and risk minimization of hosts with hard-coded IP addresses, or those spoofing valid MAC addresses.

A DHCP server must have a complete picture of your network. In the dhcpd.conf configuration file, this is done with subnet statements, one for each subnet in your network:


subnet 10.0.0.0 netmask 255.255.255.0 {
   # Include various options and subnet-specific settings here
}

Hosts can be made known to the DHCP server using host statements.


host pc-101 {
    hardware ethernet xx:xx:xx:xx:xx:xx;
    # other parameters or declarations
}

Address allocation can be dynamic, using address pools, or hosts can be assigned static addresses using fixed-address declarations within the host statement. Static addresses may be desirable for servers and printers, for example. One quick side note: just because addresses are assigned dynamically does not mean that a client will get a different IP address for different leases. The ISC DHCP server stores information about leases in a text database that persists across restarts. In the normal case, a client will continue to be offered the same IP address. One possible cause for different behavior is address pool exhaustion. This leads to re-use of addresses not in use, but previously assigned, causing the clients that had those addresses at one time to get different IP addresses when they connect later.

For dynamic address assignment, we use pool declarations within the subnet statement. A pool declaration must have a range of addresses which can be assigned. If we wish to restrict address assignment to known clients, we can utilize the allow and deny statements to control how the DHCP server should respond to requests. Now our previous subnet statement is modified to include a default gateway and an address pool restricted to known clients (those with host statements):


subnet 10.0.0.0 netmask 255.255.255.0 {
    option routers 10.0.0.1;
    pool {
        # other options
        range 10.0.0.128 10.0.0.254;
        deny unknown-clients;
    }
}

You can modify this to include a pool with allow unknown-clients if you really wanted to assign addresses to all clients which ask for one. This is a good strategy to use if you wish to move towards having full knowledge of all valid clients, but need a period of transition to collect hostnames and hardware addresses. You can also do this using a separate subnet on the same “wire” (multinetting) using a shared network statement. For example:


shared-network “engineering-net” {
    # subnet for known clients
    subnet 10.0.16.0 netmask 255.255.255.0 {
        # parameters and declarations
        pool {
            # other options
            range 10.0.16.128 10.0.16.254;
            deny unknown-clients;
        }
    }

    subnet 10.100.16.0 netmask 255.255.255.0 {
        # parameters and declarations
        pool {
            # other options
            range 10.100.16.128 10.100.16.254;
            allow unknown-clients;
        }
    }
}

We still have one issue to resolve. What if you have multiple subnets, and you really want to restrict your valid clients to specific subnet(s). For example, you do not want your engineering clients to be able to get addresses to the accounting subnet. Simply by having physical access to a port, and plugging in, the DHCP server will assign an address to any known client. This is where client classing comes in. First, we need a class statement:


class “engineering” {
    match pick-first-value (option dhcp-client-identifier, hardware);
}

This declares a class named “engineering” and indicates that members will be identified by their DHCP client identifier or hardware address. ISC’s DHCP configuration allows subclasses, which are described as a speed hack to improve performance. When classes are used to restrict access to address pools, these statements are without scope. I prefer to locate them directly after the associated host statement, like this:


host pc-101 {
    option dhcp-client-identifier 1:xx:xx:xx:xx:xx:xx;
    hardware xx:xx:xx:xx:xx:xx;
}
subclass “engineering” 1:xx:xx:xx:xx:xx:xx;
subclass “engineering” xx:xx:xx:xx:xx:xx;

The “1” in the dhcp client identifier indicates ethernet. For Windows clients, which pass this as the client identifier, it is not necessary to include a subclass statement for the hardware address, but it does no harm. Mac OSX clients do not pass a dhcp client identifier by default; for these, the subclass with the hardware address will always match. With this set of class and subclass statements, we can now change the allow statement in our pool for known clients to:


allow members of “engineering”;

Multiple allow statements can be added, if desired, but this now makes it possible for certain clients to be allowed or denied access to any address pool by the DHCP server.

Advertisements