Skip to main content
RunBook Academy

VyOSXLVI · DHCP ServicesDHCP

DHCPv4 static-mapping — fixed address by MAC, hostname, reservations

Intermediate⏱ ~18 minset service dhcp-server shared-network-name subnet static-mappingshow dhcp server leasesarp -antcpdump -i eth1.10 -n port 67 or port 68 -vvvyos

What you'll learn

  • Configure a DHCP static-mapping by MAC address
  • Bind a fixed IP address and hostname to a static-mapping
  • Override per-host DHCP options (DNS, lease, default-router)
  • Recognise the production failure modes where two hosts collide on the same fixed address

Prerequisites

Verified against VyOS 1.5.x LTS (circinus) · VyOS 1.4.x (sagitta) — legacy · FRRouting 10.x (VyOS 1.5) · Linux kernel 6.6 LTS (VyOS 1.5 base) · strongSwan 5.9.x (IPsec) · WireGuard 1.0.x (kernel module + userspace tooling) · 2026-08-15

Not yet marked complete on this device.

A static-mapping binds a host’s MAC address (or client-identifier) to a fixed IP address inside a DHCP pool. The host still uses DHCP — it broadcasts DHCPDISCOVER and the server replies with the reserved address — but the address never changes. The static-mapping is the production pattern for printers, VoIP phones, network equipment, point-of-sale terminals, and any host that other systems reach by IP.

This lesson covers the static-mapping configuration, the per-host option override, the relationship between the dynamic range and the static reservations, and the failure modes where two hosts collide on the same fixed address.

What a static-mapping does

flowchart LR
  H1["Host<br/>MAC aa:bb:cc:dd:ee:f0"] -->|DHCPDISCOVER| S["VyOS DHCP server"]
  H2["Host<br/>MAC 11:22:33:44:55:66"] -->|DHCPDISCOVER| S
  S -->|DHCPOFFER 192.0.2.50| H1
  S -->|DHCPOFFER 192.0.2.51| H2
  S -.->|"DHCPDISCOVER<br/>MAC 99:88:77:66:55:44"| X["No reservation<br/>falls through to dynamic range"]
  X -->|DHCPOFFER from pool| Y["First-come lease"]

The diagram shows the static-mapping flow. Each MAC has a fixed answer in the offer; hosts without a reservation fall through to the dynamic range. The reservations and the dynamic range share the same subnet but the reservations always win.

Configuring a static-mapping

configure
set service dhcp-server shared-network-name LAN1 subnet 192.0.2.0/24 static-mapping printer-01 ip-address '192.0.2.50'
set service dhcp-server shared-network-name LAN1 subnet 192.0.2.0/24 static-mapping printer-01 mac-address '00:1a:2b:3c:4d:5e'
set service dhcp-server shared-network-name LAN1 subnet 192.0.2.0/24 static-mapping desk-east ip-address '192.0.2.51'
set service dhcp-server shared-network-name LAN1 subnet 192.0.2.0/24 static-mapping desk-east mac-address '12:34:56:78:9a:bc'
commit
save

Each static-mapping is named (the operator picks a free-form identifier like printer-01 or desk-east), has an ip-address (the reserved address), and a mac-address (the host’s hardware address). When the host sends DHCPDISCOVER with that MAC, Kea returns the reserved address.

Static-mapping with hostname and per-host options

configure
set service dhcp-server shared-network-name LAN1 subnet 192.0.2.0/24 static-mapping printer-01 ip-address '192.0.2.50'
set service dhcp-server shared-network-name LAN1 subnet 192.0.2.0/24 static-mapping printer-01 mac-address '00:1a:2b:3c:4d:5e'
set service dhcp-server shared-network-name LAN1 subnet 192.0.2.0/24 static-mapping printer-01 host-name 'lobby-printer'
set service dhcp-server shared-network-name LAN1 subnet 192.0.2.0/24 static-mapping printer-01 lease '2592000'
commit
save

Per-host overrides:

  • host-name — option 12, hostname the server tells the host. The host uses this as its hostname and may register it via dynamic DNS.
  • lease — per-host lease time, in seconds. Printers often get longer leases (a month) because they rarely change networks.
  • dns-server — per-host DNS server override. A static-mapping can override the subnet default if a specific host needs a different resolver.
  • default-router — per-host default-router override. Used for hosts on multi-router subnets or for hosts that must use a specific gateway.

Static-mapping outside the dynamic range

A common production pattern: the static-mapping addresses are outside the dynamic range. The dynamic range is 192.0.2.50-192.0.2.200; the static mappings are 192.0.2.10-192.0.2.40 (a lower range reserved for fixed hosts).

configure
set service dhcp-server shared-network-name LAN1 subnet 192.0.2.0/24 range 0 start '192.0.2.50'
set service dhcp-server shared-network-name LAN1 subnet 192.0.2.0/24 range 0 stop '192.0.2.200'
set service dhcp-server shared-network-name LAN1 subnet 192.0.2.0/24 static-mapping printer-01 ip-address '192.0.2.10'
set service dhcp-server shared-network-name LAN1 subnet 192.0.2.0/24 static-mapping desk-east ip-address '192.0.2.11'
commit
save

This pattern makes pool exhaustion impossible to collide with a reservation. The dynamic range and the static range are disjoint by construction.

Static-mapping with client-identifier (option 61)

Some hosts (notably Windows clients and many VoIP phones) identify themselves with a client-identifier (option 61) instead of (or in addition to) their MAC. Kea prefers the client-identifier when the host sends one. The operator configures the static-mapping with client-identifier instead of (or alongside) mac-address:

configure
set service dhcp-server shared-network-name LAN1 subnet 192.0.2.0/24 static-mapping voip-01 ip-address '192.0.2.20'
set service dhcp-server shared-network-name LAN1 subnet 192.0.2.0/24 static-mapping voip-01 client-identifier '01:aa:bb:cc:dd:ee:f0'
commit
save

The client-identifier format is a one-byte type (0x01 for hardware-type Ethernet) followed by the MAC address. Kea matches the full client-identifier string verbatim.

How the result is validated

show dhcp server leases
arp -an

show dhcp server leases shows the static reservations alongside the dynamic leases. The static reservations have State: active and the configured ip-address. The operator can verify the host’s MAC is bound to the right address.

vyos@R1:~$ show dhcp server leases
IP address    MAC address        State    Lease expiration    Pool    Hostname
------------  -----------------  -------  ------------------  ------  -----------
192.0.2.10    00:1a:2b:3c:4d:5e  active   2026/09/14 01:23:45 LAN1    lobby-printer
192.0.2.11    12:34:56:78:9a:bc  active   2026/08/16 01:24:11 LAN1    desk-east
192.0.2.50    aa:bb:cc:dd:ee:f0  active   2026/08/16 01:25:33 LAN1    laptop-rev

arp -an confirms the host has the address and the MAC matches the reservation. If the operator sees a different MAC at the reserved address, the host has been swapped (or someone plugged in a rogue device with the same address).

vyos@R1:~$ arp -an | grep 192.0.2.10
? (192.0.2.10) at 00:1a:2b:3c:4d:5e [ether] on eth1.10

Capturing the reservation match

A packet capture shows the reservation working:

vyos@R1:~$ tcpdump -i eth1.10 -n port 67 or port 68 -vv -c 4
12:00:01.234 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:1a:2b:3c:4d:5e
  Option 53, length 1: DHCP Discover
  Option 61, length 7: Client-Identifier 01:00:1a:2b:3c:4d:5e
12:00:01.236 IP 192.0.2.1.67 > 192.0.2.10.68: BOOTP/DHCP, Reply
  Option 53, length 1: DHCP Offer
  Option 54, length 4: Server Identifier 192.0.2.1
  yiaddr 192.0.2.10  <-- reserved, NOT from pool
12:00:01.245 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:1a:2b:3c:4d:5e
  Option 53, length 1: DHCP Request
12:00:01.247 IP 192.0.2.1.67 > 192.0.2.10.68: BOOTP/DHCP, Reply
  Option 53, length 1: DHCP ACK

The yiaddr field in the OFFER is the reserved address (192.0.2.10), not the next free address in the pool. The client-identifier is preserved across the four messages.

How it fails

The production failure modes a routing engineer must recognise:

  • Reservation outside the subnet. The static-mapping is configured for 192.0.2.50 but the subnet is 192.0.2.0/24. The operator may have a typo (192.0.2.250 versus 192.0.2.50). Kea accepts the configuration but the address is not in any pool or subnet.
  • Reservation inside the dynamic range. The reserved address is 192.0.2.100 and the dynamic range is 192.0.2.50-192.0.2.200. The reservation wins for the matching MAC, but a second host with a different MAC can be offered 192.0.2.100 if the first host is offline. When the first host returns, it gets the address (reservation wins) but the second host gets a different address. The fix: keep the static and dynamic ranges disjoint.
  • MAC changed without reservation update. A printer is replaced; the new printer has a different MAC; the old MAC still has the reservation. The new printer falls through to the dynamic pool. Fix: update the mac-address of the static-mapping.
  • Client-identifier mismatch. The host sends a client-identifier that doesn’t match the configured mac-address. The reservation doesn’t fire. Fix: configure the client-identifier, or check the host’s option 61 settings.
  • Two reservations on the same MAC. Two static-mappings reference the same MAC with different addresses. Kea uses the first match; the second is silently ignored. Fix: search for the MAC across all static-mappings.

Rollback

The recovery from a broken static-mapping:

  • Wrong address: delete service dhcp-server shared-network-name LAN1 subnet 192.0.2.0/24 static-mapping printer-01 ip-address and re-add the correct address.
  • Wrong MAC: delete service dhcp-server shared-network-name LAN1 subnet 192.0.2.0/24 static-mapping printer-01 mac-address and re-add.
  • Reservation collision: identify the duplicate MAC across all static-mappings and remove or rename the duplicate.

The VyOS configuration rollback (rollback N) restores the previous revision if the change breaks production.

Production discipline

Cross-course references

  • XLVI-VyOS-DHCP (vyos-xlvi-01-dhcp-server) covers the shared-network / subnet / range structure this lesson extends with reservations.
  • XLVII-VyOS-MgmtPlane (vyos-xlvii-04-oob-access) covers the OOB network that should NOT have static reservations in the production DHCP scope.
  • LIV-VyOS-Automation (vyos-liv-03-config-as-code) covers the configuration-as-code pipeline that manages the static-mapping list from a version- controlled source.

Quiz

Knowledge check · 4 questions

  1. Q1. Why might a DHCPv4 static-mapping by MAC address fail to apply to a host that sends a client-identifier (option 61)?

  2. Q2. A DHCPv4 static-mapping's reserved address must be inside the dynamic range to be honoured.

  3. Q3. An operator configures a static-mapping for a printer at 192.0.2.50 with MAC 00:1a:2b:3c:4d:5e. The printer is replaced with a new model. The new printer has a different MAC. What is the symptom and what is the fix?

    The operator configured a static-mapping with the original printer's MAC. The printer was swapped for a new model. The new printer has a different MAC and does not match the reservation. The new printer falls through to the dynamic range and gets a random address from the pool. The old reservation sits unused in the configuration.

  4. Q4. An operator configures 50 static-mappings for 50 printers in a shared-network. After configuration, 25 printers receive their reserved addresses and 25 receive dynamic pool addresses. What is happening?

    The static-mappings and the dynamic pool share the same subnet. The dynamic range is 192.0.2.50-192.0.2.200 (151 addresses). The 50 static-mappings reserve addresses throughout the same range as the pool. The DHCP race: when a printer boots and broadcasts DHCPDISCOVER, the server checks reservations first; if the MAC matches, the printer gets the reserved address. If the MAC doesn't match (because of a typo, swapped hardware, or client-identifier mismatch), the printer falls through to the pool. Half the printers fall through because their MACs don't match the configured reservations.

Passing score: 75%. Answers are checked in this browser.