[Bug + Patch] tailscale0 loses "Tailscale" interface group after reboot / service restart
-
Summary
On pfSense Plus / CE with pfSense-pkg-Tailscale installed, tailscale0 sometimes
comes up after a reboot without the "Tailscale" interface group, leaving it
only in the "tun" group. Any firewall rules, NAT rules, aliases, or floating
rules that reference the Tailscale interface group silently stop matching
traffic.Running
ifconfig tailscale0 group Tailscaleby hand restores the group until
the next reboot.service tailscaled restart && service pfsense_tailscaled restartreproduces the same broken state.Tested on: pfSense Plus 26.03-RELEASE with pfSense-pkg-Tailscale.
Root cause
/usr/local/etc/rc.d/pfsense_tailscaledhas this poststart sequence:pfsense_tailscaled_poststart() { # wait for the tun device to come up wait_for_tun_dev ${tailscale_tun_dev_wait} || return 1 # add the tun device to the interface group tun_dev_add_group # <-- group added HERE # bring up Tailscale tailscale_up # <-- 'tailscale up' called AFTER # reload the packet filter pfsense_reload_filter }The order is wrong.
tun_dev_add_groupapplies the Tailscale group, then
tailscale_upis called. Whentailscale upreconnects to the control
plane, the daemon can reset the interface state as part of bringing the
tunnel up, wiping the group membership that was just set. On boxes where
thetailscale upreconnect is fast/uneventful, the group sticks; on
boxes where it actually re-configures the interface, the group is lost.Reproduction
Any of these will reproduce the broken state on an affected box:
reboot service tailscaled restart && service pfsense_tailscaled restart service pfsense_tailscaled restartAfter the command:
# ifconfig tailscale0 | grep groups groups: tun <-- missing "Tailscale"Proposed patch
Add a second tun_dev_add_group call AFTER tailscale_up so the group is
re-applied once tailscale_up has finished reconnecting.ifconfig ... group
is idempotent, so running it twice is harmless. The tun_dev_add_group
function is already defined earlier in the same file, no new code needed.--- /usr/local/etc/rc.d/pfsense_tailscaled.orig +++ /usr/local/etc/rc.d/pfsense_tailscaled @@ pfsense_tailscaled_poststart() { # wait for the tun device to come up wait_for_tun_dev ${tailscale_tun_dev_wait} || return 1 # add the tun device to the interface group tun_dev_add_group # bring up Tailscale tailscale_up + # re-apply the interface group after tailscale_up, which can reset + # interface state and drop group membership + tun_dev_add_group + # reload the packet filter pfsense_reload_filter }Verification
After applying the patch, a reboot should log:
Apr 20 10:34:28 pfSense tailscale[1923]: Added tailscale0 to interface group Tailscale Apr 20 10:34:28 pfSense tailscale[14426]: Added tailscale0 to interface group TailscaleThe two "Added tailscale0 to interface group" lines confirm both calls ran.
ifconfig tailscale0 | grep groupsshould reliably show:groups: tun TailscaleRelated note
In the same file on my pfSense, the --auth-key line is currently shipped commented out:
# handle the --auth-key parameter # pfsense_tailscaled_up_flags="--auth-key=${pfsense_tailscaled_authkey}"This is correct and should stay commented for installs that have already
enrolled the node (re-applying the auth-key on everytailscale upcauses
issues with non-expiring keys). Flagging this only because a conditional
form would be more robust:if [ -n "${pfsense_tailscaled_authkey}" ]; then pfsense_tailscaled_up_flags="--auth-key=${pfsense_tailscaled_authkey}" fiThat way the flag is applied only when an auth-key is actually configured,
and the line can be left uncommented in the shipped file.Happy to provide any additional logs / testing if helpful.
-
For now ive resorted to adding a file under: /usr/local/etc/rc.d/tailscale_fix_group
It is called tailscale_fix_group, it ensures tailscale0 is always a member of the 'Tailscale' interface group after pfsense_tailscaled starts.Code in tailscale_fix_group below, you can add it from GUI. Just open edit file and save path: /usr/local/etc/rc.d/tailscale_fix_group
Paste the code below and press save.
#!/bin/sh . /etc/rc.subr name="tailscale_fix_group" start_cmd="tailscale_fix_group_start" stop_cmd=":" tailscale_fix_group_start() { local _iface="tailscale0" local _group="Tailscale" local _waited=0 local _max=30 while [ $_waited -lt $_max ]; do if /sbin/ifconfig ${_iface} >/dev/null 2>&1; then if /sbin/ifconfig ${_iface} | grep -qw "${_group}"; then logger -s -t tailscale "tailscale_fix_group: ${_iface} already in group ${_group}" return 0 fi /sbin/ifconfig ${_iface} group ${_group} >/dev/null 2>&1 && { logger -s -t tailscale "tailscale_fix_group: added ${_iface} to group ${_group}" return 0 } fi sleep 1 _waited=$((_waited + 1)) done logger -s -t tailscale "tailscale_fix_group: ERROR could not add ${_iface} to group ${_group} after ${_max}s" return 1 } run_rc_command "$1"