很久之前看過檸檬大佬的使用 N2N 進行異地組網的文章,大受震撼,但是 N2N 的部署體驗很難說得上令人愉悅。
然後就聽說了 wireguard 被加入 linux 內核,以下是 wireguard 的介紹:
WireGuard是由 Jason A. Donenfeld 開發的開放源代碼VPN程序及協議[1],基於Linux 內核實現,利用Curve25519進行密鑰交換,ChaCha20用於加密,Poly1305用於數據認證,BLAKE2用於散列函數運算[1],支持IPv4和IPv6的第 3 層。[2]WireGuard 旨在獲得比IPsec和OpenVPN更好的性能[3]。
確實,wireguard 性能十分不錯,但是配置實在是過於繁瑣了,如果要往 wireguard 網絡中加入一台設備,則需要修改幾乎所有連入網絡設備的配置文件,實在是太麻煩了,好在現在已經有了 tailscale 這個服務提供商提供了基於 wireguard 的 0 配置的 VPN 組網方案。
而 headscale 就是 tailscale 中控服務端的開源版本,開源版本支持自己部署,同時沒有連入設備的數量限制,於是我花了一點時間將 headscale 部署了一下。
使用到的項目#
Github/headscale
Github/headscale-ui
部署 headscale#
這裡我使用 docker-componse 進行部署
version: '3.5'
services:
headscale:
image: headscale/headscale:latest-alpine
container_name: headscale
volumes:
- ./container-config:/etc/headscale
- ./container-data/data:/var/lib/headscale
ports:
- 27896:8080
command: headscale serve
restart: unless-stopped
headscale-ui:
image: ghcr.io/gurucomputing/headscale-ui:latest
restart: unless-stopped
container_name: headscale-ui
ports:
- 9443:443
同時我還使用了 nginx 來進行反向代理,將 headscale-ui 和 headscale 分別部署在了不同的域名下面,因此要做一些 CORS 的處理,Nginx 配置文件參考如下
location / {
add_header 'Access-Control-Allow-Origin' '{{UI的域名}}' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS,DELETE ,PUT' always;
add_header 'Access-Control-Allow-Headers' 'authorization ,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '{{UI的域名}}' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS,DELETE ,PUT ' always;
add_header 'Access-Control-Allow-Headers' 'authorization ,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
proxy_pass {{headscale的地址}};
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_redirect default;
}
配置 headscale-ui#
headscale-ui 這個項目是一個純前端的項目,是通過用戶的瀏覽器直接調用 headscale 的 API 接口,所以需要自己去 headscale container 內部創建 apikey 來通過鑑權
docker exec -it headscale headscale apikey create
這個指令會創建一個 apikey,將他填入 headscale-ui 的配置裡面即可,這裡的配置僅保留在本地,不會上傳到任何地方,所以如果更換了設備或者瀏覽器想要進行 headscale 的配置的話,要將這一步重複一遍。
配置 ACL#
headscale 同時還支持 ACL 功能,從而控制在這個大內網之中設備能訪問的設備,這邊我寫了一個比較簡單的 ACL 配置文件
// ./container-config/acl.json
{
"groups": {
"group:admin": ["admin"], // 管理員用戶
"group:user": ["user"], // 普通用戶
},
"acls": [
// { "action": "accept", "src": ["*"], "dst": ["*:*"] },
{ "action": "accept", "src": ["group:admin"], "dst": ["*:*"] }, // 管理員用戶的設備能訪問所有設備
{ "action": "accept", "src": ["group:user"], "dst": ["tag:share:*","autogroup:self:*"] }, // 普通用戶僅能訪問帶 share 標籤以及自己的設備
],
"ssh": [
{
"action": "check",
"src": [
"autogroup:members"
],
"dst": [
"autogroup:self"
],
"users": [
"autogroup:nonroot",
"root"
]
},
],
"tagOwners": {
"tag:share": ["group:admin"],
},
}
同時,要修改配置文件裡面的 acl_policy_path
acl_policy_path: "/etc/headscale/acl.json"
這樣基本上就大功告成了,客戶端的配置網上基本上都有,就不多寫了。