tailscale / tailscale

The easiest, most secure way to use WireGuard and 2FA.
https://tailscale.com
BSD 3-Clause "New" or "Revised" License
17.67k stars 1.36k forks source link

wgengine/router: better handle when iptables works but ip6tables doesn't #3002

Open danderson opened 2 years ago

danderson commented 2 years ago

Found on github codespaces: the VM has IPv4 netfilter modules loaded (so iptables works), but not IPv6 modules (so ip6tables fails). Currently, this causes the linux router to fail basic netfilter setup, which in turn prevents tailscale from working at all unless you tailscale up --netfilter-mode=off.

Turning netfilter off is a viable workaround, but breaks subnet router SNAT and reverse path filtering protection. Both are kinda minor to lose in codespaces (we run inside a container inside a managed VM, so spoofing opportunities are minimal; and there's no particularly useful subnets to offer from that network location to other Tailscale nodes), but it'd be nice to degrade more gracefully.

The reason we don't degrade gracefully here is the reverse path filtering protection, which blocks packets from Tailscale-looking sources that arrive on interfaces other than tailscale0. It's not safe to sacrifice that protection without some kind of explicit user action (see https://seclists.org/oss-sec/2019/q4/122 for the consequences of ignoring this vector). What else can we do?

danderson commented 2 years ago

Further note: the linux router already detects whether IPv6 works at all, and skips ip6tables in that case. What we're discussing here is a machine where IPv6 connectivity exists and works, but ip6tables doesn't. IOW, the spoofed packet attack vector is definitely possible, and we can't use netfilter to defend against it.

For codespaces in particular, it's likely safe to drop that spoofing protection (though we need to verify that a stateful firewall exists between the codespace container and the outside world), but I'd rather not encode environment-specific hacks deep inside our network engine, if we can avoid it. It'd be nicer to either have a generic fix (e.g. using something other than netfilter and the useless rp_filter sysctl), or lock in that this configuration is unsupported and the workaround at user's discretion is the only solution.

DentonGentry commented 2 years ago

https://github.com/tailscale/dgentry-codespace/pull/1 to add --netfilter-mode=off

Also noting https://github.com/tailscale/tailscale/issues/2730 as a similar issue, a failing exec() results in not starting linkmonitor nor populating the DNS config.

DentonGentry commented 1 year ago

Work in progress possible fix: https://github.com/tailscale/tailscale/pull/5006

DentonGentry commented 1 year ago

We'll need to do something like https://github.com/tailscale/tailscale/pull/5006, in a less hacky way, to tolerate ip6tables failures without having the callers treat it as a fatal error.