Tailscale とは何か、何が安全なのか。VPS の SSH をインターネットから閉じるまで
Tailscale の仕組み・安全性・料金を整理したうえで、VPS と手元の Mac / スマホを同じプライベートネットワークに入れ、SSH の 22 番をインターネットから完全に閉じます。exit node と Serve / Funnel の使いどころも。
本記事にはプロモーション (アフィリエイト広告) が含まれます。
VPS を持つと、SSH の 22 番ポートをインターネットに向けて開けたままにすることになります。鍵認証にしていれば破られはしませんが、毎日数千件の試行ログを眺めるのは気分のいいものではありません。
Tailscale を使うと、VPS と手元の Mac やスマホを「自分専用のプライベートネットワーク」に入れられます。SSH はその中だけで通し、インターネット側の 22 番は閉じます。設定は 10 分、料金は個人利用なら無料です。
この記事は 2 部構成です。前半で Tailscale が何をしているのか、何を信頼していることになるのかを整理します。後半で VPS の SSH を実際に閉じます。仕組みはいいから手順が欲しい、という方は「VPS に入れる」から読んでください。
Tailscale とは
一言でいうと、WireGuard を使ったメッシュ型 VPN のサービス です。
従来の VPN は「VPN サーバー」という中継点があり、全端末がそこに繋ぎに行きます。Tailscale には中継点がありません。VPS、Mac、スマホ、自宅の NAS が、それぞれ直接 暗号化されたトンネルで繋がります。この「全員が全員と繋がる」形をメッシュと呼びます。
仕組み
Tailscale が提供しているのは、大きく 3 つです。
- 鍵の配布 (コーディネーションサーバー)。各端末は WireGuard の鍵ペアを自分で作り、公開鍵だけを Tailscale のサーバーに登録します。サーバーは「この tailnet にはこの端末たちがいて、公開鍵はこれ」という台帳を配ります
- NAT 越え。自宅の Wi-Fi やスマホ回線は NAT の内側にいて、外から直接届きません。Tailscale は STUN などの技術で両側から穴を開け、端末同士を直接繋ぎます。どうしても直接繋がらない場合だけ、DERP という中継サーバーを経由します
- 名前解決 (MagicDNS)。各端末に
100.x.y.zの固定 IP と、vpsnotes-001のようなホスト名が割り当てられます。IP を覚える必要がなくなります
通信そのものは WireGuard で端末間が直接暗号化しています。Tailscale のサーバーは「誰と誰を繋ぐか」を調整しているだけで、中身は通りません。
安全性: 何を信頼しているのか
「Tailscale のサーバーを経由するなら、Tailscale に見られるのでは」という疑問は自然です。整理するとこうなります。
- 通信の中身: WireGuard で端末間が暗号化しています。秘密鍵は端末から出ません。DERP で中継される場合も、中継サーバーが見るのは暗号化済みのパケットです
- Tailscale が持っている情報: 端末の公開鍵、IP アドレス、ホスト名、どのアカウントに属しているか。つまり「台帳」です
- 信頼していること: コーディネーションサーバーが正しい台帳を配ること。もし Tailscale 側が悪意ある端末を台帳に紛れ込ませたら、その端末は tailnet に入れてしまいます。これを防ぐ Tailnet Lock という仕組みがあり、新しい端末の追加を既存の端末が署名して承認する形にできます
- ログインの依存先: Tailscale 自体はアカウントを持たず、Google / GitHub / Microsoft / Apple などの ID プロバイダーでログインします。つまりそのアカウントの安全性 = tailnet の安全性です。2 段階認証は必ず有効にしてください
個人で VPS に使う範囲では、「WireGuard を自分で設定する手間を、台帳の管理を Tailscale に任せることで省いている」と理解しておけば十分です。台帳の管理まで自分でやりたい場合は Headscale というオープンソースのコーディネーションサーバーもありますが、この記事では扱いません。
料金
個人向けの Personal プランは無料です。2026 年 9 月時点で、ユーザー 6 人まで、端末数は無制限。MagicDNS、exit node、Funnel も含まれ、Tailscale SSH はホスト 5 台まで使えます。VPS + Mac + iPhone + 自宅の機器くらいなら、この記事で使う機能はすべて無料の範囲です。
この記事で使う環境
- VPS: XServer VPS クラウド 4GB、Ubuntu 24.04。初期設定 済みで、ufw は「SSH のみ許可」の状態
- 手元: Mac と Android (Pixel 7a)。iPhone でも同じ手順です
- Tailscale のアカウント: Google アカウントでログイン (2 段階認証あり)
VPS に入れる
公式のインストールスクリプトを使います。Ubuntu の apt リポジトリを追加して tailscale パッケージを入れてくれます。
curl -fsSL https://tailscale.com/install.sh | sh
Installing Tailscale for ubuntu noble, using method apt
...
取得:1 https://pkgs.tailscale.com/stable/ubuntu noble/main amd64 tailscale amd64 1.102.4 [38.7 MB]
...
Installation complete! Log in to start using Tailscale by running:
sudo tailscale up
この記事の時点で入ったのは 1.102.4 です。apt のリポジトリが追加されるので、以降は apt upgrade で一緒に更新されます。
tailnet に参加させます。--ssh をつけると Tailscale SSH が有効になります (後述)。
sudo tailscale up --ssh
認証用の URL が表示されるので、手元のブラウザで開いてログインします。
To authenticate, visit:
https://login.tailscale.com/a/xxxxxxxxxxxxxx
ログイン画面では、Google / Microsoft / GitHub / Apple / パスキーから選べます。ここで選んだ ID プロバイダーがこの tailnet の「持ち主」になり、スマホや Mac でも同じアカウントでログインすることになります。個人用途なら Google か Apple が素直です。2 段階認証を有効にしたアカウントを使ってください。

この URL は一度きりのログイン用リンクです。ログインが済むと、VPS 側のコマンドが Success. と表示して戻ります。
tailscale status
tailscale ip -4
100.96.34.27 vpsnotes-001 crz33@ linux -
100.96.34.27
VPS には 100.96.34.27 という Tailscale 内の IP が付きました。ホスト名は OS のホスト名 (XServer で付けたサーバー名) がそのまま使われます。100.x.y.z は tailnet の中だけで通じるアドレスなので、記事に載せても問題ありません。
サービスはインストール時に自動起動が有効になっています。念のため確認しておきます。
systemctl is-enabled tailscaled
enabled
Mac とスマホに入れる
Mac は App Store 版か公式サイトの版を入れて、同じアカウントでログインします。スマホは Google Play か App Store から Tailscale を入れ、ログインして接続を ON にします。Pixel 7a で試しましたが、iPhone でも同じです。
Mac のターミナルから、ホスト名で VPS に届くことを確認します。
ping -c 3 vpsnotes-001
PING vpsnotes-001.tailxxxxxx.ts.net (100.96.34.27): 56 data bytes
64 bytes from 100.96.34.27: icmp_seq=0 ttl=64 time=81.181 ms
64 bytes from 100.96.34.27: icmp_seq=1 ttl=64 time=69.847 ms
64 bytes from 100.96.34.27: icmp_seq=2 ttl=64 time=20.768 ms
MagicDNS が効いていて、vpsnotes-001 が 100.96.34.27 に解決されました。フルネームは vpsnotes-001.<tailnet 名>.ts.net で、tailxxxxxx の部分が自分の tailnet 名です。後で HTTPS の名前として使うので覚えておいてください。ここで名前が引けない場合は、Tailscale の管理画面 (DNS タブ) で MagicDNS が有効か確認します。
Tailscale SSH で入る
--ssh をつけて起動した VPS には、Tailscale の認証で SSH できます。公開鍵を配る必要がありません。
ssh deploy@vpsnotes-001
The authenticity of host 'vpsnotes-001 (100.96.34.27)' can't be established.
ED25519 key fingerprint is: SHA256:uy+zqroSnSTqXMicNMlda8XLYJvAqbvbtx0qr/oU3tI
This host key is known by the following other names/addresses:
~/.ssh/known_hosts:7: 203.0.113.10
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
指紋が、グローバル IP で繋いだときと 同じ です。Tailscale SSH はホストにある OpenSSH のホスト鍵 (/etc/ssh/ssh_host_*) をそのまま使うので、鍵を信用し直す必要がありません。「別の名前で知っている鍵」として yes で進めます。
本当に Tailscale SSH で繋がっているかは、サーバーのバナーで分かります。
ssh -v deploy@vpsnotes-001 exit 2>&1 | grep -i "remote software version"
debug1: Remote protocol version 2.0, remote software version Tailscale
Tailscale と出ていれば、tailscaled が 22 番を横取りして処理しています。OpenSSH なら OpenSSH_9.x と出ます。
私の環境では、初回のブラウザ承認 (check mode) は出ませんでした。個人用の tailnet の初期 ACL は、自分の端末同士の SSH を承認なしで通す設定になっています。
Tailscale SSH は tailscale0 インターフェースに来た 22 番の接続を tailscaled が横取りして処理します。OpenSSH は動いたままで、インターネット側からの 22 番は今まで通り OpenSSH が受けます。次の手順でそちらを閉じます。
SSH をインターネットから閉じる
ここからが本題です。必ず「Tailscale 経由で入れること」を確認してから 進めてください。
1. Tailscale 経由の通信を ufw で許可する
sudo ufw allow in on tailscale0
2. 別のターミナルで Tailscale 経由のセッションを開いたままにする
今開いているセッションがインターネット経由なら、もう 1 つ ssh deploy@vpsnotes-001 で入っておきます。この後の手順で締め出されても、こちらが残ります。
3. インターネット側の 22 番を閉じる
sudo ufw delete allow OpenSSH
sudo ufw status numbered
状態: アクティブ
To Action From
-- ------ ----
[ 1] Anywhere on tailscale0 ALLOW IN Anywhere
[ 2] Anywhere (v6) on tailscale0 ALLOW IN Anywhere (v6)
インターネット側からは何も届かない状態です。
4. 閉じたことを確認する
手元の Mac で Tailscale を一度 OFF にして、グローバル IP に SSH してみます。
ssh -o ConnectTimeout=5 deploy@203.0.113.10
ssh: connect to host 203.0.113.10 port 22: Operation timed out
タイムアウトすれば成功です。Tailscale を ON に戻して ssh deploy@vpsnotes-001 で入れることも確認します。
ssh deploy@vpsnotes-001 hostname
vpsnotes-001
締め出されたときの戻り方
Tailscale が何らかの理由で動かなくなると、SSH で入る手段がなくなります。XServer VPS クラウドにはブラウザから使える VNC コンソールがあるので、そこからログインして sudo ufw allow OpenSSH で一時的に開け直せます (XServer 側のパケットフィルターも外していれば、そちらも戻す必要があります)。
コンソールは、VPS の詳細画面の上部、「電源操作」の隣にあります。

作業前に、コンソールから root でログインできるパスワードを控えてあるか確認してください。初期設定 で root のパスワードログインは止めましたが、それは SSH の話で、コンソールからのログインには効きます。
XServer のパケットフィルターも閉じる
ufw で閉じたので OS 側はもう届きませんが、XServer のパケットフィルターでも SSH を外しておくと二重になります。申し込みの記事で作った ssh-only フィルターの適用を解除する (または削除する) と、XServer 側は「すべて拒否」に戻ります。
心配なのは「受信を全部閉じて Tailscale が動くのか」ですが、動きます。Tailscale は UDP 41641 を使って外向きに穴を開けるので、受信側のフィルターがあっても直接接続できます。実際に閉じた状態で Mac から確認しました。
/Applications/Tailscale.app/Contents/MacOS/Tailscale ping vpsnotes-001
pong from vpsnotes-001 (100.96.34.27) via DERP(tok) in 23ms
pong from vpsnotes-001 (100.96.34.27) via 203.0.113.10:41641 in 38ms
最初の 1 回だけ DERP (東京の中継サーバー) を経由し、2 回目からは VPS のグローバル IP の 41641 番に直接届いています。VPS 側の tailscale status でも、Mac が direct になっています。
100.71.78.38 mac crz33@ macOS active; direct 198.51.100.20:41641, tx 187316 rx 177276
もし via DERP が続くようなら中継経由で動いている状態です。繋がりはしますが速度が落ちるので、そのときはパケットフィルターに UDP 41641 の許可を足してみてください。
便利な使い方
SSH を閉じるだけでも十分ですが、Tailscale には他にも VPS と相性のいい機能があります。
exit node: VPS を出口にする
普段の Tailscale は「Mac と VPS の間」だけをトンネルで繋ぎます。exit node は、それに加えて Mac のインターネット通信を全部 VPS に送り、VPS から外に出す 設定です。Web サイトから見ると、VPS がアクセスしているように見えます。
使いどころは 2 つです。カフェや空港の Wi-Fi で、通信をその場のネットワークに覗かれたくないとき。もう 1 つは、海外にいて日本の IP から出たいときです。自宅で普通に使うぶんには意味がなく、VPS を経由する分だけ遅くなるので、普段は OFF にしておきます。
VPS 側で IP フォワーディングを有効にして、exit node として広告します。
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.conf
sudo tailscale up --ssh --advertise-exit-node
Warning: UDP GRO forwarding is suboptimally configured on enp3s0, UDP forwarding throughput capability will increase with a configuration change.
See https://tailscale.com/s/ethtool-config-udp-gro
この警告は「UDP 転送の性能を上げる設定が可能」という案内で、動作には影響しません。exit node として本格的に使うなら、リンク先の ethtool の設定を入れると速くなります。
管理画面 (https://login.tailscale.com/admin/machines) で VPS の行の「…」→「Edit route settings」→「Use as exit node」を有効にすると、スマホや Mac の Tailscale から出口として選べるようになります。承認前は Machines 一覧の「Exit Node」バッジに ⓘ が付いていて、選べません。
Mac のアプリでは「Exit Nodes」に vpsnotes-001 が現れるので、右上の ▶ を押すと有効になります。一覧をクリックしただけでは切り替わりません。

有効になると、左上に「Routing through this exit node」と出ます。戻すときは同じ場所の ⏸ を押します。

有効にした状態で、自分のグローバル IP を確認します。
curl -s ifconfig.me
203.0.113.10
自宅回線の IP ではなく VPS の IP が返っていれば、Mac の通信は VPS 経由で出ています。コマンドでも切り替えられます。
/Applications/Tailscale.app/Contents/MacOS/Tailscale set --exit-node=vpsnotes-001
/Applications/Tailscale.app/Contents/MacOS/Tailscale set --exit-node=
2 行目で解除です。常時 VPS を経由させる必要はないので、公衆 Wi-Fi のときだけ ON にする使い方が現実的です。
Serve: tailnet の中だけに HTTPS で公開する
VPS で n8n や Immich のような Web UI を動かすとき、インターネットに公開したくはありません。tailscale serve を使うと、tailnet の中だけに HTTPS 付きで 公開できます。証明書も Tailscale が用意します。
sudo tailscale serve --bg 5678
これで https://vpsnotes-001.<tailnet名>.ts.net が VPS の 5678 番 (n8n) に繋がります。スマホからもそのまま開けます。ufw で 5678 を開ける必要はありません。
Taildrop: 端末間でファイルを送る
tailnet の中の端末同士で、ファイルを直接送れます。スマホでスクショを撮って共有メニューから Tailscale を選び、送り先に Mac を選ぶと、Mac の ~/Downloads に届きます。Google フォトやケーブルを経由せず、圧縮もされません。このサイトのスマホのスクショは、すべてこの方法で Pixel から Mac に送っています。
Funnel: 一時的にインターネットへ公開する
tailscale funnel は Serve のインターネット版です。Webhook のテストで一時的に外から届かせたいときなどに使います。常用するものではないので、用が済んだら止めてください。
sudo tailscale funnel --bg 5678
sudo tailscale funnel off
つまずいた点
- Tailscale SSH で入れているのか分からなかった。指紋が OpenSSH と同じだったので、普通の SSH で入っているのだと思いました。Tailscale SSH がホストの鍵を使い回す仕様だと知らなかったためです。
ssh -vのバナーでTailscaleを確認して納得しました - exit node の「選ぶ」が分からなかった。管理画面で承認したあと、Mac のアプリの Exit Nodes に
vpsnotes-001は出るのに、クリックしても切り替わりません。右上の ▶ ボタンが「使う」でした。承認前は ⓘ バッジが付いていて一覧に出ないので、そこも一度引っかかっています curl ifconfig.meを VPS で打っていた。exit node の確認は Mac 側で打つものです。VPS で打てば VPS の IP が返るのは当たり前でした
SSH を閉じるところまでは 15 分ほど、exit node の確認を含めても 30 分かかっていません。締め出されることもありませんでした。順番さえ守れば、危ない作業ではないです。
次にやること
- 同じ VPS に n8n を立てて、
tailscale serveでスマホから使う (準備中) - Claude Code を VPS で常駐させる の SSH + tmux は、この構成の上でそのまま動きます
まとめ
- Tailscale は WireGuard のメッシュ VPN。通信は端末間で直接暗号化され、Tailscale は「誰と誰を繋ぐか」の台帳だけを持つ
- 信頼しているのは台帳の正しさと、ログインに使う ID プロバイダー。2 段階認証は必須
- 個人利用は無料。VPS + Mac + スマホなら 10 分で繋がる
- VPS の SSH は
ufw allow in on tailscale0→ufw delete allow OpenSSHの順で閉じる。先に Tailscale 経由のセッションを確保しておく - 締め出されても VPS のコンソールから戻れる。root のパスワードは控えておく
- Web UI は
tailscale serveで tailnet 内だけに公開する。ufw を開けなくて済む