Device: GL-BE9300 (Flint 3), firmware 4.10.1 (build 2026-09-18), OpenWrt 23.05 / QSDK, fw4.
Setup: IPv6 enabled on WAN (mode NAT6, wan6 = DHCPv6 on WAN) behind an ISP ONT that sends periodic Router Advertisements; VPN policy by domain enabled (route_policy.global.enabled=1, two OpenVPN clients). Nothing else unusual.
Summary
Every periodic RA from the upstream router (here every ~3.5–10 min, ~230 times a day) makes the router run /etc/init.d/firewall reload and /etc/init.d/network reload. Because the GL firewall init script ends every reload with echo f > /proc/net/nf_conntrack, all connections of the whole home lose their conntrack state every few minutes, and the network reload causes a ~1 s outage of the wired LAN (also LAN-to-LAN traffic). Nothing actually changes in the configuration at these moments.
Root cause (traced on the device, code quoted from /rom)
-
RA from the ONT → odhcp6c refreshes the delegated prefix → netifd emits a hotplug event
ACTION=ifupdate INTERFACE=wan6 IFUPDATE_PREFIXES=1(noIFUPDATE_ADDRESSES, noIFUPDATE_DATA). Captured from/proc/<pid>/environofhotplug-callon 11 of 11 RAs. -
/etc/hotplug.d/iface/20-firewall:4correctly ignores such an event:
[ "$ACTION" = ifupdate -a -z "$IFUPDATE_ADDRESSES" -a -z "$IFUPDATE_DATA" ] && exit 0 -
But
/etc/hotplug.d/iface/99-vpn-client:18-22maps every action other thanifupto "down":if [ "${action}" = "ifup" ] ;then
action_type='up'
else
action_type='down'
fiand line 35 calls
/usr/bin/rtp2.sh interface_status_change wan6 down if_type="wan". -
In
rtp2.sh, forif_type=wanthedownbranch is empty (:1418-1419), yet the function unconditionally queues and runs reloads (:1454-1457):create_reload_service /etc/init.d/firewallcreate_reload_service /etc/init.d/networkreload_modified_service -
/etc/init.d/firewall:32-37(GL addition, not in upstream firewall4):reload_service() {fw4 reload#flush conntrack tableecho f > /proc/net/nf_conntrack}
Process tree captured at the moment of a reload: netifd → hotplug-call iface → rtp2.sh interface_status_change wan6 down if_type="wan" → /etc/init.d/firewall reload → fw4 reload. Every RA was followed ~2–3 s later by nat6: Setting up masquerading nat6 for zone_name="wan" in logread (emitted on each fw4 reload); no reload happened without an RA.
Measured impact
-
nf_conntrack_count1000–1600 → ~10–50 within 2 s, on every RA. -
ECM/NSS accelerated connections 459 → 2; CPU ~80% for ~5 s while flows are re-learned.
-
After the flush, inbound packets of existing NATed flows are dropped (WAN zone input DROP) until the LAN side sends something. A TCP session where only the server sends data (client silent) died at the first flush and never recovered. Push channels (FCM on Android TV devices), cloud MQTT of IoT devices and similar long-lived connections stayed silent 40–150 s after each flush.
-
network reload→swconfig dev switch1 load network: ping every 0.2 s from a wired LAN host lost ~5 packets (~1 s) per event to the router, to the Internet and to another wired LAN host (pure LAN-to-LAN traffic through the switch), on every RA.
Expected behaviour
An ifupdate of a WAN interface that only refreshes prefix lifetimes should not reload the firewall or the network and must not flush conntrack — exactly what 20-firewall already does.
Suggested fixes
-
99-vpn-client: ignoreifupdatewithout address/data change (at least for WAN-type interfaces), i.e. the same filter as20-firewall:4. Local one-line workaround we use, inserted innotify_if_status_change()beforearg_cmd=…(line 33):[ "$action" = ifupdate ] && [ "$if_type" = wan ] && [ -z "$IFUPDATE_ADDRESSES$IFUPDATE_DATA" ] && return 0Result on the device: RAs keep coming, the handler is skipped, no firewall/network reloads, no flushes, zero LAN packet loss at RA time, the "silent server" TCP test stays alive.
-
rtp2.sh interface_status_change: do not reload firewall/network when nothing was changed (thewan/downbranch changes nothing). -
Consider a targeted conntrack cleanup (by mark / interface / old WAN address) instead of
echo f > /proc/net/nf_conntrackon every firewall reload.
Related observations (same code path)
-
rtp2.sh:1320adds the*_in_new_connmarknft rule without checking whether it exists; the delete at:1324buildsnft delete rule … handle $(… grep … | awk '{print $NF}'), which becomes invalid when there are several matches, so duplicates are never removed. We see 2–3 copies of the same rule invpn_in_new_mark/wan_in_new_mark. -
odhcp6c keeps a stale prefix (from a previous ISP prefix, lifetime 0) and re-announces it on every RA; netifd adds/removes its route each time, which alone is enough to set
IFUPDATE_PREFIXES.
Possibly related forum topics
-
#69244 GL-BE9000 frequent packet loss with VPN on 4.9.0 firmware
-
#71227 GL-BE10000 / 4.8.4: nightly VPN domain updater reloads network and restarts dnsmasq
-
#71368 Repeatedly being disconnected when network in failover changes
-
#65033 GL-XE3000 dropping connections constantly
How to reproduce
-
IPv6 enabled on WAN in NAT6 mode (DHCPv6 on
wan6), upstream router sending RAs. -
VPN → VPN policy by domain enabled (
route_policy.global.enabled=1). -
Watch
logread -f | grep -E "nat6: Setting up"andcat /proc/sys/net/netfilter/nf_conntrack_count: a reload and a near-zero conntrack count follow every RA (ip -6 monitor address dev eth0shows the RA-driven lifetime refresh 2–3 s earlier).