0x00 前言
为什么选用tailscale?
1. 笔者有异地组网需求,目前尝试过frp stcp做穿透、wireguard组网,经过一段时间的使用,稍微总结一下:使用frp用stcp发布服务,客户端连接,确实是个很好的办法,但是配置终究太麻烦,需要安装客户端、在添加了穿透之后每个客户端需要独立配置等等;wireguard可能是当下最好的组网技术,低占用、linux内核级支持、配置简单(wireguard-ui),这些都是它的优点,可是有一个十分致命的点,它是中心化的,流量都需要过一遍server进行转发,这无异于极大的增加了服务器的带宽压力且增加了流量的延迟。经过这一段时间的查阅资料,发现了tailscale这个基于wireguard的项目,他的工作原理可以通过官网进行查看,与此同时又发现了headscale这个对tailscale server的开源实现,这不得折腾一下。
2. 这里可能有人就要问了,为什么在tailscale官方免费提供了3用户100台设备连接、提供acl、p2p、sso的情况下,要选择自建headscale呢,当然是为了固定IP,毕竟随机分配的地址可太难受了。本文将使用docker compose的方式安装headscale、derp、headscale-ui。
3. 如果您觉得tailscale官方提供的设备数量足够你使用,那么你仍然可以使用官方提供的服务,但仍建议您自建一个derp,因为官方未在大陆地区提供derp服务,存在人数较多及访问延迟较高的情况。
所使用端口列表
- tcp 58080(headscale server)
- tcp 57070(headscale web ui)
- tcp 56060 (headscale derp)
- udp 3478 (headscale derp stun)
如您使用反代请在防火墙放通反代后的端口(本文教程为tcp 80、443)及udp 3478
0x01 前提条件
1. 你需要一台具备公网IP的服务器和该服务器防火墙修改权限
2. 一个域名且带有SSL证书(可以使用acme.sh申请免费证书),需要占用两个子域名
3. 一些基础的计算机网络知识
注意:请将本文全文所涉及到的域名:hs.example.com(headscale-server及ui)、hsderp.example.com(中继)修改为自己的域名,后续将不再另行说明。
0x02 安装docker
注意:该项内容来源于清华大学开源软件镜像站
Docker 提供了一个自动配置与安装的脚本,支持 Debian、RHEL、SUSE 系列及衍生系统的安装。
以下内容假定
- 您为 root 用户,或有 sudo 权限,或知道 root 密码;
- 您系统上有 curl 或 wget
export DOWNLOAD_URL="https://mirrors.tuna.tsinghua.edu.cn/docker-ce" # 如您使用 curl curl -fsSL https://get.docker.com/ | sh # 如您使用 wget wget -O- https://get.docker.com/ | sh
0x03 docker compose文件
本文中compose文件仅部署headscale、headscale-ui、derp、client,请按需进行修改。
注意,要提前配置好config.yaml和derp.yaml,并放入headscale/config文件夹内,同时因derp更新不及时,这里采取了手动构建方式,需将derp.Dockerfile放入dockerfiles文件夹内。可以去GitHUB的代码仓下载config-example.yaml和derp-example.yaml,内容见0x04配置文件部分。
# docker-compose.yaml version: '3.9' networks: private: driver: bridge ipam: config: - subnet: 172.20.200.0/24 services: server: image: headscale/headscale:v0.23.0-alpha12 container_name: headscale-server networks: - private volumes: - ./headscale/config:/etc/headscale - ./headscale/data:/var/lib/headscale - ./headscale/run:/var/run/headscale - /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime:ro ports: - "58080:8080" command: serve restart: unless-stopped depends_on: - derp webui: image: ghcr.io/gurucomputing/headscale-ui container_name: headscale-ui networks: - private environment: HTTP_PORT: 7070 ports: - "57070:7070" volumes: - /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime:ro restart: unless-stopped derp: build: context: ./dockerfiles dockerfile: derp.Dockerfile container_name: headscale-derp networks: - private environment: DERP_DOMAIN: hs.bokro.cn DERP_ADDR: :6060 DERP_CERT_MODE: letsencrypt DERP_VERIFY_CLIENTS: true ports: - "56060:6060" # derp port, TCP - "3478:3478/udp" # STUN port, UDP volumes: - ./tailscale:/var/run/tailscale - /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime:ro restart: unless-stopped client: image: tailscale/tailscale:stable container_name: tailscale-client network_mode: "host" privileged: true environment: TS_EXTRA_ARGS: --netfilter-mode = off volumes: - ./tailscale:/var/run/tailscale - /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime:ro - /var/lib:/var/lib - /dev/net/tun:/dev/net/tun cap_add: - net_admin - sys_module command: tailscaled restart: unless-stopped
# derp.Dockerfile 放入dockerfiles文件夹内 FROM golang:latest AS builder WORKDIR /app # https://tailscale.com/kb/1118/custom-derp-servers/ RUN go env -w GOPROXY=https://goproxy.io,direct RUN go install tailscale.com/cmd/derper@latest FROM ubuntu WORKDIR /app ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ apt-get install -y --no-install-recommends apt-utils && \ apt-get install -y ca-certificates && \ mkdir /app/certs ENV DERP_DOMAIN=your-hostname.com ENV DERP_CERT_MODE=letsencrypt ENV DERP_CERT_DIR=/app/certs ENV DERP_ADDR=:443 ENV DERP_STUN=true ENV DERP_STUN_PORT=3478 ENV DERP_HTTP_PORT=80 ENV DERP_VERIFY_CLIENTS=false ENV DERP_VERIFY_CLIENT_URL="" COPY --from=builder /go/bin/derper . CMD /app/derper --hostname=$DERP_DOMAIN \ --certmode=$DERP_CERT_MODE \ --certdir=$DERP_CERT_DIR \ --a=$DERP_ADDR \ --stun=$DERP_STUN \ --stun-port=$DERP_STUN_PORT \ --http-port=$DERP_HTTP_PORT \ --verify-clients=$DERP_VERIFY_CLIENTS \ --verify-client-url=$DERP_VERIFY_CLIENT_URL
0x04 服务器配置
config.yaml
server_url: https://hs.example.cn 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: ./noise_private.key prefixes: v6: fd7a:115c:a1e0::/48 v4: 100.100.0.0/16 allocation: sequential derp: paths: - /etc/headscale/derp.yaml database: type: sqlite sqlite: path: /var/lib/headscale/db.sqlite write_ahead_log: true
derp.yaml
regions: 999: regionid: 999 regioncode: cnsz regionname: China Tencent Cloud nodes: - name: my-derp regionid: 999 hostname: hsderp.example.cn stunport: 3478 stunonly: false derpport: 443
0x05 nginx反向代理配置
注意,为了便于笔者管理,以下给出的nginx配置文件仅为proxy相关conf,请自行在域名配置文件里incloud,相关语法:include /www/hsderp.example.cn/proxy/*.conf 。您也可以根自己喜好直接写入网站配置内。
headscale-server和derp正常进行反代就行了,ui端因为跨域的原因,需要在同一个域里。如您按照本文提供的内容进行创建的话,那么你可以直接使用此nginx配置,否则请自行修改相应端口。
hsderp.example.com反代设置
# hsderp.conf location ^~ / { proxy_pass http://127.0.0.1:56060; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; add_header X-Cache $upstream_cache_status; add_header Strict-Transport-Security "max-age=31536000"; }
* hs.example.com反代设置
# hs.conf location ^~ / { proxy_pass http://127.0.0.1:58080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; add_header X-Cache $upstream_cache_status; add_header Strict-Transport-Security "max-age=31536000"; add_header Cache-Control no-cache; } #web.conf location ^~ /web { proxy_pass http://127.0.0.1:57070; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; add_header X-Cache $upstream_cache_status; add_header Strict-Transport-Security "max-age=31536000"; add_header Cache-Control no-cache; }
至此,您在浏览器中打开https://hs.example.com/web及https://haderp.example.com均可看到相关页面
0x06 headscale-ui配置
1. 为了便捷控制,首先生成api key供headscale-ui进行控制
docker exec headscale-server headscale apikeys create -e 720d
其中-e参数后面指定的是该apikey的过期时间,这里设置为720天
2. ui端配置
2.1 打开ui端页面:https://hs.example.com/web
2.2 点击”Settings”
2.3 添加”Headscale URL”,本例为https://hs.example.com
2.4 将刚才生成的api key粘贴进“Headscale API Key”中
2.5 点击“Test Server Settings”,出现绿色对号后UI端就可以通过ui控制服务端了
2.6 进入“User View”,点击“+New User”,添加一个用户
2.7 为该用户生成一个Preauth Key,供客户端连接使用。为了便捷性,最好设置为“Reusable”,并“Active”
0x07 客户端连接
客户端可以在tailscale官网进行下载及查看使用文档。
如您docker-compose文件中将derp部分的DERP_VERIFY_CLIENTS设置为了true,这代表您开启了客户端验证,如关闭则您的derp可被所有人使用。开启后需要对docker的client进行配置,参考linux客户端,如下为使用docker exec配置示例
docker exec -it tailscale-client tailscale up --netfilter-mode=off --login-server=https://hs.example.com --auth-key=YOUR AUTH KEY
linux客户端
1. 使用官方脚本安装tailscale客户端
curl -fsSL https://tailscale.com/install.sh | sh
2. 连接服务器
注意:以下命令二选一即可,有关路由转发描述见0x08 路由转发
# 需路由转发 tailscale up --netfilter-mode=off \ --accept-routes \ --advertise-routes=192.168.0.0/24 \ --login-server=https://hs.example.com \ --auth-key=YOUR AUTH KEY # 不需路由转发 tailscale up --netfilter-mode=off \ --login-server=https://hs.example.com \ --auth-key=YOUR AUTH KEY
windows客户端
1. 在官网下载并安装客户端后,首次需打开cmd或powershell,输入以下命令进行连接
tailscale up -netfilter-mode=off -login-server=https://hs.example.com -auth-key=YOUR AUTH KEY
IOS客户端
1. 您需要使用非中国大陆地区APP Store账号进行下载并安装tailscale。本文不提供相关教程,请自行搜索美区、港区APPLE ID注册教程。
2. 安装后点击右上角头像,在弹出“Accounts”窗口,点击右上角三个点,并选择“Use a custom coordination server”
3. 输入您的域名https://hs.example.com点击“Login in”
4. 复制弹窗的以mkey:xxxx开头的key
5. 浏览器打开headscale-ui,点击“Device view”,并点击“New Device”
6. 将步骤4中复制的key粘贴到“Device Key”中,并选择对应用户,点后面的勾。
其他客户端
因笔者设备原因,android/macos等平台不做其他描述,手动添加设备的教程同IOS客户端中第3步以后所示。
0x08 路由转发
路由转发为接受路由转发,当你启动tailscale时加了--accept-routes参数之后,您启动命令中advertise-routes需要附带您当前设备能够访问的子网,这将会被通告出去。
举个例子,家中网段为192.168.0.0/24,设备A的ip地址为192.168.0.1,当开启路由转发后,从手机等设备访问192.168.0.0/24这个网段将通过设备A进行转发,可以直接联通家中所有局域网。
如您在`0x07 客户端连接`中的`linux客户端`教程中使用了路由转发功能,需要额外进行配置
# eth0为出口网卡名,tailscale0为tailscale网卡名,需根据实际修改 iptables -I FORWARD -i eth0 -j ACCEPT iptables -I FORWARD -o eth0 -j ACCEPT iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE iptables -I FORWARD -i tailscale0 -j ACCEPT iptables -I FORWARD -o tailscale0 -j ACCEPT iptables -t nat -I POSTROUTING -o tailscale0 -j MASQUERADE sysctl -w net.ipv4.ip_forward=1
0x09 后记
安装完成后使用命令进行测试,tailscale status
可以查看状态及错误信息,tailscale ping <IP>
可以查看是否打洞成功。如下图
本文参考了: