aniwoh的blog

使用headscale自建tailscale服务器

前言

由于国内的网络状况,连接tailscale官方的服务器不稳定,延迟很高,所以像zerotier一样,自建Moon服务器是比较好的。

但是Tailscale 的控制服务器是不开源的,而且对免费用户有诸多限制。好在目前有一款开源的实现叫 Headscale。

服务器端搭建

你需要:一台有公网IP的服务器

访问Github页面下载安装文件,我的服务器系统为Ubuntu20.04LTS,所以选择deb格式的安装包,当然,直接下载二进制文件自己配置也是一样的。

wget --output-document=headscale.deb \
  https://github.com/juanfont/headscale/releases/download/v0.22.3/headscale_0.22.3_linux_amd64.deb

安装headscale

sudo dpkg --install headscale.deb

出现这个页面就安装成功了

设置开机自启动

sudo systemctl enable headscale

编辑配置文件

vim /etc/headscale/config.yaml

按照你自己的需求更改,如果你不懂每一项的意思,先修改以下的选项

server_url: http://1.1.1.1:8080
listen_addr: 0.0.0.0:8080
grpc_listen_addr: 0.0.0.0:50443
ip_prefixes:
  - 192.168.100.0/24  

server_url改为你自己的服务器IP地址或者域名。

ip_prefixes在示例中的配置文件是分配ipv6的,但是我不需要,就删除了,同时,将100网段改为10或192网段,这是tailscale获取到的IP地址,在国内,100网段被运营商用来分配大内网IP了,所以不改的话会出现很多问题

headscale 启动!!!

sudo systemctl start headscale

查看运行状态

systemctl status headscale

运行成功

一些可能的问题:

推荐使用一台全新的服务器来安装headsscale,90%以上的问题是由于你的服务器本身安装的软件有冲突

headscale官方团队是不建议使用反向代理软件,如nginx、caddy等,但是实际上使用起来并不会有太大的问题,你可以参考这篇文章

补充

这里补充一下使用nginx反向代理时的配置方法:

nginx的配置文件

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

server {
    listen 80;
      listen [::]:80;
      listen 443      ssl http2;
      listen [::]:443 ssl http2;

    server_name example.com;

    ssl_certificate <PATH_TO_CERT>;
    ssl_certificate_key <PATH_CERT_KEY>;
    ssl_protocols TLSv1.2 TLSv1.3;

    location / {
        proxy_pass http://127.0.0.1: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配置文件

server_url: https://example.com
listen_addr: 0.0.0.0:8080
grpc_listen_addr: 0.0.0.0:50443
ip_prefixes:
  - 192.168.100.0/24  

将上述的example.com换成你自己的域名就可以了,假设你的nginx listen的是8081端口,headscale配置文件中的server_url也要加上8081端口,不用ssl的话,server_url也要用http代替https,并且,下面所有的login_server应该与你的server_url一样。

客户端搭建

openwrt

由于openwrt涉及一个本地路由的问题,所以我们先配置openwrt。

安装软件

opkg update
opkg install libustream-openssl ca-bundle kmod-tun
opkg install tailscale

注册tailscale

tailscale up --login-server=https://example.com:8080 --accept-routes=true --accept-dns=false

这里的login-server后也可换成你的ip

初始化成功后会出现URL,复制nodekey后的密钥

登录安装headscale的服务器

headscale users create admin  # 创建一个用户
headscale --user admin nodes register --key nodekey:<YOUR_MACHINE_KEY> # <YOUR_MACHINE_KEY>换成你的密钥

注册成功,查看节点

headscale nodes list

设置 openwrt的tailscale 开机自启动

/etc/init.d/tailscale enable

接下来我们启用本地路由
先配置ipv4和ipv6的路由转发

echo 'net.ipv4.ip_forward = 1' | tee /etc/sysctl.d/ipforwarding.conf
echo 'net.ipv6.conf.all.forwarding = 1' | tee -a /etc/sysctl.d/ipforwarding.conf
sysctl -p /etc/sysctl.d/ipforwarding.conf
这里需要注意,一旦你对openwrt的接口进行过修改,包括但不限于多拨等操作,你需要重新运行以上代码,不然会出现节点列表显示在线,但是无法连上的情况

客户端修改注册节点的命令,在原来命令的基础上加上参数 –advertise-routes=192.168.1.0/24,告诉 Headscale 服务器 “我这个节点可以转发这些地址的路由”。

tailscale up --login-server=http://<HEADSCALE_PUB_IP>:8080 --accept-routes=true --accept-dns=false --advertise-routes=192.168.1.0/24 --reset

查看openwrt的路由

headscale nodes list
# 找到openwrt对应的id,查看它的路由
headscale routes list -i 1


可以看到enabled为False,改为True

headscale routes enable  -r 1

这样就开启成功了,其他节点启动时需要增加 --accept-routes=true 选项来声明 “我接受外部其他节点发布的路由”。现在你在任何一个 tailscale 客户端所在的节点都可以 ping 通 openwrt 路由器所在内网的机器了。

Windows

接下来我们在windows上安装tailscale

在tailscale官网上下载安装包,安装好后先退出tailscale。

以管理员权限启动终端,输入以下命令,记得改为你自己的服务器地址

New-ItemProperty -Path 'HKLM:\Software\Tailscale IPN' -Name UnattendedMode -PropertyType String -Value always
New-ItemProperty -Path 'HKLM:\Software\Tailscale IPN' -Name LoginURL -PropertyType String -Value https://YOUR-HEADSCALE-URL

然后启动tailscale,点击log in你应该就会被重定向到自己的服务器,但是我运行后并不成功,所以采用另一种方法

仿照Linux,打开终端,输入

tailscale up --login-server <YOUR_HEADSCALE_URL> --accept-routes=true

运行后会出现一条URL,复制nodekey,按照上述同样的方法注册,注册成功后再启动tailscale程序,就登录成功了

安卓

下载并安装安卓端的tailscale程序,打开后点击右上角的三个点,一开始只会有版本号和About,然后再点击空白处,重复上述步骤,直到出现了Change Server选项

点击Change Server,改为自己的服务器地址,点击Save,回到程序主页面,不要用Google登录,点击sign in with other,会打开一个浏览器页面,复制node key,然后在服务器上注册,注册完成后回到程序就可以了

安卓端会自动允许route,不需要而额外操作

ios

没有ios设备,跳过

linux

Linux设备直接使用以下命令安装

curl -fsSL https://tailscale.com/install.sh | sh

默认该脚本会检测相关的 Linux 系统发行版并使用对应的包管理器安装 Tailscale, 安装完成后使用以下命令启动

tailscale up --login-server https://your.domain.com --accept-routes=true --accept-dns=false

启动完成后复制node key注册

常见问题

1、ERR error getting routes error="sql: database is closed"

问题现象:在修改过配置文件后重启服务,会卡在重启页面,查看systemctl status headscale日志时出现下图的错误

解决方案:ps -ef|grep headscale找到对应的pid,直接kill就行了,后续建议通过先stop,再restart来重启服务就不会卡住了

2、卸载headscale

sudo apt-get purge headscale
sudo apt-get autoremove
sudo apt-get clean

补充

headscale常用命令

headscale namespace list # 查看所有的namespace
headscale namespace create default # 创建namespace
headscale namespace destroy default # 删除namespace
headscale namespace rename default  myspace # 重命名namespace

headscale node list # 列出所有的节点
headscale node ls -t # 列出所有的节点,同时显示出tag信息
headscale -n default node ls # 只查看namespace为default下的节点
headscale node delete -i<ID> # 根据id删除指定的节点,这里面的id是node list查询出来的id
headscale node tag -i=2 -t=tag:test # 给id为2的node设置tag为tag:test

headscale routes list -i=9    # 列出节点9的所有路由信息
headscale routes enable -i=9 -r=192.168.10.0/24  #将节点9的路由中信息为192.168.10.0/24的设置为true

# preauthkeys主要是方便客户端快速接入,创建了preauthkeys后客户端直接使用该key就可以直接加入namespace
headscale -n default preauthkeys list # 查看名称为default的namespace中已经生成的preauthkeys 
headscale preauthkeys create -e 24h -n default # 给名称为default的namespace创建preauthkeys 

# apikeys是为了客户端和headscale做http鉴权用的,http请求的时候需要设置头部authorization
# 值为固定的字符串"Bearer "加apikeys创建的key
headscale.exe apikeys create # 创建apikeys,在创建的时候需要记录下完整的值,后续查询出来的都是prefix
                             # 值类似于zs3NTt7G0w.pDWtOtaVx_mN9SzoM24Y02y6tfDzz5uysRHVxwJc1o4
headscale.exe apikeys list -o=json #查询headscale的apikeys,并将结果输出成json格式

添加新评论