之前一直是透過端口映射訪問家裡的 NAS 的,但是會存在一些問題:
- 需要配置 DDNS,IP 切換時會存在延遲
- 訪問 Web 服務需要加端口
- 只能暴露出部分服務,比較核心的服務(例如路由器的配置)不能放開公網訪問
最近一段時間也調研和嘗試了各路組網方案(ZeroTier/WireGuard/Tailscale),最後選擇了自建 Headscale 全家桶方案。
準備#
- 一台 VPS,安裝 Docker 及 Docker Compose,需要開放下面端口
8080
Headscale HTTP9090
Headscale Metrics8443
DERP 伺服器 HTTPS3478/udp
DERP 伺服器 STUN8008
Headscale-Admin
- 客戶端(Linux/macOS/Windows/iOS/Android)
部署 DERP 伺服器#
創建一個目錄,存放 DERP 伺服器的配置文件
mkdir -p /app/derper/certs
cd /app/derper
創建自簽名證書
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout /app/derper/certs/<hostname>.key -out /app/derper/certs/<hostname>.crt -subj "/CN=<hostname>" -addext "subjectAltName=DNS:<hostname>"
hostname
可隨意,統一即可
創建 docker-compose.yaml
文件,內容如下:
services:
derper:
image: ghcr.nju.edu.cn/yangchuansheng/derper:latest
container_name: derper
restart: always
volumes:
- /app/derper/certs:/app/certs
environment:
- DERP_CERT_MODE=manual
- DERP_ADDR=:443
- DERP_DOMAIN=<hostname>
ports:
- 8443:443
- 3478:3478/udp
這裡使用了南京大學提供的 GHCR 鏡像,如不需要可替換
ghcr.nju.edu.cn
為ghcr.io
最後啟動 DERP 伺服器
docker compose pull
docker compose up -d
寫一份 derp.json
配置文件,傳到一個能直接訪問的地方備用:
{
"Regions": {
"901": {
"RegionID": 901,
"RegionCode": "cn-hangzhou",
"RegionName": "Hangzhou",
"Nodes": [
{
"Name": "901h",
"RegionID": 901,
"DERPPort": 8443,
"HostName": "<hostname>",
"IPv4": "<IP>",
"InsecureForTests": true
}
]
}
}
}
這裡假設我們已經上傳到了
https://example.com/derp.json
部署 Headscale#
創建 Headscale 配置文件目錄
mkdir -p /app/headscale
cd /app/headscale
mkdir config
touch config/db.sqlite
wget -O config/config.yaml https://raw.githubusercontent.com/juanfont/headscale/main/config-example.yaml
修改 config/config.yaml
文件中的配置:
server_url
修改為http://<IP>:8080
listen_addr
修改為0.0.0.0:8080
metrics_listen_addr
修改為0.0.0.0:9090
(可選)grpc_listen_addr
修改為0.0.0.0:50443
noise.private_key_path
修改為/etc/headscale/noise_private.key
prefixes.v4
和prefixes.v6
按需修改即可derp.urls[0]
修改為剛剛上傳的derp.json
文件 URL,這裡是https://example.com/derp.json
database.sqlite.path
修改為/etc/headscale/db.sqlite
dns_config.nameservers
修改為223.5.5.5
和223.6.6.6
(可以根據情況自行修改)dns_config.base_domain
修改為你自己的域名,會顯示在客戶端中
創建 docker-compose.yaml
文件:
services:
headscale:
image: headscale/headscale:0.23.0-alpha8
container_name: headscale
restart: always
command: serve
volumes:
- ./config:/etc/headscale
ports:
- 8080:8080
- 9090:9090
最後啟動 Headscale 即可
docker compose pull
docker compose up -d
部署 Headscale-Admin#
創建 Headscale-Admin 配置文件目錄
mkdir -p /app/headscale-admin
cd /app/headscale-admin
因瀏覽器的 HTTP 安全限制,直接通過域名訪問會跨域,這裡通過 Caddy 反向代理規避
nano Caddyfile
內容如下:
:{$PORT:80} {
reverse_proxy /api/* <IP>:8080
root * /app
encode gzip zstd
try_files {path}.html {path}
file_server
}
創建 docker-compose.yaml
文件:
services:
headscale-admin:
image: goodieshq/headscale-admin:latest
container_name: headscale-admin
restart: unless-stopped
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
environment:
- PORT=80
- ENDPOINT=/headscale
ports:
- 8008:80
最後啟動即可
docker compose pull
docker compose up -d
Headscale 的 API Key 可以通過如下命令創建:
docker exec -it headscale headscale apikey create
Web UI 可以通過 http://<IP>:8008/headscale
訪問,配置需要去掉 Legacy API
的勾選狀態。
創建用戶#
在服務端執行下面命令即可
docker exec -it headscale headscale users create <你的用戶名>
客戶端配置#
Linux#
首先安裝 Tailscale 客戶端
curl -fsSL https://tailscale.com/install.sh | sh
然後申請加入 Headscale 網絡
tailscale up --login-server=http://<IP>:8080 --accept-routes
如果需要通過這個節點訪問其他網段,增加 --advertise-routes
參數即可:
tailscale up --login-server=http://<IP>:8080 --advertise-routes=192.168.1.0/24 --accept-routes
打開返回結果中的鏈接,裡面有一段認證命令,回到服務端執行即可
docker exec headscale headscale nodes register --user <你的用戶名> --key nodekey:******
Apple 設備#
直接訪問 http://<IP>:8080/apple
,按步驟操作即可。
Android#
打開 F-Droid 這個頁面下載 APK 安裝包安裝:
f-droid.org/en/packages/com.tailscale.ipn
安裝後打開 App,右上角三個點,多點幾次,就會出現 Change Server
,填入 http://<IP>:8080
後按提示完成認證即可。
Windows#
家裡沒有 Windows 設備,無法實際測試驗證,各位看官請移步參考資料中的教程。