用基於tailscale開發套件,架設headscale在自己的主機管轄VPN吧

Tailscale 本身是個很好用的 VPN 工具,基於 WireGuard 協議,設定簡單、連線穩定,把我的不同實體地區的網路設備,可以集中一起跨網段使用彼此的功能和資源。
但官方的 Tailscale 有幾個問題:
設備資訊和連線狀態會經過 Tailscale 的server,免費版有設備數量限制(雖然一般使用者很難超過這個免費數量)。
無法完全掌控自己的網路,所以我曾經遇到幽靈客戶端裝置: WPAD.tailXXX.ts.net 產生大量查詢 內網DNS伺服器 的癱瘓行為(tailscale開發團隊說它後台看不出異常來源)。

因為有一些使用條件的便利性,還是會需要用這個VPN工具來跑內網和跨設備。
這幾天發現 Headscale 是基於 Tailscale 的開源自架替代品,可以用同樣的 Tailscale 客戶端軟體,在自己的伺服器達到一樣的功能。
缺點:
需要有自己的網域和持續對外的網頁主機,所以仍有一定的IP暴露風險給無聊人士找弱點。

下載位置:
https://github.com/juanfont/headscale
架設說明文件:
https://headscale.net/stable/

以我的網路環境,因為本來就有這個網誌的網頁主機,所以架設也比較單純:
利用 Apache reverse proxy 功能,透過現有 443 port 運作,不需要額外開 port
需要 Let’s Encrypt 憑證追加新的網域
ModSecurity 防護需要針對 headscale vhost 特別關閉,避免攔截 TS2021 協議
ProxyPass 需要改 upgrade=any 才能正確處理 tailscale 的連線協議
Fail2ban 監控 headscale 行為和封鎖

HEADSCALE SERVER主機端設定:
1).
我的網域目前是cloudflare服務。
所以要到那裏開一個專用子網域,例如 hs.jir.idv.tw,然後要把Proxy 設成 DNS only(灰色雲)狀態才能正常使用。
A和AAAA record的浮動IP的更新設定好,應該新增的網域就能PING到指定的主機使用。

2).
SSL申請憑證如果是 Certbot + Let’s Encrypt,只要多加一個 -d hs.jir.idv.tw 就能一起申請和持續維護更新。
#看目前的憑證狀況:
sudo certbot certificates
#把 hs.jir.idv.tw 加進現有憑證:
sudo certbot certonly --apache \
-d jir.idv.tw \
-d linux.jir.idv.tw \
-d hs.jir.idv.tw
#如無錯誤,確認新加入網域:
sudo certbot certificates

3).
我的是跑Apache,所以在 vhost 設定新增一個設定檔。
sudo nano /etc/apache2/sites-available/headscale.conf

# HTTP → 強制轉 HTTPS

ServerName hs.jir.idv.tw
RewriteEngine On
RewriteRule ^(.*)$ https://hs.jir.idv.tw$1 [R=301,L]

# HTTPS reverse proxy → headscale

ServerName hs.jir.idv.tw
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/jir.idv.tw/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/jir.idv.tw/privkey.pem
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8080/ upgrade=any
ProxyPassReverse / http://127.0.0.1:8080/
RequestHeader set X-Forwarded-Proto "https"

SecRuleEngine Off



#啟用新設定檔:
sudo a2enmod proxy proxy_http proxy_wstunnel rewrite headers
sudo a2ensite headscale.conf
sudo apache2ctl configtest
sudo systemctl reload apache2
sudo systemctl status apache2

4).
#下載和安裝套件:
wget https://github.com/juanfont/headscale/releases/download/v0.28.0/headscale_0.28.0_linux_amd64.deb
sudo apt install headscale_0.28.0_linux_amd64.deb

#編輯設定檔案:
sudo nano /etc/headscale/config.yaml

server_url: https://hs.jir.idv.tw

listen_addr: 127.0.0.1:8080
metrics_listen_addr: 127.0.0.1:9090
grpc_listen_addr: 127.0.0.1:50443
grpc_allow_insecure: false

noise:
private_key_path: /var/lib/headscale/noise_private.key

prefixes:
v4: 100.64.0.0/10
v6: fd7a:115c:a1e0::/48
allocation: sequential

derp:
server:
enabled: false
region_id: 999
region_code: "headscale"
region_name: "Headscale Embedded DERP"
verify_clients: true
stun_listen_addr: "0.0.0.0:3478"
private_key_path: /var/lib/headscale/derp_server_private.key
automatically_add_embedded_derp_region: true
ipv4: 198.51.100.1
ipv6: 2001:db8::1
urls:
- https://controlplane.tailscale.com/derpmap/default
paths: []
auto_update_enabled: true
update_frequency: 3h

disable_check_updates: false
ephemeral_node_inactivity_timeout: 30m

database:
type: sqlite
debug: false
gorm:
prepare_stmt: true
parameterized_queries: true
skip_err_record_not_found: true
slow_threshold: 1000
sqlite:
path: /var/lib/headscale/db.sqlite
write_ahead_log: true
wal_autocheckpoint: 1000

acme_url: https://acme-v02.api.letsencrypt.org/directory
acme_email: ""
tls_letsencrypt_hostname: ""
tls_letsencrypt_cache_dir: /var/lib/headscale/cache
tls_letsencrypt_challenge_type: HTTP-01
tls_letsencrypt_listen: ":http"
tls_cert_path: ""
tls_key_path: ""

log:
level: info
format: text

policy:
mode: file
path: ""

dns:
#magic_dns: true
magic_dns: false
#base_domain: example.com
base_domain: headscale.internal
#override_local_dns: true
override_local_dns: false
nameservers:
global:
- 1.1.1.1
- 1.0.0.1
- 2606:4700:4700::1111
- 2606:4700:4700::1001
split: {}
search_domains: []
extra_records: []

unix_socket: /var/run/headscale/headscale.sock
unix_socket_permission: "0770"

logtail:
enabled: false

randomize_client_port: false

taildrop:
enabled: true

#啟動 headscale
bashsudo systemctl enable headscale
sudo systemctl start headscale
sudo systemctl status headscale

#啟用後測試一下 headscale 有沒有正常回應,正常會有一個JSON格式的pass訊息:
curl -v https://hs.jir.idv.tw/health

5).
#建立一個 user帳號,因為我是自己要用,所以一個帳號就可以:
sudo headscale users create headscaleaccount
sudo headscale users list

#產生註冊用的 preauth key,USER 1產生的數值要記下來,等一下 24 小時內可以用這個 key 在多台設備註冊時用到。
sudo headscale preauthkeys create --user 1 --reusable --expiration 24h
sudo headscale preauthkeys list

#確認設備有註冊進來
sudo headscale nodes list

#查問題可以確認交握是卡在APACHE還是HEADSCALE
sudo tail -50 /var/log/apache2/error.log
sudo tail -50 /var/log/apache2/access.log
sudo journalctl -u headscale -n 50 --no-pager

TAILSCALE CLIENT客戶端設定:
剛剛產生的KEY值假設是XXXXXXXXXXXXXXXXXXXX,以下會用到。
如果原來就已經安裝tailscale客戶端程式,我是把舊的設定檔刪除掉,改成現在新的。
*** WIN10/11
打開POWER SHELL,要admin狀態:
PS C:\> tailscale logout
PS C:\> Stop-Service tailscale
PS C:\> Remove-Item -Recurse -Force "C:\ProgramData\Tailscale"
PS C:\> Start-Service tailscale
PS C:\> tailscale up --login-server=https://hs.jir.idv.tw --authkey=XXXXXXXXXXXXXXXXXXXX --accept-dns=false --hostname=win-pc1
PS C:\> tailscale status

*** LINUX
sudo tailscale logout
sudo systemctl stop tailscaled
sudo rm -rf /var/lib/tailscale/
sudo systemctl start tailscaled
sudo tailscale up \
--login-server=https://hs.jir.idv.tw \
--authkey=XXXXXXXXXXXXXXXXXXXX \
--accept-dns=false \
--hostname=linux-pc2
tailscale status

*** Synology NAS
因為套件管理是預設跑網頁到tailscale網址,需要手動開SSH,用PUTTY跑CMD指令來加入。

題外話,我的NAS太久遠以前的版本產品了,雖然已經是DSM7.0版本,它內部的tailscale維護套件太舊,會說不能用。
所以要手動更新新版本,遇到一點小困難,還好AI能給出適用的解答來解決…@@
uname -m
cat /proc/cpuinfo | grep -i "hardware\|model\|cpu" # 或 cat /etc/synoinfo.conf | grep "unique\|platform\|upnpmodel"

前往 https://pkgs.tailscale.com/stable/#spks 找對應 NAS 架構的 .spk檔案。
像我這台老機器是 STi SoC (Hardware: STi SoC),對應的是 Synology 的 monaco 架構:
cd /tmp
wget https://pkgs.tailscale.com/stable/tailscale-monaco-1.98.2-700098002-dsm7.spk
sudo synosystemctl stop pkgctl-Tailscale
sudo synopkg install /tmp/tailscale-monaco-1.98.2-700098002-dsm7.spk
sudo synosystemctl start pkgctl-Tailscale
sudo tailscale version
#確定版本已經更新到最新版後,就可以加入自己的
sudo tailscale logout
sudo synosystemctl stop pkgctl-Tailscale
sudo rm -rf /var/lib/tailscale/
sudo synosystemctl start pkgctl-Tailscale
sudo tailscale up --login-server=https://hs.jir.idv.tw --authkey=XXXXXXXXXXXXXXXXXXXX --accept-dns=false --hostname=nas-1
sudo tailscale status

*** ANDROID
應用程式資訊,先把tailscale app清除掉登入紀錄,如果是第一次安裝使用,可以跳下一步。
打開 tailscale app,右上角 設定 ,找ACCOUNT選「Add another account」輸入 https://hs.jir.idv.tw 。
然後用 authkey的數值 輸入後完成登入步驟。

然後,我的安卓手機不知道是不是特例還是哪設定有錯誤,總之輸入網址後,一直不出現輸入授權碼的訊息選項。
弄了一翻,才留意到後台看到他已經發出交握的訊息,在等核發的樣子。
總之我自己TRY的解法,在輸入網址後,假設跳回到LOGIN的畫面,這時候手機先都不要動也不要切換。
先到HEADSCALE主機後台查目前這台交握的訊息:
sudo tail -20 /var/log/apache2/access.log

#找到最後一筆交握需求的 KEY 值,例如:gFUcqABLOg1VB,直接由後台核發後。
headscale nodes register --key gFUcqABLOg1VB --user headscaleaccount

核發的當下,手機畫面應該會跳出一個連線成功的訊息,然後左上角的連線狀態就會多一組完成設定的IP值。
只是這個方法比較奇怪的部分是他不會抓到手機的hostname,會顯示成類似:invalid-xxxxxxx的名稱。
不過是個小問題,我們找出那台的ID值,然後給他定義我們想要顯示的名稱就可以了。
headscale nodes list
headscale nodes rename -i O android-1

6).
最後,自己旗下的設備都完成共用一個網域後,正常情況應該都能PING到和共用一個A CLASS網段來溝通。
tailscale ping 100.64.0.X
ping 100.64.0.X

沒問題就能用其他的軟體或APP來達到互聯功能瞜!!

其他參考文章:
https://kafeiou.pw/tailscaleheadscale-%E8%87%AA%E6%9E%B6vpn%E5%85%A8%E7%B4%80%E9%8C%84/

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

請輸入下列驗證碼計算後阿拉伯數字 (Translate it, if not Taiwanese to post reply) *