pxe-nic-check classifies each NIC from what it hears: LLDP/CDP/802.1X from managed switches, foreign DHCP offers and their domain (one DHCPDISCOVER on the imaging NIC; the GE NIC's networkd lease is read instead), STP and ARP hosts for information. A kernel BPF filter keeps bulk SMB traffic out of the capture loop; bridge ports are listened on too, since LLDP and EAPOL stop at the port. - dnsmasq drop-in runs --guard as ExecStartPre: exit 1 on a ge or foreign-dhcp imaging verdict, fail open (loudly) on bugs or no link - pxe-nic-check.timer runs --watch every 5 min: stops dnsmasq on a bad imaging verdict, never starts it - /run/pxe-nic-status.json (0644, atomic) for the webapp - playbook installs it all and writes /etc/pxe-server/nic.conf from pxe_imaging_mac, pxe_ge_mac, pxe_corp_domain_suffixes, pxe_nic_allowed_switches - unit tests plus a no-root network-namespace lab (veth pairs, a raw socket DHCP/LLDP peer and real dnsmasq); docs/pxe-nic-guard.md has the operator notes and the two floor tests
19 lines
926 B
Plaintext
19 lines
926 B
Plaintext
# dnsmasq drop-in: refuse to start DHCP/PXE unless the imaging NIC is on
|
|
# the isolated imaging network.
|
|
#
|
|
# Installed as /etc/systemd/system/dnsmasq.service.d/nic-guard.conf by
|
|
# pxe_server_setup.yml. pxe-nic-check --guard listens on the imaging NIC
|
|
# for 5 s and sends one DHCPDISCOVER (~6 s total), then exits:
|
|
# 0 safe to serve (isolated, no link, or the check itself broke - it
|
|
# fails open on bugs and says so loudly in the journal)
|
|
# 1 DO NOT serve: a foreign DHCP server or a managed/corporate switch
|
|
# (LLDP, CDP, 802.1X) is on the imaging NIC. dnsmasq does not start.
|
|
#
|
|
# Why did dnsmasq not start? journalctl -u dnsmasq -b | grep pxe-nic-check
|
|
# Full picture: pxe-nic-check (or the webapp status page)
|
|
# Guard does not run on "systemctl reload"; every start/restart runs it,
|
|
# including the @reboot cron restart.
|
|
|
|
[Service]
|
|
ExecStartPre=/usr/local/sbin/pxe-nic-check --guard
|