很久之前看过柠檬大佬的使用 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"
这样基本上就大功告成了,客户端的配置网上基本上都有,就不多写了。