Write the Tailscale policy in grants, not acls (#46)
The console ships a grants-based default policy, so an acls example forces the operator to translate before they can use it - and the two differ in exactly the place that matters: grants carry ports in `ip` (`tcp:9222`) rather than suffixed onto `dst`. Adds the three things dropping the blanket grant silently takes away: an ssh block, since tagged devices leave `autogroup:self` and Tailscale SSH stops resolving them; a commented `autogroup:internet` grant for exit-node users; and `tcp:22` to the browser machine, without which tagging locks you out.
This commit is contained in:
@@ -314,12 +314,13 @@ tailnet's policy is allow-all, so this is the step that makes "Tailscale
|
||||
identity is the access control" true rather than aspirational.
|
||||
|
||||
Tailscale has no `deny`, so a restriction is expressed by removing the blanket
|
||||
`accept` and enumerating what is left. That only works if the browser machine
|
||||
can be *excluded* from a selector that still covers your own devices — which is
|
||||
grant and enumerating what is left. That only works if the browser machine can
|
||||
be *excluded* from a selector that still covers your own devices — which is
|
||||
what tagging buys: a tagged device has no user, so `autogroup:member` and
|
||||
`autogroup:self` stop matching it. Tagging is the mechanism, not decoration.
|
||||
|
||||
In the admin console, under **Access controls**, replace the default rule:
|
||||
In the admin console, under **Access controls**, the shipped policy grants
|
||||
`{"src": ["*"], "dst": ["*"], "ip": ["*"]}`. Replace it:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
@@ -329,24 +330,44 @@ In the admin console, under **Access controls**, replace the default rule:
|
||||
"tag:bookmark-browser": [],
|
||||
},
|
||||
|
||||
"acls": [
|
||||
"grants": [
|
||||
// The only thing on the tailnet that may drive the browser.
|
||||
{
|
||||
"action": "accept",
|
||||
"src": ["tag:bookmark-api"],
|
||||
"proto": "tcp",
|
||||
"dst": ["tag:bookmark-browser:9222"],
|
||||
"src": ["tag:bookmark-api"],
|
||||
"dst": ["tag:bookmark-browser"],
|
||||
"ip": ["tcp:9222"],
|
||||
},
|
||||
// Your own devices: everything of yours, both servers — but not CDP.
|
||||
// Drop the `:22` and you have locked yourself out of the browser machine.
|
||||
// Your own devices reach your own devices, and the VPS, in full.
|
||||
{
|
||||
"action": "accept",
|
||||
"src": ["autogroup:member"],
|
||||
"dst": ["autogroup:self", "tag:bookmark-api"],
|
||||
"ip": ["*"],
|
||||
},
|
||||
// On the browser machine you get SSH and nothing else. Widen this to `*`
|
||||
// and the restriction above is void; delete it and you are locked out.
|
||||
{
|
||||
"src": ["autogroup:member"],
|
||||
"dst": ["tag:bookmark-browser"],
|
||||
"ip": ["tcp:22"],
|
||||
},
|
||||
// Uncomment if you route traffic through an exit node — dropping the
|
||||
// blanket grant takes exit-node access with it.
|
||||
// {"src": ["autogroup:member"], "dst": ["autogroup:internet"], "ip": ["*"]},
|
||||
],
|
||||
|
||||
// Tagged devices left `autogroup:self`, so Tailscale SSH needs them named.
|
||||
// Irrelevant if you reach these boxes with ordinary sshd over the tailnet —
|
||||
// that is the `tcp:22` grant above.
|
||||
"ssh": [
|
||||
{
|
||||
"action": "check",
|
||||
"src": ["autogroup:member"],
|
||||
"dst": ["autogroup:self:*", "tag:bookmark-api:*", "tag:bookmark-browser:22"],
|
||||
"dst": ["autogroup:self", "tag:bookmark-api", "tag:bookmark-browser"],
|
||||
"users": ["autogroup:nonroot", "root"],
|
||||
},
|
||||
],
|
||||
|
||||
// Saved policies are rejected if these fail, so the rule cannot rot silently.
|
||||
// Run on every save, so a later edit that reopens 9222 is rejected outright.
|
||||
"tests": [
|
||||
{ "src": "tag:bookmark-api", "accept": ["tag:bookmark-browser:9222"] },
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user