/ Article / 92浏览

Headscale+Derp异地组网

文章目录

Tailscale是一种虚拟组网工具,基于WireGuard。能够把安装了Tailscale服务的机器,都连接到同一个局域网。局域网中的每台设备会自动分配IP,设备可以通过IP实现相互访问,除了延迟,与物理本地局域网相同。

Tailscale会优先使用中继服务器,保证最快可连接,之后尝试P2P连接,即两台设备之间数据不经过中继服务器直接连接。P2P连接成功之后,两台设备直接的延迟取决于两地距离,带宽取决于两地网络带宽上线,不再收中继服务器带宽约束。P2P连接中断时,自动fallback回中继服务器连接,优先保证可访问,其次优化连接速度。

Tailscale本身是一款商业软件,free版本支持3个用户和100个设备组网,但是中继服务器不在国内,在P2P连接失败后,网络延迟较大。可以通过自建中继节点接入官方控制器解决,其次,官方控制器在设备首次接入网络时,都需要使用相同的Google、微软账号登录,比较麻烦,因此选择使用Tailscale的开源替代版本Headscale。

安全方面,Tailscale网络之间的流量使用WireGuard协议传输,中继节点无法解密流量,外部设备需要进行授权才能加入网络,因此安全性较高。

组网成功并且两台设备之间可以通过P2P直连,延迟可以在个位数毫秒内。

网络拓扑

组网后网络拓扑如下,网络中每台设备会分配一个tailscale网络IP

搭建需求

  • 至少需要两台服务器,一台部署控制器,多台部署中继节点
  • 至少需要两个域名,一台指向控制器,另一台指向各个中继节点
  • 域名强制使用HTTPS,如果不使用Caddy等工具,需要手动上传、更新SSL证书,如果证书到期服务将无法使用
  • 控制器需要使用80、443端口,中继节点可自定义端口,但不使用443端口时,可能会与Clash冲突导致无法连接到中继节点

使用软件

GitHub – juanfont/headscale: An open source, self-hosted implementation of the Tailscale control server

GitHub – GoodiesHQ/headscale-admin: Admin Web Interface for juanfont/headscale

GitHub – fredliang44/derper-docker: tailscale‘s selfhosted derp-server docker image

安装前

创建Docker网络

docker network create headscale-network

服务端-1-控制器Headscale

安装位置/root/headscale

创建配置文件夹、数据文件夹、docker-compose文件

mkdir container-config  container-data
touch docker-compose.yml
version: '3'
services:
  headscale:
    container_name: headscale
    image: headscale/headscale:latest
    restart: unless-stopped
    volumes:
      - ./container-config:/etc/headscale
      - ./container-data:/var/lib/headscale
    entrypoint: headscale serve
    networks:
      headscale-network:
networks:
  headscale-network:
    external: true

container-config下创建配置文件config.yaml

先使用官方提供的配置文件模板,后续会对该文件进行修改



server_url: http://127.0.0.1:8080

配置文件第13行,需要改成指向服务器的域名

配置文件第19行,需要改成0.0.0.0:8080否则外部网络无法连接

此时文件目录如下所示

/root/headscale
├── container-config
│   └── config.yaml
├── container-data
└── docker-compose.yml

启动Headsale服务

docker compose up -d

服务端-1-Headsale管理面板

安装目录/root/headscale-admin

使用docker-compose运行

version: '3'
services:
  headscale-admin:
    image: goodieshq/headscale-admin:latest
    container_name: headscale-admin
    ports:
      - 8000:80
    networks:
      - headscale-network

networks:
  headscale-network:
    external: true

启动容器

docker compose up -d

目录结构如下

/root/headscale-admin/
└── docker-compose.yml

服务端-1-Caddy反代服务

Headscale强制要求HTTPS,此处使用Caddy是为了自动申请更新域名证书,可根据需要更换Nginx

安装目录/root/caddy

创建目录、配置文件

mkdir container-config  container-data
touch docker-compose.yml
services:
  caddy:
    image: caddy:latest
    container_name: caddy
    restart: always
    networks:
      headscale-network:
    stdin_open: true
    tty: true
    volumes:
      - ./container-data:/data
      - ./container-config:/config
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 80:80
      - 443:443
    entrypoint: /usr/bin/caddy run --adapter caddyfile --config /config/Caddyfile

networks:
  headscale-network:
    external: true

container-config下创建配置文件Caddyfile,自行更换example.com为服务器使用域名

https://example.com {
    reverse_proxy /admin/* http://headscale-admin
    reverse_proxy * http://headscale:8080
}

此时目录结构如下

/root/caddy
├── container-config
│   └── Caddyfile
├── container-data
└── docker-compose.yml

验证是否安装成功

访问以下地址https://<font style="color:rgb(55, 53, 47);">example.com/windows</font>,能正常访问说明以上步骤正确

管理面板配置

访问地址[https://example.com/admin/](https://headscale2.vio.vin/admin/settings/)进入管理面板,注意此处需要有最后的/

创建默认用户

docker exec headscale headscale users create default

获取用户加入节点时的key

docker exec headscale headscale preauthkeys create --user default

生成API密钥

docker exec headscale headscale apikey create

在管理面板填入API密钥,点击保存即可认证成功

注意:此处的Legacy API (Headscale < 0.23)选项需要关掉,如果失败可以打开控制台日志进行排错,浏览器中打开F12即可

  • Users:用于创建不同用户,不同用户之间可以隔离也可互相访问
  • Nodes:管理已加入Tailscale网络的设备,可以删除设备
  • Deploy:用于生成客户端加入Tailscale网络的指令,按照下图设置即可

服务端-2-中继节点Derper

中继节点作为客户端加入Tailscale网络

  • 此处是为了使用DERP_VERIFY_CLIENTS=true的功能更,用于中继节点授权,防止节点被公网其他用户使用
curl -fsSL https://tailscale.com/install.sh | sh

安装之后使用查看状态确保程序为active状态

systemctl status tailscaled.service

之后使用使用上一步生成的指令加入tailscale网络

tailscale up --login-server=https://headscale2.vio.vin --authkey=e228e7ddcc424e4a5eb4bec397ee493aa03f383fb608e804 --accept-dns=false --accept-routes

安装目录/root/derp

第15行,此处的域名应该使用节点域名,不可与Headscale域名相同

第10行,映射端口需要开启udp

version: '3'

services:
  derper:
    image: fredliang/derper
    container_name: derper
    restart: always
    ports:
      - 443:443
      - 34789:3478/udp
    volumes:
      - ./certs:/app/certs
      - /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock
    environment:
      - DERP_DOMAIN=example.com
      - DERP_VERIFY_CLIENTS=true

此时目录结构如下

/root/derp
└── docker-compose.yml

启动容器

docker compose up -d

访问derp域名确认已在运行

节点加入Headscale

/root/headscale/container-config下创建derp.yaml文件

regions:
  902:
    regionid: 902
    regioncode: chd
    regionname: HK Claw
    nodes:
      - name: 902a
        regionid: 902
        hostname: derp-hk.vio.vin
        stunport: 34789
        stunonly: false
        derpport: 443

此处的902为节点id,stunport为udp端口,derpport为derp HTTPS端口,其余按照上述自行填写

修改/root/headscale/container-config/config.yaml

注释掉114行,不需要tailscale官方的中继服务器

修改124、125行,指定derp.yaml文件地址

---
  # List of externally available DERP maps encoded in JSON
  urls:
    # - https://controlplane.tailscale.com/derpmap/default

  # Locally available DERP map files encoded in YAML
  #
  # This option is mostly interesting for people hosting
  # their own DERP servers:
  # https://tailscale.com/kb/1118/custom-derp-servers/
  #
  # paths:
  #   - /etc/headscale/derp-example.yaml
  paths: 
    - /etc/headscale/derp.yaml

  # If enabled, a worker will be set up to periodically
  # refresh the given sources and update the derpmap
  # will be set up.
  auto_update_enabled: true

  # How often should we check for DERP updates?
  update_frequency: 24h

用户使用

下载tailscale软件并自行安装

Download | Tailscale

打开CMD窗口,输入headscale管理面板中生成的命令,当显示Tailscale Connected时说明已经连接成功

点击Network devices可查看当前网络中的其他设备,点击可复制设备IP地址

高级功能

Subnet Routers

文档

Subnet routers · Tailscale Docs

按照上述示例配置后,每个设备需要在客户端单独运行tailscale才能加入tailscale网络,加入网络之后才能互相访问,如果需要加入网络的设备较多,此方法不够简单。

是否有什么办法可以将一个ip段或者一个局域网的设备全部拉入tailscale网络中呢,通过Subnet Routers可以实现。不适用Subnet Routers时,只能实现点对点互联,只有使用Subnet Routers才能实现真正的VPN功能。

假设网络拓扑为公司局域网ip段为192.168.31.0/24,将该局域网中任意一个设备的启动命令修改为

tailscale up --accept-routes=true --accept-dns=false --advertise-routes=192.168.31.0/24 --advertise-exit-node

该设备加入tailscale之后,会以该设备网为中继节点,访问局域网内其他设备,此处需要对防火墙出入站规则进行相应配置,tailscale启动后会创建一个tailscale0虚拟网卡,需要对此网卡关闭防火墙,允许出入站。

注意:

  1. 此处非常不建议使用192.168的网络前缀,容易与客户端网络发生冲突,建议改为10.XX.XX.0网段。
  2. 开启Subnet Routers功能的节点设备需要开启IP转发功能,具体参考以下文档。

Subnet routers · Tailscale Docs

Exit node

在上述启动命令中有一个参数--advertise-exit-node,该参数意味将该设备作为整个网络的出口节点,网络中所有设备访问互联网时,不会直接进行访问,所有流量会被转发到该设备,由该设备代理网络流量实现访问,该功能类似与传统意义的VPN,该功能并不是默认的,客户端需要手动设置才能使用Exit node功能。

Exit nodes (route all traffic) · Tailscale Docs

Access Control

默认情况下,同一个局域网内的设备互相可以访问,如果需要对该局域网下的设备进行分组隔离,可以使用tags功能,给加入网络的所有设备打上tag之后,可以通过acl设置设备之间的单向-双向访问,除tag之外,也支持对设备进行分组控制。首先需要修改配置文件,定义tag,此处以json配置文件为示例,自建Headscale需要以yaml为配置文件。

创建Tags

此处的"tag:home-pc",代表一个tag,后的中括号制定了谁可以使用这个tag,此处简单设置为管理员可以使用tag。

{
  "tagOwners": {
        "tag:home-pc":     ["autogroup:admin"],
        "tag:home-server": ["autogroup:admin"],
        "tag:work-pc":     ["autogroup:admin"],
        "tag:game-server": ["autogroup:admin"],
        "tag:game-player": ["autogroup:admin"],
        "tag:relay-node":  ["autogroup:admin"],
    },
}

访问控制

默认设置为{"action": "accept", "src": ["*"], "dst": ["*:*"]}所有设备之间可相互访问,如需自行控制需要删除这一行。

  • acls中包含多个访问规则
  • action个reject代表接收或拒绝连接。
  • src表示连接源,后可配置tag或group,格式为,示例["tag:game-player"]
  • dst表示连接目的地,格式为:<端口号>,示例["tag:game-server:*", "tag:game-server:8080", "tag:game-server:8000:9000"],
    • tag:game-server:*所有端口均可访问
    • tag:game-server:8080只允许访问8080端口
    • tag:game-server:8000:9000允许访问的端口范围为8000-9000
"acls": [
        // Allow all connections.
        // Comment this section out if you want to define specific restrictions.
        // {"action": "accept", "src": ["*"], "dst": ["*:*"]},
        {
            "action": "accept",
            "src":    ["tag:game-player"],
            "dst":    ["tag:game-server:*"],
        },
        {
            "action": "accept",
            "src":    ["tag:game-server"],
            "dst":    ["tag:game-player:*"],
        },
        {
            "action": "accept",
            "src":    ["tag:work-pc"],
            "dst":    ["*:*"],
        },
        {
            "action": "accept",
            "src":    ["tag:home-pc"],
            "dst":    ["*:*"],
        },
    ],

更多配置可以查看官方文档以其其他文档。

Group devices with tags · Tailscale Docs

Tailscale/Headscale ACL 使用教程

IPV6

启用IPV6可以提高直连几率,减少中继服务器流量负载,IPV6访问需要中继节点和客户端同时支持IPV6,且必须是240开头的公网IP地址。

其他

无人值守模式

开启次配置,tailscale将在设备开机时自动允许

不加入Subnet

如果遇到IP地址冲突,客户端可以暂时关闭subnet routers,关闭如下配置即可

排错

在客户端使用指令tailscale netcheck可以查看中继服务器状态

tailscale netcheck

使用tailscale status可查看当前客户端是否连接到tailscale网络,同时可查看网络中其他设备IP

如果遇到Subnet Router无法访问,需要按照此文档开启ip转发

Subnet routers · Tailscale Docs

参考文档

更新于
LibreOffice Python Macro 开发
LibreOffice Python Macro 开发
NAS文件备份
NAS文件备份
Ubunut 24 自建幸福工厂服务器
OpenWRT配置
OpenWRT配置
我的2024
我的2024
Grafana Uptime Resource监控
Grafana Uptime Resource监控

0

  1. This post has no comment yet

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注