tailscale serve shared-service (svc:) routing silently breaks when xt_MARK kernel module is unavailable
Environment
- Tailscale running as a Docker sidecar container (
tailscale/tailscaleimage) on a NAS (vendor Linux firmware, non-mainline kernel) - Host kernel does not have the
xt_MARKmodule available (modprobe xt_MARK→module 'xt_MARK' not found) - Container advertises ~18 services via
AdvertiseServices(Tailscale Services /svc:feature), each proxying to a different backend container on the same Docker network
What happens
On container start, the log shows:
wgengine: Reconfig: router config failed (adding [-i tailscale0 -j MARK --set-mark 0x40000/0xff0000] in v4/filter/ts-forward: running [/usr/sbin/iptables ...]: exit status 2: Warning: Extension MARK revision 0 not supported, missing kernel module?
...
); continuing to DNS config so name resolution still worksThis is the same underlying defect as #8569 (iptables MARK rule failing silently, node/service still reported as configured/healthy) — but here it manifests through the svc: services feature rather than exit-node routing.
tailscale serve status correctly lists every service, e.g.:
https://myservice.<tailnet>.ts.net (tailnet only) (svc:myservice)
|-- / proxy http://myservice:3000So the static configuration is correct. However, clients intermittently get connections refused, and the container log shows:
magicsock: disco: node [...] now using <ip>:<port>
The destination service doesn't have a TCP handler set.This error reliably appears immediately after a peer's connection endpoint changes (visible via the preceding magicsock: disco line) — i.e., whenever a client's NAT mapping/roaming causes Tailscale to renegotiate the connection (common on WiFi/mobile clients; rare on a stable wired client). Wired clients on the same tailnet essentially never hit this because their endpoint rarely changes; WiFi/mobile clients hit it often.
Workaround found
The equivalent non-svc: per-port URL on the same node (e.g. https://<node>.<tailnet>.ts.net:3000) for the identical backend does not exhibit this failure and works reliably across the same endpoint-change events. This suggests the svc: routing path specifically depends on the MARK-based rule that failed at startup, while the plain per-node/per-port serve path does not.
Expected behavior
Per #4329, ideally Tailscale would detect the missing kernel module/failed iptables rule and either (a) refuse to advertise the affected svc: services as configured, or (b) fall back to a routing path that doesn't require MARK, rather than silently accepting new connections and failing them individually after the fact.
Related issues
- #8569 (same MARK failure mode, exit-node context)
- #4329 (feature request: detect required kernel modules)
- #13863, #14018 (same
xt_MARK/kernel module error on other distros)
Source: tailscale/tailscale