Re-imaging the same PC: clear its stale SMB/conntrack state every time
A PC whose imaging failed and is re-imaged gets the same IP, and the
server still held state from the dead run, so net use failed (System
error 53). The April fix (18537ac) did not cover it:
- The dnsmasq hook only acted on 'add'/'del'. A re-image comes back to the
existing lease, which dnsmasq reports as 'old', and only when the
hostname/MAC changed. Now dnsmasq sets script-on-renewal, and the hook
clears state on 'old' when the request comes from PXE firmware or iPXE
(vendor class PXEClient), i.e. the machine just network-booted. A
Windows lease renewal (MSFT 5.0) is left alone.
- The 1 h conntrack timeout never applied after a reboot: systemd-sysctl
runs before ufw loads nf_conntrack, so the keys did not exist and the
5-day default stayed. /etc/modules-load.d/pxe-conntrack.conf loads it
first.
- smb-soft-reset.sh flushed neighbours on br-pxe, which no longer exists.
Live 2026-10-14. Hook tested on the server with an unused IP: network-boot
renewal clears, Windows renewal and no vendor class do not, add clears.
This commit is contained in:
@@ -14,6 +14,14 @@
|
||||
# $3 = client IP
|
||||
# $4 = hostname (may be empty)
|
||||
#
|
||||
# A re-image usually comes back to the SAME lease (same MAC, same IP), which
|
||||
# dnsmasq reports as "old", not "add" - and only at all because dnsmasq.conf
|
||||
# sets script-on-renewal. "old" also fires when a running Windows PC renews
|
||||
# its lease, so on "old" we only clear state when the request came from PXE
|
||||
# firmware or iPXE (vendor class PXEClient...): that machine has just
|
||||
# rebooted into a network boot, so any server-side session for its IP is
|
||||
# dead. A renewal from Windows (vendor class "MSFT 5.0") is left alone.
|
||||
#
|
||||
# Must exit quickly; dnsmasq waits for it. Logs to syslog via logger.
|
||||
|
||||
set +e
|
||||
@@ -25,13 +33,22 @@ host="${4:-}"
|
||||
|
||||
[ -z "$ip" ] && exit 0
|
||||
|
||||
clear_state() {
|
||||
/usr/sbin/conntrack -D -s "$ip" >/dev/null 2>&1
|
||||
/usr/sbin/conntrack -D -d "$ip" >/dev/null 2>&1
|
||||
/usr/bin/ss -K "dst = $ip" >/dev/null 2>&1
|
||||
/usr/bin/ss -K "src = $ip" >/dev/null 2>&1
|
||||
logger -t pxe-dhcp-hook "cleared stale state for $1 $ip ($mac${host:+ $host})"
|
||||
}
|
||||
|
||||
case "$action" in
|
||||
add|del)
|
||||
/usr/sbin/conntrack -D -s "$ip" >/dev/null 2>&1
|
||||
/usr/sbin/conntrack -D -d "$ip" >/dev/null 2>&1
|
||||
/usr/bin/ss -K "dst = $ip" >/dev/null 2>&1
|
||||
/usr/bin/ss -K "src = $ip" >/dev/null 2>&1
|
||||
logger -t pxe-dhcp-hook "cleared stale state for $action $ip ($mac${host:+ $host})"
|
||||
clear_state "$action"
|
||||
;;
|
||||
old)
|
||||
case "${DNSMASQ_VENDOR_CLASS:-}" in
|
||||
PXEClient*) clear_state "old (network boot, ${DNSMASQ_VENDOR_CLASS%%:UNDI*})" ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
# Step 3: restart smbd (full smbd restart, kills all child sessions)
|
||||
# Step 4: kill any leftover smbd child processes that survived restart
|
||||
# Step 5: flush conntrack for 172.16.9.0/24 (kernel connection tracking)
|
||||
# Step 6: flush ARP / neighbour cache on br-pxe
|
||||
# Step 6: flush ARP / neighbour cache
|
||||
# Step 7: drop TCP sockets on port 445 via ss -K
|
||||
# Step 8: restart dnsmasq (DHCP/TFTP state as a last resort before reboot)
|
||||
|
||||
@@ -65,8 +65,8 @@ else
|
||||
fi
|
||||
pause "Step 5 done"
|
||||
|
||||
echo "=== Step 6/8: flush ARP / neighbour cache on br-pxe ==="
|
||||
ip neigh flush dev br-pxe 2>&1 || ip neigh flush all 2>&1 || true
|
||||
echo "=== Step 6/8: flush ARP / neighbour cache ==="
|
||||
ip neigh flush all 2>&1 || true
|
||||
pause "Step 6 done"
|
||||
|
||||
echo "=== Step 7/8: drop tcp sockets on port 445 ==="
|
||||
|
||||
@@ -205,6 +205,11 @@
|
||||
# client re-images the same machine and hits a stale SMB session.
|
||||
# Script runs as root by default (dnsmasq --dhcp-scriptuser default).
|
||||
dhcp-script=/usr/local/sbin/pxe-dhcp-hook.sh
|
||||
# Also call it when a client comes back to its existing lease (a
|
||||
# re-image of the same PC), which dnsmasq otherwise reports only if
|
||||
# the hostname or MAC changed. The hook acts on those only for PXE
|
||||
# firmware / iPXE requests.
|
||||
script-on-renewal
|
||||
|
||||
- name: "Create TFTP directory"
|
||||
file:
|
||||
@@ -628,6 +633,15 @@
|
||||
mode: '0644'
|
||||
notify: reload sysctl
|
||||
|
||||
- name: "Load nf_conntrack at boot so the conntrack sysctl applies"
|
||||
# systemd-sysctl runs before ufw loads nf_conntrack, so without this the
|
||||
# net.netfilter.* keys do not exist yet at boot and the 1 h timeout is
|
||||
# silently skipped (the kernel default of 5 days stays in force).
|
||||
copy:
|
||||
dest: /etc/modules-load.d/pxe-conntrack.conf
|
||||
content: "nf_conntrack\n"
|
||||
mode: '0644'
|
||||
|
||||
- name: "Deploy SMB diagnostic + soft-reset helper scripts"
|
||||
copy:
|
||||
src: "{{ usb_mount }}/pxe-server-helpers/{{ item }}"
|
||||
|
||||
Reference in New Issue
Block a user