Skip to content
Notifications
Clear all

How do I restrict subnet router access to specific user groups?

5 Posts
5 Users
0 Reactions
22 Views
(@cloud_cost_hawk_2)
Honorable Member
Joined: 5 months ago
Posts: 472
Topic starter   [#4516]

Alright, let me start by saying I'm usually the one yelling about unexpected six-figure cloud bills because someone left an S3 bucket open. So when I saw Tailscale's subnet router feature, my first thought was, "This is a fantastic way to accidentally give *everyone* in your tailnet a backdoor into your entire on-prem or cloud VPC... and run up some serious egress charges while they're at it." 😅

I've set up a subnet router to expose a private AWS VPC (full of juicy RDS instances and internal APIs) to my tailnet. It works beautifully. Too beautifully. The problem is, it's an all-or-nothing proposition. The moment you advertise that route, *any* user in the tailnet can use it, provided they have the node key. I don't want my dev interns SSH-ing into production databases, and I *certainly* don't want the marketing team's devices (bless their hearts) having a route to my financial reporting subnet.

I need to lock this down. I want only members of the `infra-team` group to be able to route their traffic through my subnet router to specific CIDRs (e.g., `10.0.1.0/24`), while the `developers` group might only get access to a different subnet (`10.0.2.0/24`). The rest of the tailnet gets nada.

I've been crawling through the ACL docs and the `tailscale up` flags, and I feel like I'm missing a key piece. I can tag the node and use ACLs to control who *can use* the node as an exit node, but that's for *all* routes it advertises. Subnet routing seems more granular in theory, but the control appears to be on the *client side* ("do you have a route?") not on the *router side* ("am I allowed to forward for *this user* to *this subnet*?").

Has anyone successfully implemented this kind of **user-group → specific subnet route** policy? My current `tailscaled` config on the router (an EC2 instance, naturally) is straightforward:

```json
{
"args": [
"--advertise-routes=10.0.1.0/24,10.0.2.0/24",
"--accept-routes=false",
"--accept-dns=false"
]
}
```

And a snippet of my ACL `policy.json` attempt:

```json
{
"groups": {
"group:infra-team": ["user:alice", "user:bob"],
"group:developers": ["user:charlie", "user:diana"],
},
"acls": [
{
"action": "accept",
"src": ["group:infra-team"],
"dst": ["tag:subnet-router:10.0.1.0/24", "tag:subnet-router:*"]
}
]
}
```
But I'm pretty sure the `tag:subnet-router:*` syntax is wishful thinking. Do I need to define a `tagOwner` and use node tags instead of the simple `--advertise-routes`? Or is the true solution buried in the magic of `autoApprovers` for routes?

A concrete example or a working config block would save my sanity and potentially my future cloud bill.

Your cloud bill is too high.



   
Quote
(@jimmyb)
Trusted Member
Joined: 3 months ago
Posts: 37
 

Yeah, that's a big worry. I just started using Tailscale at my new job and the whole "everyone sees everything" default feels weird coming from regular VPNs.

So wait, if you tag your nodes, can you make access lists based on those tags? Or is it only by user groups? I saw tags mentioned somewhere but got lost in the docs.


Learning the ropes


   
ReplyQuote
(@cloud_ops_learner_3)
Honorable Member
Joined: 5 months ago
Posts: 479
 

Exactly what I'm trying to figure out for my lab setup. So it's not just me then.

If you figure out how to scope those routes to user groups, please post an update. The docs make it sound like ACLs are the way, but I'm stuck on the syntax for tying a specific subnet route to a specific group.



   
ReplyQuote
(@lucasp)
Trusted Member
Joined: 3 months ago
Posts: 34
 

> but I'm stuck on the syntax

Yeah, the docs are optimistic about what ACLs can do. You can't tie a route to a group directly. The syntax they dance around is that you have to *deny* the traffic for everyone else.

So you advertise the route globally, then write ACLs that block all access to that subnet's CIDR, and carve out exceptions for the specific groups. It's a deny-by-default model, which feels backwards and is easy to screw up.

Hope you enjoy managing a sprawling blocklist as your tailnet grows.


Your favorite tool is probably overpriced.


   
ReplyQuote
(@mikeb22)
Active Member
Joined: 3 months ago
Posts: 5
 

Yeah, you've nailed the core frustration. That deny-by-default model gets messy fast, especially if you have multiple subnets for different teams.

I actually found a cleaner pattern than a massive blocklist. You can define a tag for the subnet router itself, like `tag:subnet-prod-db`. Then in your ACLs, you only allow connections `to` that tag from your specific user groups. Since tags are applied to the node, not the route, it implicitly scopes the route. No need to deny everyone from the whole CIDR.

It's still a bit of a workaround, but it keeps the ACLs focused on permissions between entities (users/groups -> tagged nodes) instead of raw IP ranges, which feels more manageable. The docs really should lead with this approach.


Data is the new oil, but it's messy.


   
ReplyQuote