- Which never-used pool address a new client gets: sequential (the lowest, as before), reverse or random, in the settings, a subnet or a single pool (FIRST-LAST:ORDER). When no never-used address is left, the one free the longest, whatever the order; returning clients keep theirs. - A subnet's pools are used in the order listed, or one at random weighted by its never-used addresses. Pools now keep the order they are given in (no more sorting by address). - CLI --address-order and --pool-order; --add-pool of an existing range changes its order in place. Web UI: per-pool order and a move-up button, pool and address order on the subnet and settings pages. - Kea's allocator: random is imported. Schema migration 5. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
213 lines
9.6 KiB
Markdown
213 lines
9.6 KiB
Markdown
# Subnets, pools, reservations and leases
|
|
|
|
## Subnets and interfaces
|
|
|
|
A subnet is an IPv4 network Steward hands addresses out in, served on
|
|
one network interface:
|
|
|
|
```sh
|
|
steward subnet add 10.0.10.0/24 --interface eth0 --name office \
|
|
--pool 10.0.10.100-10.0.10.199 --option routers=10.0.10.1
|
|
```
|
|
|
|
**The interface decides.** stewardd opens one socket on port 67 per
|
|
interface that has a subnet, bound to that interface. A request is
|
|
answered only from the subnets of the interface it came in on. A client on
|
|
`eth0.20` never gets an `eth0` address, even if it asks for one. It gets a
|
|
NAK, then an address of its own VLAN.
|
|
|
|
For VLANs, give the server an interface on each, such as `eth0.20`, or a
|
|
bridge such as `br-iot`, each with an address in its subnet. That address
|
|
is the server identifier clients see, and the one they renew their lease
|
|
with. `steward interface list` shows the server's interfaces with their
|
|
addresses and subnets. To keep interfaces such as `lo`, `docker0` or
|
|
`veth*` out of that list and the web UI's picker, name them in
|
|
`interfaces.exclude` in steward.yaml ([configuration.md](configuration.md)).
|
|
|
|
An interface that doesn't exist yet is fine. The subnet gets a warning
|
|
(`interface_unknown`), and stewardd starts serving it within 30 seconds of
|
|
the interface appearing. `steward status` and the dashboard show each
|
|
interface's state; when one isn't served, they say why.
|
|
|
|
**Several subnets on one interface** form a shared network: two networks
|
|
on the same wire, the server with an address in each. Addresses come from
|
|
the first subnet's pools, then the next. Clients of every subnet are
|
|
answered from the interface's address in their own subnet, or its first
|
|
address.
|
|
|
|
A subnet can be **disabled**: its configuration and leases stay, but its
|
|
clients get no answers (`steward subnet disable NAME`, or Disable in the
|
|
web UI).
|
|
|
|
## Pools
|
|
|
|
Pools are the ranges handed out to any client: `FIRST-LAST`, or a prefix,
|
|
`10.0.10.128/25`. A subnet may have several pools, or none if only clients
|
|
with a reservation should get addresses. Pools must be inside the subnet,
|
|
must not overlap, and can't include the network or broadcast address.
|
|
|
|
Pool sizes are shown as the addresses that can really be handed out.
|
|
Reserved addresses inside a pool don't count, since nobody else gets them.
|
|
|
|
## Reservations
|
|
|
|
A reservation fixes a client's address:
|
|
|
|
```sh
|
|
steward reservation add 10.0.10.20 aa:bb:cc:dd:ee:01 --hostname nas
|
|
steward lease reserve 10.0.10.57 # the address a client has now
|
|
```
|
|
|
|
* **The client** is known by its MAC address, or by its client identifier
|
|
(option 61) when the reservation has one (`--client-id`; give `-` as the
|
|
MAC). Some devices change their identifier but not their MAC address,
|
|
and others the other way round. When unsure, use the MAC address.
|
|
* **The address picks the subnet**: the subnet whose network holds it. It
|
|
may be inside a pool or outside one; either way, nobody else gets it.
|
|
* **The host name** is sent to the client (option 12).
|
|
* **Options** set on the reservation are for that client only, and win
|
|
over the subnet's and the settings'.
|
|
* **A device on two VLANs** can have a reservation in each subnet. Within
|
|
one subnet, a client has at most one.
|
|
|
|
A reservation can be **disabled** (`steward reservation disable RES`, or
|
|
Disable in the web UI). It is kept but ignored: the client gets a pool
|
|
address like any other, and the reserved address, if it is inside a pool,
|
|
may go to someone else. The client keeps the address it has until its
|
|
lease runs out. While it is disabled, another reservation may use its
|
|
address or client; enabling it again is then refused until one of them
|
|
moves.
|
|
|
|
A client with a reservation always gets that address, not a pool address.
|
|
If it asks for another one, for example after the reservation was added,
|
|
it gets a NAK that names its reserved address, and then the reservation.
|
|
|
|
## Options
|
|
|
|
Options are set at three levels. A reservation's win over its subnet's,
|
|
and a subnet's over the settings' (the options every subnet gets):
|
|
|
|
```sh
|
|
steward settings set --option domain-name-servers=10.0.10.2 --option domain-name=lan
|
|
steward subnet update office --option routers=10.0.10.1 --option ntp-servers=10.0.10.2
|
|
steward reservation update nas --option domain-name-servers=1.1.1.1
|
|
```
|
|
|
|
`--option NAME=VALUE` sets one and keeps the others; `--unset-option NAME`
|
|
removes one. [options.md](options.md) lists the names, and how to write
|
|
each kind of value. Any other option can be set by number, with its type:
|
|
`--option 224:string=hello`.
|
|
|
|
Every reply carries the subnet mask, the server identifier and, for a
|
|
lease, the lease time and the times to renew (half of it) and rebind (7/8
|
|
of it). With a parameter request list (most clients send one), the client
|
|
gets the options it asked for, in its order. The subnet mask, routers, DNS
|
|
servers, domain name and host name are sent even if it didn't ask. Without
|
|
a list, it gets every option set for it.
|
|
|
|
## Lease times
|
|
|
|
The settings have the default (12 hours, `steward settings set
|
|
--lease-time 1d`); a subnet can have its own (`--lease-time 1h`). Clients
|
|
renew halfway through. Short times let changes reach clients sooner;
|
|
long ones keep clients working longer if Steward is down.
|
|
|
|
## How an address is chosen
|
|
|
|
For a DISCOVER, Steward offers, in this order:
|
|
|
|
1. the client's reservation in a subnet of the interface;
|
|
2. the address the client had before, from its last lease, even if that
|
|
ended, as long as it is still free and in a pool;
|
|
3. the address the client asks for (option 50), if it is free and in a
|
|
pool;
|
|
4. a free pool address: one never handed out before, in the subnet's
|
|
[address order](#address-order), else the one that has been free the
|
|
longest.
|
|
|
|
An address is free when no other client has an active lease on it, it
|
|
isn't held back, and it isn't offered to someone else in the last minute.
|
|
The server's own addresses are never offered. A fresh pool address is
|
|
pinged first: if something answers, it is held back and the next one is
|
|
tried.
|
|
|
|
When the client confirms with a REQUEST, the lease is saved, and only
|
|
then is the ACK sent.
|
|
|
|
## Address order
|
|
|
|
Which never-used address a new client gets is set at three levels, each
|
|
overriding the one above:
|
|
|
|
| Level | Setting | Values |
|
|
|---|---|---|
|
|
| settings | `steward settings set --address-order` | `sequential` (the lowest free address, the default), `reverse` (the highest), `random` |
|
|
| subnet | `--address-order` | the same, or `default` (the settings') |
|
|
| pool | `:ORDER` after the pool: `--pool 10.0.10.200-10.0.10.250:random` | the same, or `default` (the subnet's) |
|
|
|
|
A subnet with several pools also has a **pool order**, `--pool-order`:
|
|
|
|
* `listed` (the default): the pools are used in the order they are
|
|
listed; the next one only when the one before has no never-used address
|
|
left. `--pool` gives the order; in the web UI, ↑ moves a pool up.
|
|
* `random`: a pool at random, weighted by how many never-used addresses
|
|
each has, so addresses spread over all of them. With `random` addresses
|
|
too, every never-used address in the subnet is as likely as any other.
|
|
|
|
```
|
|
steward subnet update office --pool-order random --address-order reverse
|
|
steward subnet update office --add-pool 10.0.10.200-10.0.10.250:random # one pool's own order
|
|
steward subnet update office --add-pool 10.0.10.200-10.0.10.250:default # back to the subnet's
|
|
```
|
|
|
|
The order only picks among addresses **never handed out** (or whose lease
|
|
was deleted, or ended over 30 days ago). Once every free address has been
|
|
used before, the one free the longest is given, whatever the order: an
|
|
address that just came free isn't handed to the next device, so stale ARP
|
|
caches and DNS records don't point at the wrong one. Returning clients
|
|
keep their address (steps 2 and 3), so changing the order doesn't move
|
|
anyone.
|
|
|
|
## Leases
|
|
|
|
| State | Meaning |
|
|
|---|---|
|
|
| active | the client holds the address until the lease ends |
|
|
| expired | the lease ran out; the client gets the address back if it returns while it is free |
|
|
| released | the client gave the address back |
|
|
| held back | a client declined the address because another device answered for it, or it answered Steward's ping. It isn't handed out until the hold ends (a day; `--decline-hold`) |
|
|
|
|
`steward lease list` shows active and held-back leases; `--all` shows
|
|
the others too. Leases that ended more than 30 days ago are deleted.
|
|
|
|
### Online and last seen
|
|
|
|
A client is **online** while its lease is active. With the ping check on
|
|
(the default), Steward also pings every active lease's address once a
|
|
minute, and a client that answers gets a **last seen** time: on the
|
|
Leases page, next to a reservation's online badge, and in `steward lease
|
|
list`. Many devices block pings (Windows' firewall does by default), so a
|
|
client that doesn't answer stays online and simply has no last-seen time,
|
|
or keeps the one it had. The time stays with the lease when it is
|
|
renewed, and is kept across restarts.
|
|
|
|
`steward lease delete IP` frees an address at once. A client still using
|
|
it gets a NAK when it next renews, then asks for a new address.
|
|
|
|
## Authority
|
|
|
|
Steward is **authoritative** for its interfaces. A client that asks to
|
|
keep an address that doesn't belong on its interface, or that someone
|
|
else holds, gets a NAK and starts over at once, rather than keeping a
|
|
wrong address until its lease runs out. Turn this off (`steward settings
|
|
set --authoritative off`) only when another DHCP server serves the same
|
|
network. Requests for addresses Steward knows nothing about then get no
|
|
answer.
|
|
|
|
## Not in 0.1
|
|
|
|
Relayed requests (with `giaddr`) are ignored and logged once an hour: a
|
|
subnet must be on one of the server's own interfaces. DHCPv6, failover,
|
|
client classes and DNS names through Jarl are planned
|
|
([design.md](design.md)).
|