Allowing friends to surf the web via my home network with Tailscale grants

I am a happy user of Tailscale. For the most part, it’s painless for my personal use of creating a VPN to connect all my personal and home devices. Moreover, it has this neat feature that turns a designated device into an exit node, which is like having your own home VPN gateway. Once I connect to Tailscale via my exit node, it’s as if I’m browsing the web from the comfort of my couch even if I’m on the move. I get to connect to all my home devices, including my NAS and media servers. I get ad-blocking and protection via my AdGuard Home DNS setup. The public IP that’s reflected will be the one assigned to my home by my ISP even if I’m not there.
A neat neat side effect of connecting to an exit node is being able to bypass annoying Geo-restrictions for content and subscriptions. Netflix, Spotify and their ilk have all started doing this anti-consumer crap. Thing is, even when I genuinely have family plans for these kinds of subscriptions, they lock us out when we go on extended periods inside or outside the country because of their brittle checks. How the heck are you supposed to connect to your home network to verify when you’re in a different corner of the world?! It’s quite the nightmare. Netflix truly takes the cake for the most absurd implementation of this. There are also plenty of content-restrictions such as not being able to stream Cricket or other local events when you’re in a different country even if you have a subscription. A generic VPN provider might work but it’s a cat-and-mouse game and not super reliable. Tailscale is a cure for all of these problems.
Some of my friends were intrigued by this when I told them about it and wanted to see if they could be added to my personal Tailscale org so that they can also bypass these annoying blockers when they’re on the move. I wanted to help but there was one major problem.
The starter configuration allows access to everything in the network to everyone in the org. While I’m happy to let my friends wants to connect to my home for general internet access, I don’t want them poking inside my local network and ping local devices. I wanted to see if there was a way to accomplish the following:
- Add my trusted friends into a
friends
group - Allow
friends
to connect to my Tailscale network and access the web via a designated exit node - Don’t allow
friends
to connect to my local network and local devices
While I commend Tailscale and award them best marks for the initial setup UX, I give them 1/10 for the permissions config. It’s hellish. Even the new Grants system isn’t making it any less horrendous to deal with. After failing to get Claude to generate a usable config, I wasted an hour or so into their documentation and managed to cook up the following config that seems to accomplish the desired setup:
{
"tagOwners": {
// Assign this to RPis that can serve as exit nodes. They should also
// advertise my home subnet so I can access my home servers and use
// my home DNS server.
"tag:pi-exit-node": ["runofthemillgeek@github"],
},
"groups": {
"group:home": ["jane@github", "runofthemillgeek@github"],
"group:superuser": ["runofthemillgeek@github"],
"group:friends": ["bob@github", "dave@github", "steve@github"],
},
"hosts": {
// Currently, my router is also my DNS server.
"home-router": "192.168.0.1",
},
"grants": [
// Grants are deny all by default. Need to punch holes
// to allow traffic.
//
// Allow home group access to everything.
{
"src": ["group:home"],
"dst": ["*"],
"ip": ["*"],
},
// Allow internet use but via tagged devices. Doesn't allow local
// network access.
{
"src": ["group:friends"],
"dst": ["autogroup:internet"],
"ip": ["*"],
"via": ["tag:pi-exit-node"],
},
// Allow only DNS access to my home router (which is the DNS
// server).
{
"src": ["group:friends"],
"dst": ["home-router"],
"ip": ["udp:53"],
},
],
}
Tailscale grants are “deny all by default”. If the grants
array was empty like so:
{
"grants": []
}
No one would be able to connect to anything. We need to add rules in the form of objects to punch holes and allow access. I’ve made it so that all members of group:home
gets access to everything, including my local devices. But the next two rules limit my friends’ access to just internet traffic via my exit node and also allows access to my local router only for the sole purpose of making DNS queries. They aren’t allowed to connect to the admin page of my router or use it for anything else. And they can’t access the rest of my local network either, since I never allowed for it in the first place. The last rule can be omitted if you aren’t overriding DNS nameservers in Tailscale settings but since I am doing it, this needs to be present.
Once the above config is applied, go to the list of machines and apply the tag pi-exit-node
to the designated exit node device. I can add the IDs of my friends who I’ve already invited into my Tailscale org into the group:friends
array field and they will be able to connect to my network and use it for the sole purpose of routing their internet traffic.
Frankly, this config system sucks big time. I’m confident even the most technical people deploying Tailscale at their orgs are struggling to make heads or tails about this and would rather prefer some good UX in the web dashboard to abstract it all away. Principle of least privilege sounds cool in theory but most of the time, I just want to explicitly express I want to block/deny and allow/accept so and so. If anyone from Tailscale is reading this, I hope you pass this feedback along.