summaryrefslogtreecommitdiffhomepage
path: root/wgengine/router/router_linux.go
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@tailscale.com>2022-08-28 14:31:34 -0700
committerBrad Fitzpatrick <bradfitz@tailscale.com>2022-08-28 16:52:57 -0700
commitad91d1aa2099d028a96a4e2ac216c30aefd22f2c (patch)
tree29e932d3fced7334fc9616167aa610c0c03a6369 /wgengine/router/router_linux.go
parent66d7d2549f3b1673f78f8e6eb2573b83bd5f5a4a (diff)
downloadtailscale-bradfitz/u32.tar.xz
tailscale-bradfitz/u32.zip
wgengine/router: allow disco packets through iptables on Linuxbradfitz/u32
Fixes #3824 Change-Id: I9d0a86bae7f6ca3b4588a0b621dc434b1611f414 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Diffstat (limited to 'wgengine/router/router_linux.go')
-rw-r--r--wgengine/router/router_linux.go33
1 files changed, 33 insertions, 0 deletions
diff --git a/wgengine/router/router_linux.go b/wgengine/router/router_linux.go
index 3a95c00ca..a4c9782c9 100644
--- a/wgengine/router/router_linux.go
+++ b/wgengine/router/router_linux.go
@@ -1112,6 +1112,30 @@ func (r *linuxRouter) addNetfilterBase() error {
return nil
}
+// allowDiscoRule is the iptables rule to allow all UDP discovery packets in.
+// See https://github.com/tailscale/tailscale/issues/3824.
+var allowDiscoRule = []string{
+ "-p", "udp", // UDP
+ "!", "-f", // not fragmented parts of UDP packets
+ "-m", "u32", "--u32",
+ "0>>22&0x3C@8=0x5453f09f && 0>>22&0x3C@10&0xffff=0x92ac", // check first 6 bytes of UDP payload is disco packet magic
+ "-m", "comment", "--comment", "Allow Tailscale NAT traversal",
+ "-j", "ACCEPT",
+}
+
+// allowDiscoRule6 is allowDiscoRule without the fragment check that doesn't
+// apply to IPv6, and with the right offsets for the IPv6 UDP payload.
+//
+// Note: this doesn't work if IPv6 extension headers are present. Oh well.
+// It'll help most users.
+var allowDiscoRule6 = []string{
+ "-p", "udp", // UDP
+ "-m", "u32", "--u32",
+ "0x30=0x5453f09f && 0x32&0xffff=0x92ac", // check first 6 bytes of UDP payload is disco packet magic
+ "-m", "comment", "--comment", "Allow Tailscale NAT traversal",
+ "-j", "ACCEPT",
+}
+
// addNetfilterBase4 adds some basic IPv4 processing rules to be
// supplemented by later calls to other helpers.
func (r *linuxRouter) addNetfilterBase4() error {
@@ -1129,6 +1153,10 @@ func (r *linuxRouter) addNetfilterBase4() error {
if err := r.ipt4.Append("filter", "ts-input", args...); err != nil {
return fmt.Errorf("adding %v in v4/filter/ts-input: %w", args, err)
}
+ if err := r.ipt4.Append("filter", "ts-input", allowDiscoRule...); err != nil {
+ // Not worth returning an error about. (Maybe they lack u32 kernel match support.)
+ r.logf("ignoring error adding allow-disco in v4/filter/ts-input: %v", err)
+ }
// Forward all traffic from the Tailscale interface, and drop
// traffic to the tailscale interface by default. We use packet
@@ -1167,6 +1195,11 @@ func (r *linuxRouter) addNetfilterBase6() error {
// TODO: only allow traffic from Tailscale's ULA range to come
// from tailscale0.
+ if err := r.ipt6.Append("filter", "ts-input", allowDiscoRule6...); err != nil {
+ // Not worth returning an error about. (Maybe they lack u32 kernel match support.)
+ r.logf("ignoring error adding allow-disco in v6/filter/ts-input: %v", err)
+ }
+
args := []string{"-i", r.tunname, "-j", "MARK", "--set-mark", tailscaleSubnetRouteMark}
if err := r.ipt6.Append("filter", "ts-forward", args...); err != nil {
return fmt.Errorf("adding %v in v6/filter/ts-forward: %w", args, err)