Gluetun+Tailscaleで(強引に)VPNで保護されたExit Nodeを組む
きっかけ
普段はMullvad VPNを使っているのですが、普通にTailscaleを使うとMullvadと共存できない関係で自分のipを晒す事になってしまいます。
TailscaleはMullvadと提携しているので管理画面からMullvadを買って終わり!!でもいいですが、せっかくなら1~2台程度の最低限のマシンだけMullvadに接続して、他の家庭内・別拠点内にあるマシンはそれを経由するようにしたいです。そうすれば5台までしか使えないというMullvad VPNの制約を回避し、何十台の物理(または仮想)マシンがあってもVPNを介して通信できるようになります。
という事でそんな夢を叶えられる方法がないか調べたところ、GluetunというDocker Imageを見つけました。
Dockerコンテナ向けのvpnクライアントで、こいつを他のサービスとがっちゃんこしてやればVPN経由でなんでも通信できる!!!ってわけです。
実は結構前から試行錯誤しながら実験しまくっていて、とりあえずまともに動くレベルまで持っていけたので記事として残しておこうと思います。
試行錯誤している間に色んなフォーラムなりGithubのディスカッションなりを参考にしまくりました。感謝感謝。
材料
- Mullvadのアカウント(ここにあるプロバイダなら何でもok)
- Tailscaleのアカウント
- Dockerが動くマシン1台(Ubuntu向けDockerのインストール方法)
- Tailscaleにつなげるマシン何台か(てきとう)
- 気合
docker-compose.ymlを用意
services:
gluetun:
container_name: Gluetun
hostname: GluetunTS
image: qmcgaw/gluetun
cap_add:
- NET_ADMIN
ports:
- 1090:1090 #socks5
devices:
- /dev/net/tun:/dev/net/tun
environment:
- VPN_SERVICE_PROVIDER=custom
- VPN_TYPE=wireguard
- WIREGUARD_ENDPOINT_IP=123.456.7.89
- WIREGUARD_ENDPOINT_PORT=52001
- WIREGUARD_PUBLIC_KEY=eW91dHViZS5jb20vd2F0Y2g/dj1kUXc0dzlXZ1hjUQ=
- WIREGUARD_PRIVATE_KEY=eW91dHViZS5jb20vd2F0Y2g/dj1RRGlhM2UxMmN6Yw=
- WIREGUARD_ADDRESSES=10.20.300.400/32
- TZ=Asia/Tokyo
tailscale:
container_name: TailScale
image: tailscale/tailscale:latest
depends_on:
gluetun:
condition: service_healthy
environment:
- TS_HOSTNAME=tsvpn
- TS_OUTBOUND_HTTP_PROXY_LISTEN=:1090
- TS_ACCEPT_DNS=true
- TS_AUTHKEY=tskey-auth-xxxxxxxxxxxx
- TS_EXTRA_ARGS=--advertise-exit-node --accept-routes
- TS_STATE_DIR=/var/lib/tailscale
- TS_USERSPACE=true
- TS_ROUTES=192.168.1.0/24
volumes:
- ${PWD}/tailscale-nginx/state:/var/lib/tailscale
devices:
- /dev/net/tun:/dev/net/tun
cap_add:
- net_admin
restart: unless-stopped
network_mode: service:gluetun
まずGluetunが接続を試みて、接続完了でhealthyになったらTailscaleが立ち上がるようになっています。まあDockerゴリゴリに扱ってる人間からすれば当たり前の事なんでしょうけど、私はこの設定ファイルを書くために色々調べている間に初めて知りました。便利ですね〜
設定する環境変数
Gluetun
Mullvadの場合、VPN_SERVICE_PROVIDER=mullvad
を使うようにWiki上では指示されていますが、それだと動かなかったので、custom
にしてゴリ押してます。
https://mullvad.net/ja/account/wireguard-config から接続用の設定ファイルを生成して、ダウンロードしてください。ポートなりプロトコルなり、細かい設定はお任せします。
ダウンロードした設定ファイルを見ながら、以下の変数を設定してください。
-
WIREGUARD_ENDPOINT_IP
▶[Peer]
内のEndpointにあるip -
WIREGUARD_ENDPOINT_PORT
▶[Peer]
内のEndpointにあるport -
WIREGUARD_PUBLIC_KEY
▶[Peer]
内のPublicKey -
WIREGUARD_PRIVATE_KEY
▶[Interface]
内のPrivateKey -
WIREGUARD_ADDRESSES
▶[Interface]
内のAddress
その他の変数設定はお好みで。国外在住であればTZいじるなりなんなり。
Tailscale
以下のとおりに設定。
-
TS_AUTHKEY
▶ 管理画面で生成したキーをコピペ -
TS_ROUTES
▶ マシンが設置されているネットワークのCIDRを設定 -
TS_OUTBOUND_HTTP_PROXY_LISTEN
▶ httpプロキシのポートを指定(:
を忘れずに)
他はお好きに。HOSTNAMEいじるなりなんなり。
起動
そういえばdocker-compose.yml
ってファイル名の場合は-f
オプション付けなくても立ち上がるらしいです。(前書いた記事では付けてた)
なので
sudo docker compose up
これだけで動きます。うひょ〜
管理画面に表示されていればOK。
Subnet routesとExit nodeの設定
ボタンポチポチするだけです。
管理画面から先程のマシンを見つけ、...
をクリック
Edit route settings...
からSubnet routes
とExit node
にある項目にチェックを入れてSave
。
おわり!
接続テスト
お好きな端末でTailscaleにログインして、exit nodeを見つけて接続してみてください。pingなりページを開くなりして繋がれば成功です。
致命的な問題
確かにつながりはしたけど...
でも...
めっちゃ遅い!!!!(環境による差はあり)
私の場合は1.1.1.1
へのpingが100msを超え、下りは脅威の0.6mbpsを叩き出しました。もちろんvpnは国内にあるサーバーを選んでいます。
「リレーを経由しているのでは?」
いいえ。sudo docker exec -it TailScale tailscale ping {端末名}
を叩いてもリレーは一切経由せず直接接続されている事がわかります。(リレー経由の場合、via DERP(osk) in **ms
という表記になります。)
これに関してはいくつかの問題があります。
1. 無駄が多い
Gluetun+Tailscaleという構成なのもあり、表面上はVPNのIPしか見えていません。
つまり、こうなっているわけです。(Mermaidムズカチイ)
クライアントがexample.comへHTTPなり何かしらのリクエストを送りたい場合、
- Exit NodeへVPNのIPを経由して接続しリクエストを送信(Client ▶ VPN ▶ Node)
- Exit NodeはVPNを経由してリクエストを宛先へ送信(Node ▶ VPN ▶ Destination)
- レスポンスを受け取る(Destination ▶ VPN ▶ Node)
- 受け取ったレスポンスをクライアントへ送信(Node ▶ VPN ▶ Client)
という手順を辿ります。
家の中であればVPNを経由せずに Client ▶ Node とつながるようにしたいですね。
2. そもそもTailscaleのExit Nodeが遅い?(多分?)
試しにGluetunを抜いてみましょう。
services:
tailscale:
container_name: TailScale
image: tailscale/tailscale:latest
environment:
- TS_HOSTNAME=TSSingle
- TS_AUTHKEY=tskey-auth-xxxxxxxxxx
- TS_EXTRA_ARGS=--advertise-exit-node --accept-routes
- TS_STATE_DIR=/var/lib/tailscale
- TS_USERSPACE=false
- TS_ROUTES=192.168.1.0/24
volumes:
- ${PWD}/tailscale-nginx/state:/var/lib/tailscale
devices:
- /dev/net/tun:/dev/net/tun
cap_add:
- net_admin
この状態でsudo docker exec -it TailScale tailscale ping {lan内の端末名}
なりしてみると、lan内で直接つながりました。
じゃあスピードの方はというと、下り上り両方とも20mbpsほどです。普段は400mbps近く出るのですが、Exit Nodeを経由すると一気にスピードが落ちました。
フォーラムでも「同じ様な問題が発生する」だの「いいや、私の環境では正常だ」だのと言い争っているので、恐らく環境によってここは変わると思います。
(2025/07/04 追記) 東京リージョンのVPSを買ったのでTailscaleを入れてExit Node化してみました。なんと上り下り 400mbps という結果を叩き出しました。やはり環境によってここら辺の差は生じそうです。(特に東京都外に住んでいる場合は影響を受けそうです。)
HTTP Proxyで接続!
外出する予定がない人間であれば、家の中でhttp proxyを使って接続するのが手っ取り早いです。
先程TS_OUTBOUND_HTTP_PROXY_LISTEN
を設定しましたね!!もう準備は整っているので、あとはクライアント側で設定するだけです!!
(プロキシの設定は端末によって異なるので省略します)
スピードを測ってみると...
200~300mbpsほど出ました!!大成功です!!
もちろんTailscale内にある他のマシンへの接続も可能です!
外出先でも、一応Dockerを動かすことができれば同じ事ができます。
(ちょっぴり面倒ですが...)
おわりに
結構強引なところもありますが、やりたいことはできたので満足です。
他のイメージと組み合わせて認証付きプロキシ化したり、もう一個WireguardのVPNを生やすなり、色々やれることはあると思います。
ぜひお試しあれ。
Discussion