tailscale: Add an option to allow LAN access when using an exit node.

Describe the bug

When selecting an exit node, the new routing table (52 in my case) does not include any of the local subnets, making it impossible to reach them, and reflecting the traffic due to them back onto tailscale0.

This pretty much means a node that selected an exit node becomes invisible to all the local clients. This can be solved by adding the local subnets back to the newly created routing table.

Now, according to the ip rule output, it loosk like this is meant to be addressed by fwmark 0x80000:

rule
0:      from all lookup local
5210:   from all fwmark 0x80000 lookup main
5230:   from all fwmark 0x80000 lookup default
5250:   from all fwmark 0x80000 unreachable
5270:   from all lookup 52
32766:  from all lookup main
32767:  from all lookup default

That forces a lookup on otable main, that includes the local routes. But as far as I can tell nothing is setting that mark:

flameeyes@brentcube:~$ sudo iptables -L -v -n
Chain INPUT (policy ACCEPT 2330 packets, 241K bytes)
 pkts bytes target     prot opt in     out     source               destination
 2333  241K ts-input   all  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
 1939  131K ts-forward  all  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain OUTPUT (policy ACCEPT 3807 packets, 523K bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain ts-forward (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 MARK       all  --  tailscale0 *       0.0.0.0/0            0.0.0.0/0            MARK set 0x40000
    0     0 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            mark match 0x40000
    0     0 DROP       all  --  *      tailscale0  100.64.0.0/10        0.0.0.0/0
 1939  131K ACCEPT     all  --  *      tailscale0  0.0.0.0/0            0.0.0.0/0

Chain ts-input (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  lo     *       100.121.107.31       0.0.0.0/0
    0     0 RETURN     all  --  !tailscale0 *       100.115.92.0/23      0.0.0.0/0
    0     0 DROP       all  --  !tailscale0 *       100.64.0.0/10        0.0.0.0/0

This is with

1.6.0
  tailscale commit: ddc975fcb268a06dc39923ec5db93f1c95b8cfc4
  other commit: 995460c32665f1dab78c78512386235d275cf074
  go version: go1.16.2-ts3b83fb3

on Ubuntu 20.04.2.

Front logo Front conversations

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 2
  • Comments: 28 (12 by maintainers)

Commits related to this issue

Most upvoted comments

The problem here is that there is no one true answer to how this should work. For you, no LAN access is not what you want, but for other use cases, LAN access would be a data leak when trying to access the exit node. As a first pass, we implemented the option that defaults to being as safe as possible, which implies denying LAN access.

We definitely want to add an option on the client to permit LAN access when using an exit node, but it’ll take some effort to implement on every OS (support for this kind of configuration varies wildly, and requires different hacks). I’ll use this bug to track that.

As for “automatically turn things on and off depending on which network you’re in”, there is no way to make that safe from spoofing, unfortunately. There are a number of options that might be acceptable depending on your particular threat model, but fundamentally the local network cannot be trusted when it comes to making security decisions 😦. We’re still thinking about how to implement some kind of option like that for people who really need it, but there’s no timeline on that yet.

We’ve built the backend infrastructure for this feature, and are looking to expose it in and upcoming release. Here’s some sample designs for how we can achieve this on desktop. Mobile will take a little longer, since we’ll be building out a settings view to accommodate this feature, and others like it.

/cc @DentonGentry @maisem

allow-lan-access

And @maisem, since we were talking about decoupling exit node selection from enabling/disabling exit nodes, you might be surprised that the above designs follow our current pattern of picking “None” or “<exit node>”. I audited a bunch of menu bar apps and couldn’t find a good pattern for a nested enable/disable. Building a toggle like macOS’ Wi-Fi menu bar item could work, but it’d still leave us needing a solution on Windows. For now, I think it’s best to use the existing pattern of picking which exit node you want each time you activate it.

I think this behaviour seems especially counter-intuitive in a mobile use-case. I’d like to leave my phone with Tailscale enabled and running with a configured exit node, so that I can have zero interaction with Tailscale other than using services provided to me by my network. But when I leave it on with an exit node, I can’t use features like Chromecast to interact with the local network that I’m currently on.

In order to avoid having to turn Tailscale on and off at times, I think that good options would be either an option to leak the local subnet, or to preconfigure which networks you’d like to use the exit node capability on and which you would not.

On the other hand, the security provided by this default configuration is quite appealing if I imagine I’m on a public WiFi network… so… it does seem like a strong starting position. It just needs a wedge to open up a bit on a slightly more trusted network?

Hi @Omrigan

I would love to see an option like you suggested to add additional local routes.

For now I succesfully do it manually like this sudo ip route add throw 192.168.0.0/16 table 52.

Can someone explain me this issue like I’m 5?

The reason I’m trying to understand is that I feel like my scenario below shouldn’t be working but it is:

  • I have a Raspberry Pi with tailscale running with --advertise-routes=10.0.10.0/24, --advertise-exit-node and --accept-dns=false. This machine LAN IP address is 10.0.10.200;
  • On Tailscale admin I have “Subnets” and “Exit Node” enabled for the Raspberry Pi;
  • I have a DNS server running on the Raspberry Pi (10.0.10.200 / 100.x.x.x), and an additional DNS server running on a different LAN machine (10.0.10.205)
  • Also on Tailscale admin I have “Magic DNS” disabled, Nameservers set to the Raspberry Pi 100.x.x.x address (notice one extra zero compared to my LAN IP address), and I also have my own custom domain on “Search Domains”;
  • I have updated Tailscale to the latest 1.6.0 version on my Android phone and for testing purposes connected to the LTE network from my ISP, with the “exit node” option on the Android app enabled, and my Raspberry Pi as the exit node;
  • I can successfully use both DNS servers detailed above (10.0.10.200 and 10.0.10.205) with Ping Tools (this app allows you to pick the IP address for the DNS server to use when debugging DNS lookups).

Is this in any way related to the issue here being discussed or completely different?

You’re right, looks like that’s an issue in our docs. We’ll get that fixed. /cc @WalterHub

Any update on when the allow lan access feature will be coming to iOS and Android?

Windows support for allowing access to Local LAN while an exit node is in use added in 1.12. MacOS was added in 1.10. Linux --exit-node-allow-lan-access added in 1.10 (I think).

Going to close this as fixed.

@flexzuu by design, turning a machine into an exit node does not grant access to the LAN the exit node is attached to. Think of it as guest wifi at the remote location. You can --advertise-routes the LAN if you do want access to it.

@33b5e5 Probably not the same thing. On Windows we explicitly allow DNS traffic to continue using the LAN, to handle the case you describe. Can you file a separate bug with the info you reported in the forum, and the Tailscale IPs of the two nodes in question so I can debug more?

Thanks for following @MiraiSubject / @rosszurowski

As an aside for anyone reading this, I did discover an alternative that gave me the same thing I wanted.

tailscale up --advertise-exit-node --advertise-routes=192.168.0.0/16

Now I have that, I’m not even sure how a client-side setting would interact with this option.

The iOS UI needs a redesign to add a control for this in a reasonable way. That redesign has started, but not delivered in 1.22.

The mobile clients need a more extensive UI revamp to allow preferences. We have some ideas about what to do, but it is not being actively worked on at this time.

Windows, Linux, and macOS currently implement the allow-lan-access-with-exit-node feature.

@flexzuu It sounds like you’re trying to set up a LAN router that sends traffic over tailscale, which currently requires a bunch of manual configuration and network know-how, but is not what this bug is about. Let’s take this back to the forum, since it’s a different kind of setup.

Oh. I think this got me too. https://forum.tailscale.com/t/no-dns-when-using-exit-node/477

My DNS servers are on the LAN, so when I try to use an exit node, I lose DNS.

I’m not sure how to work around this, because setting external DNS on the admin panel doesn’t seem to change anything in this context. Is there a way to route DNS over Tailscale and out the exit node?