TailscaleのACLを設定した

TailscaleのACLは簡単に設定できることは知ってたけど、自分のデバイス間は全許可というデフォルトのポリシーのまま使っていた。

{
  "acls": [
    // Allow all connections.
    // Comment this section out if you want to define specific restrictions.
    {"action": "accept", "src": ["*"], "dst": ["*:*"]},
  ],
}

一応手元のデバイスだけはtailscale up --shields-upでどこからもアクセスを受け付けないようにしてたし、仮にポートが空いていても認証が必須にはなっていた。ただ、人にTailscaleのデバイス共有機能と別途SSHの鍵認証でログインを許可することがあり、ログインするとそのデバイスが紐付いているTailscaleアカウント(私のアカウント)内の全デバイスに(ネットワーク的に)アクセスできてしまう。もちろん信頼できる人にしかログインさせていないけれども、これを機にACLを設定した。特筆することはなくドキュメント通り。

まずはデバイスを3つタグにグループ分け。

  • tag:client - 手元のノートPC
  • tag:server - 検証用マシンなど
  • tag:scraper - Prometheusを動かしているマシン
{
  // Define the tags which can be applied to devices and by which users.
  "tagOwners": {
    "tag:client":  ["autogroup:admin"],
    "tag:server":  ["autogroup:admin"],
    "tag:scraper": ["autogroup:admin"],
  },
}

ACLは初期ルールをコメントアウトするとデフォルトが全拒否になるので、必要なルールだけ追加。この場合は、手元のノートPCからは全マシンに全許可、Prometheusからはserverタグが付いたマシンのNode exporter用9100ポートのみ許可。serverタグ用のルールは存在しないのでこのタグのマシンはどこへもアクセスできない。

{
  // Define access control lists for users, groups, autogroups, tags,
  // Tailscale IP addresses, and subnet ranges.
  "acls": [
    // Allow all connections.
    // Comment this section out if you want to define specific restrictions.
    //{"action": "accept", "src": ["*"], "dst": ["*:*"]},
    {"action": "accept", "src": ["tag:client"], "dst": ["*:*"]},
    {"action": "accept", "src": ["tag:scraper"], "dst": ["tag:server:9100"]},
  ],
}
`tag:scraper`のプレビュー
tag:scraperのプレビュー

ルール数が最小なので、テストを書くのも簡単。

{
  // Test access rules every time they're saved.
  "tests": [
    {
      // clients can access anywhere
      "src":    "tag:client",
      "accept": ["tag:server:22", "tag:client:22", "tag:scraper:22"],
    },
    {
      // scraper can only access to servers with port 9100
      "src":    "tag:scraper",
      "accept": ["tag:server:9100"],
      "deny":   ["tag:client:22", "tag:scraper:22", "tag:server:22"],
    },
    {
      // servers cannot access anywhere
      "src":  "tag:server",
      "deny": ["tag:client:22", "tag:server:22", "tag:scraper:22"],
    },
  ],
}

これでデバイスを共有してログインしてもらったとしても、アカウント内の全デバイスへのネットワークアクセスまで許可することはなくなった。