618的时候把垂涎已久的 NAS 买了,到货后一直在幻想着各种使用场景。而当前面临的首要问题是,我现在需要进城务工,NAS 则放在乡下的家里,因此大部分时间都需要一个可靠的穿透方案。最初直接使用 FRP
进行穿透,虽然也支持点对点穿透,但是我的移动设备就没办法使用了。也考虑过直接用公网 IPv6,但是需要在路由器中关闭防火墙才能访问,考虑到安全问题这并不可取,并且出租屋的宽带也不支持 IPv6,长时间用流量也伤不起。工友给我推荐了蒲公英,但是需要购买一个硬件,并且免费服务的限制让我直接放弃了选择的想法。在最后我想尝试 ZeroTier
的时候,被一篇帖子的回复种草了 Tailscale
,看了下官网的说明和其它的一些文章的介绍后,认定就是它了。简单说一下我选择 Tailscale
的几个原因:
基于 WireGuard
实现,整体的组网逻辑比较合理,遵循就近原则,支持点对点传输和中继,即使点对点打洞失败,也可以保证基本的穿透可用性。并且支持 ACL
,在多用户使用的时候可以自定义用户的访问权限。
我能想到的平台都有客户端可用。
可自建服务,将来如果不自建服务也可以无痛切换到官方的服务,并且官方服务的免费套餐非常良心,对于个人用户来说完全够用。
由于现在手头还有几台云服务器,所以就先选择自建方案,可以有较高的自由度和可控性。而 Tailscale
是一套商业产品,因此需要使用第三方开发的 Headscale
项目搭建控制服务器,并辅以官方开源的 DERP
协议搭建中继服务器。
为了方便部署和维护,我选择用 Docker
来部署,并通过 Nginx Proxy Manager
反向代理。
先创建一个目录,存放 docker-compose.yml
和相关的配置文件,整体目录结构如下。
├── config
│ ├── acl.hujson
│ ├── config.yaml
│ └── derp.yaml
├── data
├── derp
├── docker-compose.yml
└── webui
docker-compose.yml
配置如下,部分配置可根据自己实际需求修改。
version: '3.9'
services:
headscale:
image: headscale/headscale:latest
container_name: headscale
volumes:
- ./config:/etc/headscale
- ./data:/var/lib/headscale
ports:
- 8080:8080
command: headscale serve
restart: unless-stopped
cap_add:
- NET_ADMIN
- SYS_MODULE
webui:
image: ifargle/headscale-webui:latest
container_name: headscale-webui
environment:
- TZ=Asia/Shanghai
- COLOR=blue-gray
- HS_SERVER=https://yourdomain.com # Headscale 的域名
- SCRIPT_NAME=/admin # 如果跟 Headscale 共用一个域名则需要随意指定一个路径,如果不是则填写 /
- DOMAIN_NAME=https://yourdomain.com # WebUI 的域名
- KEY=YourKeyBetweenQuotes # 使用“openssl rand -base64 32”生成 - 用于加密磁盘上的密钥。
- AUTH_TYPE=Basic
- LOG_LEVEL=info
- BASIC_AUTH_USER=username
- BASIC_AUTH_PASS=password
volumes:
- ./webui:/data
- ./config:/etc/headscale:ro
ports:
- 5000:5000
restart: unless-stopped
接下来简单配置一下 Headscale
,推荐直接使用官方提供的 example 进行修改。需要修改一下用于暴露 Headscale
服务的 URL
,没有域名则用 IP,有域名尽量用域名并使用443端口。
# The url clients will connect to.
# Typically this will be a domain like:
#
# https://myheadscale.example.com:443
#
server_url: http://yourdomain.com:443
保存后启动容器
docker compose up -d
最后在 Nginx Proxy Manager
中配置一下反向代理,并且配置下 SSL。需要注意的是,要把 Websockets Support
打开,否则客户端会无法登录。
如果 webui
跟 Headscale
使用了同一个域名,需要配置一下 Custom locations
。
最后访问下 Headscale
的域名,如果返回了 404,说明部署成功。
首次访问需要设置 Headscale
的 API Key,需要先创建一个。
docker exec -it headscale headscale apikey create
设置完成后,后续就可以方便的添加和管理设备了。
由于 Tailscale
官方的 DERP
服务在中国大陆地区并没有服务提供,并且使用的人也非常的多,以至于中继的体验并不好,因此可以自建一个中继服务来改善这个问题。
在 docker-compose.yml
中添加一个 service
。
derper:
container_name: derper
image: fredliang/derper
restart: unless-stopped
ports:
- 3478:3478/udp
- 12345:12345
environment:
- DERP_DOMAIN=derper.yourdomain.com
- DERP_ADDR=:12345
- DERP_VERIFY_CLIENTS=true
# 映射宿主机上的 tailscaled 进程用于避免服务被白嫖
volumes:
- /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock
在 Nginx Proxy Manager
中配置一下反向代理,这个也需要开启 Websockets Support
,否则客户端中会无法连接 DERP
服务。
为了防止被白嫖服务,在宿主机上安装一个 tailscaled
,具体安装方法根据不同的系统自行尝试。
如果自建了 DERP
服务,可以把 Tailscale
官方的公共服务禁用,只用自己的服务。修改 config.yaml
derp:
...
server:
# List of externally available DERP maps encoded in JSON
urls:
# 禁用 Tailscale 官方的 DERP 服务
# - https://controlplane.tailscale.com/derpmap/default
path:
- /etc/headscale/derp.yaml # 对应前面设置的映射
derp.yaml
regions:
901:
regionid: 901
regioncode: jp
regionname: Aliyun Japan
nodes:
- name: 901a
regionid: 901
hostname: 'derper.yourdomain1.com'
ipv4: ''
stunport: 3478
stunonly: false
derpport: 443
902:
regionid: 902
regioncode: cn
regionname: Aliyun Guangzhou
nodes:
- name: 902a
regionid: 902
hostname: 'derper.youdomain2.com'
ipv4: ''
stunport: 3478
stunonly: false
derpport: 443
重新创建容器
docker compose down
docker compose up -d
先在 webui
中创建一个用户,然后在需要使用的客户端中开始登录。
具体不同客户端的使用不做过多赘述,可以查看 Headscale 仓库中的文档说明。如果是 NAS 用户,可以参考官方文档中的安装说明。
由于我使用的是威联通,这里简单记录下如何设置自定义服务器。威联通可以直接在 App center
中进行安装,安装好后不要用 GUI 操作,进 SSH 中操作。
/share/CACHEDEV1_DATA/.qpkg/Tailscale/tailscale up --login-server <YOUR_HEADSCALE_URL>
把返回的 nodekey
复制到 webui
中,添加给某个用户即可。