Tailscaleでサービスをサブドメインでネットワーク内アクセスできるようにする

Tailscale Servicesで自宅サーバーを公開しようとしてハマった話

自宅LANで動かしている個人開発のAPIサーバー(FastAPI製、127.0.0.1固定バインド)を、Tailscale経由でiPhone/iPadからも見られるようにしたいと思い立った。単純に--host 0.0.0.0でLAN全体に公開するのは平文HTTPの盗聴リスクがあるといってCodexにもSonnetにも止められたので、代わりにTailscaleのtailscale serve機能を使って安全にTailscaleネットワーク内に公開する方法を調べた。

背景: なぜ0.0.0.0でHTTP公開しないのか

家庭内LANで、インターネットに公開しないなら別に良くない?と私は思ったのだけど、AI曰く「トークン認証を実装していても、平文HTTPだと同一LAN上でパケットを覗ける第三者にトークンごと盗聴されるリスクが残る」そう。思ったより、AIコーディングエージェントってセキュリティ意識高いんだよね。一昔前のバイブコーディングされたアプリで、脆弱性がたくさんあるっていう話は何なんだろうね。

まぁ確かにコマンド実行藻できるような仕組みなので、セキュリティはちゃんとしておいたほうがいいかなと思い、Tailscaleの暗号化トンネル内で公開する方法をこの際調査して、iPadやiPhoneから見れるようにした。

tailscale serveで公開

tailscale serveを使うと、Tailscale側がHTTPSリバースプロキシとして動作する。

1tailscale serve https / http://127.0.0.1:8765

これでTailscaleのMagicDNS名に対して自動発行されたHTTPS証明書でアクセスできるようになる。

複数サービスを同時公開したい → --serviceを使う

Macbookでは他にOpen WebUIなど別のWebサービスも動かしていて、これらを同時にTailscale経由で公開したい。単純なポート分けやパス分けでも実現できるが、サービスごとに独立したホスト名(サブドメイン風)を使いたかったので、そういうことができないか聞いてみると--serviceフラグというものがあるようだ。

1tailscale serve --service=svc:aihub --https=443 127.0.0.1:8765

こんな感じで、aihub.がサブドメイン風に機能して、aihub.(magicDNS)でアクセスできる。

タグの設定

1service hosts must be tagged nodes

Tailscale ServicesはTagged Node(用途ベースのアクセス制御に使うタグを持つノード)でないとホストできない仕様になっている。Admin ConsoleのACLポリシーで、タグの定義・自動承認・アクセス許可を追加する必要があった。

 1{
 2  "tagOwners": {
 3    "tag:aihub-host": ["autogroup:member"]
 4  },
 5  "autoApprovers": {
 6    "services": {
 7      "svc:aihub": ["tag:aihub-host"]
 8    }
 9  }
10}

tagOwnersで自分自身にタグ付与権限を与え、autoApproversでそのタグを持つノードがこのServiceをホストすることを自動承認する設定を追加。既存のgrantsにワイルドカード許可({"src": ["*"], "dst": ["*"], "ip": ["*"]})がすでにあったため、アクセス許可自体は追加不要だった。

タグの付与は下記コマンドでもできるようだけど、Tailscaleの管理パネルからも追加できた。

1sudo tailscale set --advertise-tags=tag:aihub-host

Admin approval待ち

タグ付けとACL設定を終えて再度コマンドを実行すると、今度は承認待ちの状態になった。

1This machine is configured as a service proxy for svc:aihub, but approval from an admin is required.

これはAdmin Console → Machinesの該当デバイスから手動承認するか、autoApproversの設定を先に反映させた上でコマンドを再実行すれば自動承認される。今回は設定の設定した直後でまだ反映されていなかっただけで、一度Serveを停止し、クリアしてから再実行したらできた。

iPhone/iPadから繋がらない

iPhone/iPadから繋がらないのでおかしいなと思って管理パネルを見ると、警告がでている。

1Services HOSTS: 1 needs configuration
2m1mbp: Advertising the service, but some required ports are missing

原因はAdmin Console側で設定する待ち受けポート設定をアプリの内部公開ポート(8765) を指定してしまっていた。正しくは、TailscaleがHTTPSとして外側に公開するポート、つまり443番を指定するべきだった。

Admin Console側のServices設定でPortsを443に修正したところ、設定エラーが消え、iPhone/iPadからも問題なく接続できるようになった。