FreeBSD.software
Home/Guides/isc-dhcp-server on FreeBSD: DHCP Server Review
review·2026-04-09·11 min read

isc-dhcp-server on FreeBSD: DHCP Server Review

Review of isc-dhcp-server on FreeBSD: installation, subnet configuration, address pools, failover clustering, relay agent setup, migration path to Kea, and comparison with dnsmasq.

isc-dhcp-server on FreeBSD: DHCP Server Review

ISC DHCP (Internet Systems Consortium DHCP) is the most widely deployed DHCP server implementation in production networks. It has been the reference implementation for DHCP since the 1990s and supports both DHCPv4 and DHCPv6. ISC officially declared isc-dhcp end-of-life at the end of 2022, with no further maintenance releases, but it remains heavily deployed and is still available in the FreeBSD package repository. Its successor, ISC Kea, is the recommended path forward for new deployments.

This review covers ISC DHCP installation and configuration on FreeBSD, subnet and pool management, failover for high availability, relay agent configuration, the migration path to Kea, and a comparison with dnsmasq.

Why ISC DHCP Still Matters

Despite the end-of-life status, ISC DHCP remains relevant for several reasons:

  • It is already deployed on millions of networks worldwide
  • Kea migration requires planning and is not always straightforward
  • Many administrators are familiar with its configuration syntax
  • It works and has decades of battle-tested reliability
  • Some features (particularly failover) are mature in ISC DHCP while still evolving in Kea

For new deployments, ISC Kea is the better choice. For existing deployments, understanding ISC DHCP and planning a migration timeline is the practical approach.

Installation on FreeBSD

Package Installation

sh
pkg install isc-dhcp44-server

This installs the DHCPv4 server. For DHCPv6:

sh
pkg install isc-dhcp44-server

The same package handles both protocols. The binaries are:

  • /usr/local/sbin/dhcpd -- DHCP server daemon
  • /usr/local/sbin/dhcrelay -- DHCP relay agent
  • /usr/local/etc/dhcpd.conf -- Main configuration file
  • /var/db/dhcpd/dhcpd.leases -- Lease database

Enable and start the service:

sh
sysrc dhcpd_enable="YES" sysrc dhcpd_ifaces="em1" service isc-dhcpd start

The dhcpd_ifaces variable specifies which network interfaces dhcpd listens on. Set this to your internal/LAN interface.

Verify Installation

sh
dhcpd --version service isc-dhcpd status

Basic Configuration

Minimal Working Configuration

Create /usr/local/etc/dhcpd.conf:

sh
# /usr/local/etc/dhcpd.conf # Global options option domain-name "example.com"; option domain-name-servers 10.0.1.1, 10.0.1.2; default-lease-time 3600; max-lease-time 7200; authoritative; log-facility local7; # Subnet declaration subnet 10.0.1.0 netmask 255.255.255.0 { range 10.0.1.100 10.0.1.200; option routers 10.0.1.1; option subnet-mask 255.255.255.0; option broadcast-address 10.0.1.255; option ntp-servers 10.0.1.1; }

Test the configuration before starting:

sh
dhcpd -t -cf /usr/local/etc/dhcpd.conf

Restart the service:

sh
service isc-dhcpd restart

Logging Configuration

ISC DHCP logs to syslog. Configure /etc/syslog.conf to capture DHCP messages:

sh
# Add to /etc/syslog.conf local7.* /var/log/dhcpd.log

Create the log file and restart syslog:

sh
touch /var/log/dhcpd.log service syslogd restart

Add log rotation in /etc/newsyslog.conf:

sh
/var/log/dhcpd.log 644 7 1000 * JC

Subnet and Pool Configuration

Multiple Subnets

sh
# /usr/local/etc/dhcpd.conf # Office subnet subnet 10.0.1.0 netmask 255.255.255.0 { range 10.0.1.100 10.0.1.200; option routers 10.0.1.1; option domain-name-servers 10.0.1.1, 10.0.1.2; default-lease-time 3600; max-lease-time 7200; } # Server subnet subnet 10.0.2.0 netmask 255.255.255.0 { range 10.0.2.100 10.0.2.150; option routers 10.0.2.1; option domain-name-servers 10.0.1.1, 10.0.1.2; default-lease-time 86400; max-lease-time 172800; } # Guest WiFi (short leases, isolated) subnet 10.0.10.0 netmask 255.255.255.0 { range 10.0.10.50 10.0.10.250; option routers 10.0.10.1; option domain-name-servers 1.1.1.1, 8.8.8.8; default-lease-time 1800; max-lease-time 3600; }

Address Pools with Classes

Pools allow assigning different ranges to different clients:

sh
# Define classes based on vendor ID class "printers" { match if substring (option vendor-class-identifier, 0, 6) = "Hewlet"; } class "phones" { match if substring (option vendor-class-identifier, 0, 5) = "Cisco"; } subnet 10.0.1.0 netmask 255.255.255.0 { option routers 10.0.1.1; pool { allow members of "printers"; range 10.0.1.220 10.0.1.240; default-lease-time 86400; } pool { allow members of "phones"; range 10.0.1.200 10.0.1.219; default-lease-time 86400; option tftp-server-name "10.0.1.5"; } pool { deny members of "printers"; deny members of "phones"; range 10.0.1.100 10.0.1.199; } }

Static Reservations

Fixed addresses for specific hosts based on MAC address:

sh
host web-server { hardware ethernet 00:1a:2b:3c:4d:5e; fixed-address 10.0.2.10; option host-name "web-server"; } host db-server { hardware ethernet 00:1a:2b:3c:4d:5f; fixed-address 10.0.2.11; option host-name "db-server"; } host printer-lobby { hardware ethernet 00:aa:bb:cc:dd:01; fixed-address 10.0.1.220; option host-name "printer-lobby"; }

Shared Networks

When multiple subnets exist on the same physical network:

sh
shared-network office-floor3 { subnet 10.0.3.0 netmask 255.255.255.0 { range 10.0.3.100 10.0.3.200; option routers 10.0.3.1; } subnet 10.0.4.0 netmask 255.255.255.0 { range 10.0.4.100 10.0.4.200; option routers 10.0.4.1; } }

Failover Configuration

ISC DHCP supports failover between two servers for high availability. One server is designated as primary, the other as secondary. They synchronize lease data and can serve clients independently if one fails.

Primary Server

sh
# /usr/local/etc/dhcpd.conf on primary (10.0.1.5) failover peer "dhcp-failover" { primary; address 10.0.1.5; port 647; peer address 10.0.1.6; peer port 647; max-response-delay 60; max-unacked-updates 10; mclt 3600; split 128; load balance max seconds 3; } subnet 10.0.1.0 netmask 255.255.255.0 { option routers 10.0.1.1; pool { failover peer "dhcp-failover"; range 10.0.1.100 10.0.1.200; } }

Secondary Server

sh
# /usr/local/etc/dhcpd.conf on secondary (10.0.1.6) failover peer "dhcp-failover" { secondary; address 10.0.1.6; port 647; peer address 10.0.1.5; peer port 647; max-response-delay 60; max-unacked-updates 10; load balance max seconds 3; } subnet 10.0.1.0 netmask 255.255.255.0 { option routers 10.0.1.1; pool { failover peer "dhcp-failover"; range 10.0.1.100 10.0.1.200; } }

Key failover parameters:

  • mclt (Maximum Client Lead Time): Maximum time the primary can extend a lease beyond what the secondary knows about. Set only on the primary.
  • split: How the address pool is divided between servers (0-255, where 128 is an even 50/50 split).
  • max-response-delay: How long to wait before assuming the peer is down.
  • max-unacked-updates: Number of lease updates that can be pending acknowledgment.

Monitoring Failover

sh
# Check failover state omshell << 'EOF' server localhost port 7911 connect new failover-state set name = "dhcp-failover" open EOF

DHCP Relay Agent

When DHCP clients and servers are on different network segments, a relay agent forwards DHCP messages.

FreeBSD as Relay Agent

sh
pkg install isc-dhcp44-relay sysrc dhcrelay_enable="YES" sysrc dhcrelay_servers="10.0.1.5 10.0.1.6" sysrc dhcrelay_ifaces="em1 em2 em3" service dhcrelay start

This configures the relay to forward DHCP requests received on em1, em2, and em3 to the DHCP servers at 10.0.1.5 and 10.0.1.6.

Router-Based Relay

Most enterprise routers support DHCP relay (called ip helper-address on Cisco). If your routers handle relay, you do not need FreeBSD's dhcrelay. The DHCP server configuration remains the same either way -- it serves the correct subnet based on the giaddr (gateway IP address) in the relayed DHCP message.

Lease Management

Viewing Active Leases

sh
# View the lease file directly cat /var/db/dhcpd/dhcpd.leases # Search for a specific client grep -A 10 "00:1a:2b:3c:4d:5e" /var/db/dhcpd/dhcpd.leases

Lease File Cleanup

ISC DHCP appends to the lease file. Over time, it grows with expired entries. The daemon periodically rewrites the file, but you can force a cleanup:

sh
service isc-dhcpd stop # Backup cp /var/db/dhcpd/dhcpd.leases /var/db/dhcpd/dhcpd.leases.bak service isc-dhcpd start

When dhcpd starts, it reads the lease file and writes a clean version.

Migration Path to ISC Kea

ISC Kea is the successor to ISC DHCP. It uses a JSON-based configuration, supports database backends (MySQL, PostgreSQL, Cassandra) for lease storage, and provides a REST API for management. Migration is recommended but requires planning.

Installing Kea on FreeBSD

sh
pkg install kea sysrc kea_enable="YES" service kea start

Kea configuration is at /usr/local/etc/kea/kea-dhcp4.conf.

Key Differences

| Feature | ISC DHCP | ISC Kea |

|---|---|---|

| Config format | Custom syntax | JSON |

| Lease storage | Flat file | File, MySQL, PostgreSQL |

| API | OMAPI (limited) | REST API (full management) |

| Hooks/plugins | Limited | Extensible hook system |

| Failover | Built-in (mature) | Hot-standby, load-balancing (newer) |

| Performance | Good | Better (multi-threaded) |

| Status | End-of-life | Active development |

Migration Steps

  1. Audit current configuration: Document all subnets, pools, reservations, classes, and failover settings.
  2. Convert configuration: Translate dhcpd.conf to kea-dhcp4.conf. There is no automated converter; this is manual work.
  3. Migrate reservations: Convert static host entries to Kea's reservation format.
  4. Migrate leases: Kea can import ISC DHCP lease files, or you can let leases expire naturally during a transition.
  5. Test in parallel: Run Kea on a test subnet while ISC DHCP handles production.
  6. Cut over: Switch one subnet at a time to Kea.

Kea Configuration Example

The equivalent of the basic ISC DHCP configuration in Kea format:

sh
# /usr/local/etc/kea/kea-dhcp4.conf { "Dhcp4": { "interfaces-config": { "interfaces": ["em1"] }, "lease-database": { "type": "memfile", "persist": true, "name": "/var/db/kea/dhcp4.leases" }, "valid-lifetime": 3600, "max-valid-lifetime": 7200, "option-data": [ { "name": "domain-name", "data": "example.com" }, { "name": "domain-name-servers", "data": "10.0.1.1, 10.0.1.2" } ], "subnet4": [ { "subnet": "10.0.1.0/24", "pools": [ { "pool": "10.0.1.100 - 10.0.1.200" } ], "option-data": [ { "name": "routers", "data": "10.0.1.1" } ], "reservations": [ { "hw-address": "00:1a:2b:3c:4d:5e", "ip-address": "10.0.2.10", "hostname": "web-server" } ] } ] } }

ISC DHCP vs dnsmasq

dnsmasq is a lightweight DNS forwarder and DHCP server commonly used in small networks, home routers, and development environments.

Architecture

dnsmasq combines DNS forwarding, DHCP, TFTP, and PXE boot in a single, lightweight daemon. Its configuration is a single flat file with a simple key=value syntax. It is designed for simplicity and small-to-medium networks.

ISC DHCP is a dedicated DHCP server with a richer feature set. It handles complex network topologies, failover, and large-scale deployments that exceed dnsmasq's design envelope.

Feature Comparison

| Feature | ISC DHCP | dnsmasq |

|---|---|---|

| DHCP | Full implementation | Full implementation |

| DNS | No | Forwarding/caching |

| TFTP | No | Built-in |

| Failover | Yes (mature) | No |

| Lease storage | File | File |

| Class-based pools | Yes | Limited (tags) |

| Shared networks | Yes | Limited |

| Configuration complexity | Higher | Lower |

| Scalability | Enterprise | Small/medium |

| IPv6 (DHCPv6) | Full | Router Advertisement + stateless |

| Dynamic DNS updates | Yes | Yes |

When to Choose Each

ISC DHCP (or Kea): Enterprise networks with multiple subnets, DHCP relay, failover requirements, complex pool assignments, or detailed logging needs. Networks with more than a few hundred clients.

dnsmasq: Small office networks, home labs, development environments, PXE boot servers, or situations where combined DNS+DHCP in one service simplifies the setup. Networks with under 200 clients where failover is not critical.

dnsmasq on FreeBSD

sh
pkg install dnsmasq sysrc dnsmasq_enable="YES"

Configure /usr/local/etc/dnsmasq.conf:

sh
# DHCP range dhcp-range=10.0.1.100,10.0.1.200,255.255.255.0,1h # Gateway dhcp-option=option:router,10.0.1.1 # DNS servers dhcp-option=option:dns-server,10.0.1.1,10.0.1.2 # Static reservation dhcp-host=00:1a:2b:3c:4d:5e,10.0.2.10,web-server # Listen only on LAN interface interface=em1 bind-interfaces

The simplicity is apparent. What takes 20 lines in ISC DHCP takes 8 lines in dnsmasq.

FAQ

Is it safe to keep running ISC DHCP after end-of-life?

It continues to work reliably, but no security patches will be released. For internal networks behind a firewall, the risk is low. For networks exposed to untrusted clients, plan migration to Kea. The DHCP protocol itself has limited attack surface since it operates on the local network segment, but vulnerabilities in the parsing code could be exploited by malicious clients.

How do I monitor ISC DHCP on FreeBSD?

Monitor the lease file for pool utilization:

sh
# Count active leases grep -c "^lease" /var/db/dhcpd/dhcpd.leases

For detailed monitoring, use dhcpd-pools:

sh
pkg install dhcpd-pools dhcpd-pools -c /usr/local/etc/dhcpd.conf -l /var/db/dhcpd/dhcpd.leases

This shows pool utilization statistics. Integrate with Prometheus using a textfile collector for graphing and alerting.

Can I run ISC DHCP in a FreeBSD jail?

Yes, with VNET jails. The jail needs a dedicated network interface since DHCP operates at layer 2 (broadcast). A standard shared-IP jail cannot run DHCP because it does not have its own network stack. Create a VNET jail with a bridged interface for the LAN segment you want to serve.

How many clients can ISC DHCP handle?

ISC DHCP can handle thousands of clients on a single FreeBSD server. The practical limit depends on network topology, lease duration, and hardware. Networks with 10,000+ clients run ISC DHCP without issues. The main bottleneck at scale is lease file I/O -- for very large deployments, Kea's database backend is an advantage.

How do I convert ISC DHCP configuration to Kea?

There is no automated conversion tool. The process is manual: translate each dhcpd.conf directive to its Kea JSON equivalent. ISC provides a migration guide in the Kea documentation. Start with a simple subnet, verify it works in Kea, then convert the remaining configuration incrementally.

What happens during a failover split-brain scenario?

If both servers lose communication with each other, each server enters a "communications-interrupted" state. Both continue serving clients, but they only allocate from their portion of the address pool (determined by the split value). When communication is restored, they synchronize lease databases and return to normal operation. The MCLT parameter on the primary limits how far lease times can diverge during the split.

How do I debug DHCP issues on FreeBSD?

Run dhcpd in foreground debug mode:

sh
service isc-dhcpd stop dhcpd -d -f -cf /usr/local/etc/dhcpd.conf em1

This prints all DHCP transactions to the console. For client-side debugging:

sh
tcpdump -i em1 -n port 67 or port 68

This captures all DHCP traffic (DISCOVER, OFFER, REQUEST, ACK) on the network.

Get more FreeBSD guides

Weekly tutorials, security advisories, and package updates. No spam.