Skip to content

lease-sync: add DHCP lease sync daemon#29135

Open
pgaufillet wants to merge 1 commit intoopenwrt:masterfrom
pgaufillet:add-lease-sync
Open

lease-sync: add DHCP lease sync daemon#29135
pgaufillet wants to merge 1 commit intoopenwrt:masterfrom
pgaufillet:add-lease-sync

Conversation

@pgaufillet
Copy link
Copy Markdown

@pgaufillet pgaufillet commented Apr 12, 2026

📦 Package Details

Maintainer: @pgaufillet

Description:
Add lease-sync, an event-driven daemon that synchronizes DHCP leases between dnsmasq instances on clustered OpenWrt routers.

Features:

  • Real-time lease replication via dnsmasq ubus add_lease/delete_lease
  • AES-256-GCM encrypted UDP peer-to-peer protocol
  • Last-Writer-Wins conflict resolution with millisecond timestamps
  • Full sync on startup with peer reconciliation
  • Retry queue for transient ubus failures
  • IPv4 and IPv6 lease support

Requires the dnsmasq ubus lease methods patch: openwrt/openwrt#22904.
That PR must be merged first for lease-sync to function.

Part of the OpenWrt HA cluster proposal:

Source: https://github.com/pgaufillet/lease-sync (v1.1.0)


🧪 Run Testing Details

  • OpenWrt Version: 24.10 and 25.12
  • OpenWrt Target/Subtarget: x86/64, mediatek/filogic
  • OpenWrt Device: Generic x86_64 VM, ASUS TUF Gaming AX4200

✅ Formalities

  • I have reviewed the CONTRIBUTING.md file for detailed contributing guidelines.

@pgaufillet
Copy link
Copy Markdown
Author

While #22904 was waiting on review I ran a narrow-prompt diff-style review across the lease-sync daemon source (the same review style that caught the four bugs the /claude bot flagged on #22904). That sweep surfaced six issues in lease-sync — four real bugs and two configurable surfaces that had no implementation behind them — so I have released a v1.2.0 of the daemon and updated this PR to point at it.

Wire protocol unchanged (LEASE_SYNC_PROTOCOL_VERSION = 1 still). v1.0.0, v1.1.0, and v1.2.0 nodes interoperate. The fixes are isolated to the package source repository; the OpenWrt packaging only changes in three places (PKG_VERSION, PKG_SOURCE_VERSION, PKG_MIRROR_HASH, plus the UCI/init drop of one inert option).

Bug fixes in upstream lease-sync v1.2.0:

  • NUL-terminate the wire node_id field after recvfrom/decrypt. The protocol carries node_id as a fixed 64-byte field. Before v1.2.0 a single UDP frame with 64 non-zero bytes triggered out-of-bounds reads in the subsequent strcmp / %s log / strncpy into the dedup ring. Fix is a one-line termination immediately after both memcpy(&msg, …) sites.

  • format_mac and parse_mac are now size-aware. Previously both functions were hardcoded with limits (50 output bytes / 32 input bytes) that didn't reflect the size of the buffers their callers actually passed. The user-visible effect was that DHCPv6 DUIDs and RFC 4361 client-IDs longer than ~16 bytes were silently truncated — at parse time on the originating node (corrupting the local replica DB) and at format time on the peer node (injecting a different client-ID into dnsmasq, breaking client-ID matching across the HA pair). Both signatures grew an explicit size_t buffer-size parameter. All in-tree callers updated.

  • Zero-init the peer_addr stack buffer in config_add_peer. strncpy on an uninitialized buffer plus an over-long peer= line in the config could leak adjacent stack contents into peer->address and the "Invalid peer address" log line.

Removed surface (option 1: delete inert configuration):

  • The -f / --foreground CLI flag is gone. It never actually changed the daemonization path — only the syslog LOG_PERROR mode flag — so it was misleading. lease-sync always runs in the foreground of its supervising process; procd handles detachment. The init script never used -f, so this PR is unaffected at the packaging level.

  • The persist_file and persist_interval configuration options are gone. The on-disk lease database was wired into the config schema but never actually read or written, so the options were inert. This PR drops option persist_interval from /etc/config/lease-sync and the corresponding config_get + flat-config-file generation in the init script. Existing UCI files that retained the option remain compatible: it's parsed by the init script's config_get only if mentioned, and the daemon now silently ignores any persist_interval= / persist_file= lines that older configs (or older init scripts) might still emit. Replicated state is rebuilt from peers via SYNC_REQUEST after a restart (existing behavior); simultaneous cluster-wide restart loses replicated state until new DHCP events occur — this is now documented in the upstream lease-sync.conf.example.

Tests. The upstream repo's unit suite gained four targeted regression tests:

  • 20-byte client_id formatted in full through format_mac (catches the silent truncation).
  • 40-byte client_id parsed in full through parse_mac.
  • parse_mac honors caller-supplied max_len boundary.
  • 20-byte client_id round trip through parse_macformat_mac preserves all bytes.
  • config_load tolerates an over-long peer= line without crashing or leaking stack content.

All five existing unit suites (config / crypto / lease-db / peer-sync / util) pass on top of these additions.

Change to this PR:

  • PKG_VERSION: 1.1.01.2.0
  • PKG_SOURCE_VERSION: v1.1.0v1.2.0
  • PKG_MIRROR_HASH: recomputed against the v1.2.0 release tarball.
  • files/lease-sync.config: drop option persist_interval '60'.
  • files/lease-sync.init: drop persist_interval from config_get and from the generated flat-config block.

I have kept the PR as a single commit since v1.1.0 hasn't been merged yet.

@pgaufillet pgaufillet marked this pull request as ready for review May 2, 2026 11:00
Add lease-sync, an event-driven daemon that synchronizes DHCP
leases between dnsmasq instances on clustered OpenWrt routers.

Features:
- Real-time lease replication via dnsmasq ubus add_lease/delete_lease
- AES-256-GCM encrypted UDP peer-to-peer protocol
- Last-Writer-Wins conflict resolution with millisecond timestamps
- Full sync on startup with peer reconciliation
- Retry queue for transient ubus failures
- IPv4 and IPv6 lease support

Requires the dnsmasq ubus lease methods patch (openwrt/openwrt).

Source: https://github.com/pgaufillet/lease-sync (v1.2.0)
Tested on: OpenWrt 24.10 and 25.12 (x86_64 + filogic), production.

Signed-off-by: Pierre Gaufillet <pierre.gaufillet@bergamote.eu>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant