Using Host Reservations in Kea
  • 27 Jul 2023
  • 12 Minutes to read
  • Contributors
  • Dark
    Light
  • PDF

Using Host Reservations in Kea

  • Dark
    Light
  • PDF

Article Summary

This article applies to the Kea 1.8 branch

The instructions in this article apply to features in the 1.8.X branch of Kea DHCP. The behaviors described have changed in the 1.9 branch: more flexible configuration options were introduced called "reservations-global", "reservations-in-subnet" and "reservations-out-of-pool" to replace the old "reservation-mode" parameter.

What is a Host Reservation?

The "host" in "host reservation" is a device that is interested in DHCP services, commonly a DHCP client or, with explicit configuration, a DHCP relay agent. "Host" and "client" can be used interchangeably most of the time. The "reservation" is an assignment of resources for the host, which can include an IP address, an IPv6 prefix, multiple IPv6 addresses, or any of a number of options.

Host reservations are also known as "address reservations," for their ability to reserve addresses for hosts, or as "static reservations," for their ability to override dynamic allocation from the address pool. In Kea terminology, we refer to them as "host reservations."

  1. When should you use host reservations?
  2. Example configurations
  3. Defining host reservations
  4. Performance considerations
  5. Migrating from ISC DHCP to Kea

When should you use host reservations?

  1. Host reservations can provide a pre-determined, unchanging address or prefix for a host. For example, a client that has special access (e.g., a firewall rule permitting access based on the originating IP address) needs to keep its address permitted in the firewall configuration. Another use case is that of a device with a mission-critical network service which needs to be accessible by IP address in case DNS lookups by name fail.
  2. Host reservations also allow you to provide consistent DHCP options to a host asking for them in an Option Request Option (ORO). You might learn over time that some devices in your network require a specific option in order to function correctly. Another example is associating the correct boot file with a host in the host reservation.
  3. Host reservations are useful when you need a static hostname for your host, such as for a server or application that is commonly accessed via domain name.
  4. They are also useful when you want to assign a client class to a packet to identify the device it's coming from, to further control subnet selection, lease allocation, hook functionality, etc.

Example configurations

A host reservation configuration consists of the criterion for identifying the client or host, followed by a list of reserved resources.

The host is identified in the host reservation through one of the following:

  • duid
  • hw-address
  • flex-id
  • client-id (v4 only)
  • circuit-id (v4 only)

Reserved resources can include any of the following:

  • addresses
  • prefixes (v6 only)
  • option-data
  • hostname
  • client-classes
  • boot-file-name (v4 only)
  • next-server (v4 only)
  • server-hostname (v4 only)

Following is a basic example of a host reservation statement.

"reservations": [
    {
        "duid": "01:02:03:04:05:06:07:08:09:0A",

        "ip-addresses": [
            "2001:db8:1:cafe::1"
        ],
        "prefixes": [
            "2001:db8:2:abcd::/64"
        ],

        "option-data": [
            {
                "code": 17,
                "name": "vendor-opts",
                "data": "4491"
            }
        ],

        "client-classes": [
            "office",
            "special_snowflake"
        ],

        "hostname": "foo.example.com"
    }
]

Example: host identifier

In this example, the host is identified by the device unique identifier (DUID) or duid. Alternatives are hw-address and flex-id. For DHCPv4 only, there are also client-id and circuit-id. Note: you can't specify more than one identifier for any single reservation, but you may have different identifier types over the span of multiple reservations.

The host identifier acts as a filter, telling Kea which identifiers to evaluate. If you only want hosts to be matched by DUID and hardware address, you can achieve this through host-reservation-identifiers: [duid, hw-address]. For best performance, have as few entries as possible; if you don't specify one or more identifiers, then Kea has to search for a possible host reservation using all possible client identifier types, every time it receives a new client request.

Example: addresses & prefixes

The reserved resources follow the host identifier. Every host reservation must reserve at least one resource; if not, Kea complains at configure time. Resources include address, prefixes, options, hostname, and client classes.

In this example, the host is assigned an IPv6 address as well as an IPv6 prefix. These are returned to the host in the IAAddr and IAPrefix options in the response from Kea.

More on this in the Kea Administrator Reference Manual (ARM).

Example: options

Options are reserved through option-data. In this example, the DHCPv6 option with code 17, named OPTION_VENDOR_OPTS, is used to let the host know what vendor the server is hosted on: specifically, enterprise ID 4491.

Options specified in the host reservation are provided ONLY if requested by the host. For custom options, i.e., all those outside the defined standard list (DHCPv4, DHCPv6), a matching option-def must be included in the global Kea configuration, in addition to the option value specified in the host reservation. This is explained in the Kea ARM.

Options defined at the host level have the highest priority. In other words, if there are options defined with the same type on global, subnet, class, and host levels, the most-specific values, which are those at the host level, are used.

Example: hostname

The hostname resource is requested by a DHCP client containing DHCPv6 option code 39 OPTION_CLIENT_FQDN, or DHCPv4 option code 12 OPTION_HOSTNAME. Kea then mirrors the option in the response, but with the configured value. A DNS client is then able to use this information to assign the host to an A record. More on this in the Kea ARM.

Example: classification

A host reservation can also assign client classes, which is like a tag associated with a client. You tag the packet with the client-class so that it can then be used as an additional identification criterion in subnet selection, lease allocation, hook functionality, etc.

Read more on this in the Kea ARM.

Additional reservations for DHCPv4

There are three additional fields that can be reserved for the server to complete in responses under the DHCPv4 packet header:

  • boot-file-name for the file field
  • next-server for the siaddr field
  • server-hostname for the sname field

Defining host reservations

Kea supports defining host reservations (HRs) in the main Kea configuration file, as described above, or in a separate database. If you are establishing only a few host reservations, the overhead of setting up an external database is probably not worth the effort; if you have hundreds of host reservations, they can be easier to maintain in a database.

Using BOTH file and database configurations

It is possible to specify HRs in BOTH the configuration file and an external database. In this case, HRs in the configuration file always have precedence over database HRs, regardless of where in the config file they are specified.

Host Reservations in the Configuration file

Host reservation in the Kea configuration file are read at server start and kept in memory. There are three places (specified here in jq filter notation) in the configuration file where reservations can be defined:

  • Global: .Dhcp[46].reservations
  • Subnet-level: .Dhcp[46].subnet[46][].reservations
  • Shared-network subnet-level: .Dhcp[46]["shared-networks"][].subnet[46][].reservations

Where in the file to put the host reservation configuration is an important decision. The location determines what portion of the network topology is served.

A global reservation can be used to assign certain parameters, such as a hostname or other dedicated, host-specific options, to any client, regardless of that client's location in the network. This is specifically useful for mobile or roaming clients.

It is also possible to assign addresses in a global reservation. This is enabled for corner cases, but it is generally a bad idea, because the address assigned may be unsuitable for the place in the network that the client has roamed to. (For example, the default gateway may be unreachable for that client.) Be aware that the global setting is a server-level configuration setting that excludes in-subnet reservations. You must choose either global or non-global reservations. This is the purpose of the reservation-mode setting.

Reservation mode

Just as reservations can be defined in different places, the reservation-mode setting can be specified in multiple locations in the configuration:

  • Global: .Dhcp[46][reservation-mode]
  • Shared-network-level: .Dhcp[46][shared-networks][][reservation-mode]
  • Subnet-level: .Dhcp[46].subnet[46][][reservation-mode]
  • Shared-network subnet-level: .Dhcp[46][shared-networks][].subnet[46][][reservation-mode]

The effect is local to the specific configuration portion, so a subnet-level reservation-mode only affects the subnet. When there are multiple reservation-modes specified, the one most specific to the matched subnet is taken into account. Thus, the global reservation-mode has the least precedence.

Here are the possible values for reservation-mode:

  • disabled - this is a simple, straightforward switch to disable host reservations altogether. As Kea skips checking for reservations, the server may operate faster in this mode.
  • all - this enables both in-pool and out-of-pool host reservation types. This setting is the default value, and is the safest and most flexible. However, since Kea does the maximum number of checks for reservations, it is also the slowest. It does not check against global reservations.
  • out-of-pool - this allows only out-of-pool host reservations. With this setting in place, the server assumes that all host reservations are for addresses that do not belong to the dynamic pool. Therefore, it can skip the reservation checks when dealing with in-pool addresses, thus improving performance. Do not use this mode if any reservations use in-pool addresses. Caution is advised when using this setting; Kea does not sanity-check the reservations against reservation-mode and misconfiguration may cause problems.
  • global - this allows only global host reservations. With this setting in place, the server searches for reservations for a client only among the defined global reservations. If an address is specified, the server skips additional reservation checks, thus improving performance. Caution is advised when using this setting; Kea does not sanity-check global reservations and it is possible to specify an address in a global reservation that is unreachable or unsuitable for the client.

If not specified in the configuration file, reservation-mode defaults to all.

When set to out-of-pool or all, global reservations are ignored. all causes the allocation engine to search for subnet reservations while verifying that the reserved address or prefix is not leased by another client. out-of-pool optimizes performance by leaving out the verification and should only be used if you are certain that reserved addresses/prefixes don't overlap with defined pools.

Why does pre-1.9 Kea not allow both global and in-subnet reservations?

Kea doesn't allow both global and in-subnet reservations in order to simplify the logic for parsing the configuration file which reduces the processing required. Kea warns you at configure time if you have overlapping subnets or shared-networks, to prevent conflicts, and reservations are also checked for overlap with pools in their subnet. But there could theoretically be two reservations for the same host between global reservations and shared-network/subnet-level reservations. To check this would require evaluating the entire configuration twice for every client request, which would be very inefficient.

Since Kea versions 1.9.1 and 2.0.0, the new flags named "reservations-global", "reservations-in-subnet" and "reservations-out-of-pool" can be configured independently, allowing both global and in-subnet reservations to coexist.

Notice that for global, the client does not need to match a pool.

The following diagram may assist you in determining which reservation-mode setting is right for you:
image.png

Configuring databases

When configuring database credentials in the hosts-database or hosts-databases fields in the file configuration, reservations are dynamically searched at allocation time in the databases. The tables that administrators need to populate are hosts, ipv6_reservations, dhcp4_options, and dhcp6_options.

An easy way to populate them consistently is by using the host_cmds hook. Refer to the Kea ARM for instructions.

Performance considerations

In a typical network, clients with host reservations are the exception, rather than the rule. However, if host reservations are used, Kea has to check for the existence of a reservation with every client request (see this flow chart in the ARM). This can be a significant performance burden, which is why Kea has options to limit both the number of identifiers evaluated and the scope of the reservation.

For more information on Kea performance optimization, see this related article.


Migrating from ISC DHCP to Kea

There are a few differences in the handling of host reservations that should be considered when migrating from ISC DHCP to Kea.

Notable differences:

ISC DHCP Kea
Reservations are global only. Reservations are configurable at the global level as well as at the subnet and shared-network levels.
A single reserved address can be specified under fixed-address6 for a v6 host declaration. For multiple addresses, specify multiple host declarations. Multiple reserved addresses can be specified under ip-addresses under a single v6 host reservation.
ISC DHCP starts without a warning even if configured with a `fixed-address` statement that is not viable on the subnet (or shared network) where the client is attached. Kea does not start if configured with an address or prefix that is not viable on its subnet; it displays an error. This is not true for global reservations: global reservations are not checked against subnets.
The host declarations only match a client if one of the fixed-address statements is viable on the subnet (or shared network) where the client is attached. As stated above, Kea does not work if a subnet-level reservation is not viable. Global reservations are not checked against subnets, so are offered regardless.

The Kea Migration Assistant (keama) can migrate some elements of your existing ISC DHCP configuration to a new Kea configuration. Specifically, the -N option is relevant to host reservation migration, with N being the subnet ID: by default, HRs are migrated as global HRs in a Kea configuration. Running keama -N causes them to be placed in the appropriate subnet.

Example command: keama -6 -i ./dhcp.conf -o ./kea.conf

Corresponding configuration fields from ISC DHCP to Kea DHCP:

ISC DHCP Kea
not supported outside hardware address duid: <value>
hardware ethernet <value> hw-address: <value>
host-identifier option dhcp6.client-id <value> client-id: <value> or flex-id with identifier-expression: option[61].hex
host-identifier option agent.circuit-id <value> circuit-id: <value> or flex-id with identifier-expression: option[1].hex
fixed-address4 <value> ip-address: <value>
fixed-address6 <value> ip-addresses: [ <value> ]
fixed-prefix6 <value> prefixes: [ <value> ]
option dhcp6.name-servers <value> option-data: [ { code: 23, data: <value>, name: dns-servers } ]

Example 1 for ISC DHCP:

host myclient {
	# The entry is looked up by this
	host-identifier option
		dhcp6.client-id 00:01:00:01:00:04:93:e0:00:00:00:00:a2:a2;

	# A fixed address
	fixed-address6 3ffe:501:ffff:100::1234;

	# A fixed prefix
	fixed-prefix6 3ffe:501:ffff:101::/64;

	# Override of the global definitions,
	# works only when an address or prefix is assigned
	option dhcp6.name-servers 3ffe:501:ffff:100:200:ff:fe00:4f4e;
}

Example 1 migrated to Kea:

{
  "Dhcp6": {
    /// The flexible host identifier is a premium feature
    "hooks-libraries": [
      {
        /// Please update the path here
        "library": "/path/libdhcp_flex_id.so",
        "parameters": {
          "identifier-expression": "option[1].hex"
        }
      }
    ],
    "reservation-mode": "global",
    "reservations": [
      {
        "hostname": "myclient",
        "flex-id": "00010001000493e000000000a2a2",
        # The entry is looked up by this
        # A fixed address
        "ip-addresses": [
          "3ffe:501:ffff:100::1234"
        ],
        "prefixes": [
          # A fixed prefix
          "3ffe:501:ffff:101::/64"
        ],
        "option-data": [
          # Override of the global definitions,
          # works only when an address or prefix is assigned
          {
            "space": "dhcp6",
            "name": "dns-servers",
            "code": 23,
            "data": "3ffe:501:ffff:100:200:ff:fe00:4f4e"
          }
        ]
      }
    ]
  }
}

Example 2 for ISC DHCP:

host otherclient {
        # This host entry is hopefully matched if the client supplies a DUID-LL
        # or DUID-LLT containing this MAC address.
        hardware ethernet 01:00:80:a2:55:67;

        fixed-address6 3ffe:501:ffff:100::4321;
}

Example 2 migrated to Kea:

{
  "Dhcp6": {
    "host-reservation-identifiers": [
      "hw-address"
    ],
    "reservation-mode": "global",
    "reservations": [
      {
        "hostname": "otherclient",
        # This host entry is hopefully matched if the client supplies a DUID-LL
        # or DUID-LLT containing this MAC address.
        "hw-address": "01:00:80:a2:55:67",
        "ip-addresses": [
          "3ffe:501:ffff:100::4321"
        ]
      }
    ]
  }
}