headscale+derp+tailscale异地组网

异地组网许多人都有需求,我也一样。最日常的应用场景是比如我希望,随时随地我可以在家里电脑,公司电脑,手机上访问家里和公司的局域网。之前尝试过Zerotier,但一来国内体验不好,当时我还在云服务上搭建了Moon但不知道什么原因也并没有改善,二来是还是需要在官网注册账号使用,这样就不是完全可控的。
最近发现tailscale的方案,本来tailscale的控制服务器不开源,他只是开源了客户端代码,也需要注册账号使用,但有个欧洲航天局的哥们开源个替代的控制服务器headscale,而且居然官方也认可。这样这个方案就完全可控。所以赶紧部署了一套使用。

控制服务器搭建在云服务器上,理论上应该最好是有IPv4+IPv6的双栈服务器,但我现在的服务器没有IPv6,等租期到了再考虑换,关于IPv6的作用后面再讨论

最方便的我还是采用docker部署,我这里是用nginx反向代理443到headscale,因为服务器的443端口还有其他作用

nginx的关键配置

stream {
    map $ssl_preread_server_name $backend_name {
        xx.xxxxx.com xxx;
        headscale.xxxxx.com headscale;
        default xxx;
    }

    # xxx
    upstream xxx {
        server 127.0.0.1:8443;
    }

    # headscale  这里是将特定域名的https请求转到9443的服务
    upstream headscale {
        server 127.0.0.1:9443;
    }

    server {
        listen 443 reuseport;
        listen [::]:443 reuseport;
        proxy_pass  $backend_name;
        ssl_preread on;
    }
}

http{
    map $http_upgrade $connection_upgrade {
        default      keep-alive;
        'websocket'  upgrade;
        ''           close;
    }

    server {
        listen 9443      ssl http2;
        server_name      headscale.xxxxx.com;

        ssl_certificate /path/xxxx.crt;
        ssl_certificate_key /path/xxxx.key;
        ssl_protocols TLSv1.2 TLSv1.3;

        location / {
            proxy_pass http://headscale:8080;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
            proxy_set_header Host $server_name;
            proxy_redirect http:// https://;
            proxy_buffering off;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
            add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
        }

        #headscale是默认就开启了api接口的swagger文档,不知道怎么关,安全起见屏蔽了
        location /swagger { 
            return 403;
            root  html;
            index index.html index.htm;
        }

        #headscale是默认就开启了api接口,我这里并不想使用网页控制,安全起见屏蔽了
        location /api {
            return 403;
            root  html;
            index index.html index.htm;
        }
    }
}

headscale容器docker-compose的关键配置

  headscale:
    image: headscale/headscale:latest-alpine
    volumes:
      - ./headscale/conf:/etc/headscale/
      - ./headscale/data:/var/lib/headscale
    ports:
      - 3478:3478/udp
    command: headscale serve
    restart: always
    cap_add:
      - NET_ADMIN
      - NET_RAW
      - SYS_MODULE
    sysctls:
      - net.ipv4.ip_forward=1
      - net.ipv6.conf.all.forwarding=1

headscale的关键配置

---
# 这个地址是告诉客户端需要访问的地址, 所以这个地址也必须写成反向代理前的访问地址
server_url: https://headscale.xxxxx.com
# Headscale 实际监听ip和端口,这个就是上面nginx反向代理到容器IP的端口
listen_addr: 0.0.0.0:8080
# grpc 监听地址,存疑,不知道有啥用,暂时没映射出容器
grpc_listen_addr: 0.0.0.0:50443
# 给vpn客户端分配的vpn网段
ip_prefixes:
  - fd7a:115c:a1e0::/48
  - 100.64.0.0/10
# 存疑,headscale的内置derp,但是否支持IPv6,是否会被白嫖还不清楚
derp:
  server:
    enabled: true
    region_id: 999
    region_code: "headscale"
    region_name: "Headscale Embedded DERP"
    stun_listen_addr: "0.0.0.0:3478"

其中最大的疑问是headscale内置的derp,网上很多教程都是不开,另外搭个derp容器,但那样很麻烦,我就希望headscale和derp部署在同一个机器上,那样做是否有必要?目前是先直接开启内置derp来用,也可以用,但有几个问题找不到答案:

  1. 内置derp是否可以防止被白嫖,是否需要做什么配置才可以防止?
  2. 内置derp是否支持IPv6,我尝试过临时租用了一台IPv4+IPv6的双栈服务器部署,但客户端依然显示ipv6: no, but os has support,是否stun_listen_addr配置问题?

部署好服务端后,先创建个命名空间(似乎新版本可以用user代替)

headscale namespaces create mynet

客户端有两种认证方式

  1. 通过nodekey接入
    客户端获取nodekey后在服务端运行

    headscale -n mynet nodes register --key nodekey:xxxxxxxxxxxxxx
  2. 通过Pre-Authkeys接入
    首先在服务端生成 pre-authkey 的 token,有效期可以设置为 24 小时

    headscale preauthkeys create -e 24h -n mynet

各种设备的客户端都可以使用tailscale的官方客户端

  1. 安卓手机客户端
    Android 客户端从 1.30.0 版本开始支持自定义控制服务器(即 coordination server),可以通过 Google Play 或者 F-Droid 下载最新版本的客户端。
    需要反复不停地点开再关闭右上角的“三个点”,重复三四次之后,便会出现一个 Change server 选项,填写自己的headscale服务地址后打开浏览器页面,显示nodekey,服务端使用命令通过nodekey接入
  2. Windows客户端
    其实通过访问部署好的headscale服务页面:https://headscale.xxxxx.com/windows有详细说明,包括如何在注册表添加相关内容,按照说明注册表修改好后,安装官方tailscale的windows客户端,然后可以通过CMD进行Pre-Authkeys接入

    cd "C:\Program Files\Tailscale\" 
    .\tailscale.exe up --login-server=https://headscale.xxxxx.com  --accept-dns=false --advertise-routes="192.168.1.0/24,192.168.2.0/24"  --authkey=xxxxxxxxxx   --accept-routes=true --reset

    此处我还添加了公司网段的路由,在服务器上也需要做运行路由转发操作:

    先查询接入设备ID
    headscale nodes list
    然后查看该设备注册的路由
    headscale routes list -i 2
    再允许注册路由
    headscale routes enable -i 2 -r "192.168.1.0/24,192.168.2.0/24"

    这样操作后,接入该headscale私网的设备就可以访问公司网段

  3. 群晖tailscale客户端
    不使用套件中心的tailscale客户端,会有诸多限制问题,使用docker部署。
    我是DSM7.1版本,先启用虚拟网络设备tun,通过配置服务的方式自启动

    sudo curl -sL https://raw.githubusercontent.com/TRaSH-Guides/Synology-Templates/main/script/tun.service -o "/etc/systemd/system/tun.service"
    
    sudo systemctl enable /etc/systemd/system/tun.service
    sudo systemctl start tun
    sudo systemctl status tun

    开启IPV4/IPV6转发

    echo 'net.ipv4.ip_forward = 1' | tee -a /etc/sysctl.conf
    echo 'net.ipv6.conf.all.forwarding = 1' | tee -a /etc/sysctl.conf
    sysctl -p /etc/sysctl.conf

    通过tailscale官方docker镜像启动客户端容器

    sudo docker run -d --name=ts \
    -v /volume1/docker/tailscale:/var/lib \
    -v /dev/net/tun:/dev/net/tun \
    -e TS_STATE_DIR=/var/lib/state/ \
    --restart unless-stopped \
    --cap-add NET_ADMIN \
    --cap-add NET_RAW \
    --cap-add SYS_MODULE \
    --network=host \
    tailscale/tailscale:latest \
    tailscaled --tun=tailscale0 -no-logs-no-support=true

    在容器中,通过接入

    docker exec -it ts tailscale login --login-server https://headscale.xxxxx.com --accept-dns=false --authkey xxxxxxx --advertise-routes=192.168.10.0/24 --accept-routes=true

    同样的,注册了家里网段的路由后,也需要在服务端进行允许操作

希望在家里的其他电脑也可以通过这个群晖访问到刚才配置的windows客户端的公司网段,需要配置iptables,可以将其写入计划任务,开机自动执行

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

同时在家里路由器中添加公司网段的静态路由,指向群晖。

通过这一些操作后,就可以实现手机/家里/公司电脑,都可以互相访问,并且可以访问到家里网段和公司网段的其他电脑。
并且如果打洞成功,是P2P连接,如果打洞不成功,也会走derp转发。比如公司网络环境复杂,其实就走了derp转发,而手机端和家里网络是P2P直连。

Headscale 联网示意图.png

已有 2 条评论

  1. 新盘首开 新盘首开 征召客户!!!coinsrore.com

  2. 字里行间饱含人文关怀,温暖而有力。

添加新评论