Tailscale 自建 Derp 中转服务器(全程无 Docker + 无域名纯 IP 版本)

5,689 阅读10分钟

整体大纲

image.png


目的:为什么要建立 Derp 中转服务器

  • 官方给你的公用服务器一般情况下不在大陆,所以延迟高
  • 并且因为是公用的,可能会 拥挤,导致 不稳定

在大陆的情况下,为了降低延迟提高带宽,所以要自建 Derp


云服务器安装 Derp

以下是个人的操作,仅供参考~

Derp 中转服务器介绍

Tailscale 使用的算法很有趣: 所有客户端之间的连接都是先选择 DERP 模式(中继模式),这意味着连接立即就能建立(优先级最低但 100% 能成功的模式),用户不用任何等待。然后开始并行地进行路径发现,通常几秒钟之后,我们就能发现一条更优路径,然后将现有连接透明升级(upgrade)过去,变成点对点连接(直连)

因此, DERP 既是 TailscaleNAT 穿透失败时的保底通信方式(此时的角色与 TURN 类似),也是在其他一些场景下帮助我们完成 NAT 穿透的旁路信道。换句话说,它既是我们的保底方式,也是有更好的穿透链路时,帮助我们进行连接升级(upgrade to a peer-to-peer connection)的基础设施。

Tailscale 官方内置了很多 DERP 服务器,分步在全球各地,惟独不包含中国大陆,原因你懂得。这就导致了一旦流量通过 DERP 服务器进行中继,延时就会非常高。而且官方提供的 DERP 服务器是万人骑,存在安全隐患


安装 Go 环境

根据官方安装手册,需要先安装 go

在这里插入图片描述 先更新软件包列表,然后升级已安装的软件包

apt update && apt upgrade

等了大半年终于安完了,然后安装所需的软件,包括 wget、 git、 openssl、 curl

apt install -y wget git openssl curl

在这里插入图片描述

然后安装 go 语言(这里有一个坑,我没有安装最新版本的 go, 导致安装 Derp 的时候报错了,解决的办法就是 安装最新的 go,没关系可以继续往下看我是怎么处理的,你也可以在这里安装最新版的 go

wget https://go.dev/dl/go1.20.5.linux-amd64.tar.gz

我这里的云服务器 linux 连不上这个网,所以在本地直接下载了,然后传到服务器上面

然后参考 go 官方的安装手册

在这里插入图片描述

运行这行代码

rm -rf /usr/local/go && tar -C /usr/local -xzf go1.20.5.linux-amd64.tar.gz 

这里的 go1.20.5.linux-amd64.tar.gz 需要写成你下载的 go 版本

在这里插入图片描述 然后临时添加到环境变量

export PATH=$PATH:/usr/local/go/bin

之后验证一下是否安装成功

go version

在这里插入图片描述 如果想要永久添加到环境变量中,可以这样做

echo "export PATH=$PATH:/usr/local/go/bin" >> /etc/profile
source /etc/profile

解释一下上面的操作:

  • 虽然 export 命令和 source 命令都涉及修改 PATH,但它们的作用范围和持久性不同。
  • export 只对当前 shell 会话有效。
  • echo 命令将 export 命令写入配置文件,使其永久生效。
  • source 命令则使配置文件中的更改立即生效。

通过 Go 安装 Derp

安装 Derp 的时候报错了

在这里插入图片描述 可以看到报错信息,让你匹配 go 1.23,我刚才安装的是1.20.5,没关系,在安装 go 的最新版本,去官网重新下载一个最新版(我当前的是 2024-11-19 号,最新版为 1.23.3

在这里插入图片描述 然后安装,注意版本号,要是你当前最新的

rm -rf /usr/local/go && tar -C /usr/local -xzf go1.23.3.linux-amd64.tar.gz 

在这里插入图片描述

然后 go version 看一下版本,可以看到安装完之后是直接生效的,不用添加什么环境变量了,因为之前已经永久加过了

在这里插入图片描述

之后接着用 go 运行下载 Derp 的命令

go install tailscale.com/cmd/derper@latest

在这里插入图片描述

处理证书文件

安装好之后,我们要解决一下域名的校验问题

看一下这个路径下的证书文件

在这里插入图片描述

把框框中的三行代码注释掉

可以简单看一下,这是验证域名的用途,因为我们是没有域名,纯ip,所以这个地方注释掉,不要去校验

在这里插入图片描述

然后重新用 go 编译一下,并输出到指定目录

在这里插入图片描述

自签一个域名给 Derp

接着我们用命令自签一个 Https 的域名 derp.myself.com

在这里插入图片描述

cat > /etc/systemd/system/derp.service <<EOF
[Unit]
Description=TS Derp
After=network.target
Wants=network.target
[Service]
User=root
Restart=always
ExecStart=/etc/derp/Derp -hostname derp.myself.com -a :33445 -http-port 33446 -certmode manual -certdir /etc/derp
RestartPreventExitStatus=1
[Install]
WantedBy=multi-user.target
EOF

把云服务的 tcp 33445 (HTTPS 需要)和 udp3478 (STUN需要)的端口打开

然后输入如下命令,打开自启,以及立即启动 Derp 服务

systemctl enable derp:启用 derp 服务,使其在系统启动时自动启动。 systemctl start derp:立即启动 derp 服务

在这里插入图片描述

如果你是用 宝塔的话,不仅是云服务器那边需要开启相对应的端口,宝塔的安全也要开启相应端口!


验证 Derp 是否启动

在浏览器中输入https://your ip:33445/ 即可

在这里插入图片描述


云服务器安装并登录 Tailscale

在服务器安装 Tailscale

sudo apt install tailscale

如果下载太慢,参考这个解决apt install 下载速度太慢,配置一个国内的源

在这里插入图片描述

检查网络

tailscale netcheck

在这里插入图片描述

可以看到我们用的 Derp 列表都是国外的,延迟比较高,下文会逐步讲解到添加自建的 Derp

然后可以用 tailscale status 查看状态,这里我的 linux 还没有登录 Tailscale

在这里插入图片描述

这里有两种组合

  • 一个是官方账号 + 自己的 Derp:简单,但是不够自由,比方说我要让别人添加到我的局域网中,我就没研究明白这个...
  • 另一个是 自己建的 Headscale + 自己的 Derp:复杂一些,但是可控性更高,可以让其他人加入到我的局域网

第一种组合: 官方 Tailscale 账号 + 自己的 Derp 中转

登录官网 tailscale ,并用你的账号登录,之后在你组的网络中,添加一个 linux 设备

在这里插入图片描述 生成 install 的 script 然后返回 linux 中运行

然后再 Access controls 中指定你的 Derp,把其他的节点都屏蔽掉

在这里插入图片描述 这样就可以了

第二种组合:自建 Headscale + 自建 Derp (无域名版本)

自建 Headscale 教程我在另一篇文章有讲过,具体可以在这里查看 ,我这里接着讲

如果是自己没有域名,那么可以用自签的 IP,这种情况下,配置 Headscaleconfig.yaml

注意:

  • 只能用 json,只能用 json,只能用 json!!!
  • 只能用 json,只能用 json,只能用 json!!!
  • 只能用 json,只能用 json,只能用 json!!!

配置 path 指定为 derp.yaml 是不好使的!!!

TM的 试了好久的 yaml,都他妈不好使 应该是个bug 吧?大概

在这里插入图片描述

无论是那种办法,我们的目的是:让 headscale 拿到我自建的 Derp 服务器的信息

那么,我的思路就是:用 Nginx 建立一个反向代理,然后指定到 derp.json,用 Nginx 代理一下

在这里插入图片描述 这里是 derp.json 的内容

在这里插入图片描述

其他的一些配置

自建 Derp 提供 IPv6 的支持(隧道版本,不推荐,延迟高)

这个是效果,虽然能够使用 IPv6,但是是通过隧道的模式,选择香港的节点,还是延迟很高,所以我放弃了,这里简单的说明一下

如果你的服务器自带 IPv6,就直接配置你的地址即可 在这里插入图片描述

代码如下

network:
  version: 2
  tunnels:
    he-ipv6:
      mode: sit
      remote: 216.218.221.6
      local: 内网ip
      addresses:
        - "2001:470:18:e6d::2/64"
      routes:
        - to: default
          via: "2001:470:18:e6d::1"

可以看到已经可以直联了

还是根据视频的步骤来,但是我这里选择的 linux

在这里插入图片描述

然后大概长成这个样子:

在这里插入图片描述

然后保存, reboot 一下服务器


防止 Derp 被白嫖(添加客户端验证)

具体的原理参考一下这个大佬的博客

进入服务器 /etc/systemd/system 路径下的

在这里插入图片描述

--verify-clients: 这个选项要求客户端进行验证,但具体的验证机制没有详细说明。如果只是简单的验证,可能不足以防止未授权访问

保存文件之后,重启一下 Derp

在这里插入图片描述


参考

  1. 官方自建 Derp
  2. 解决apt install 下载速度太慢
  3. Tailscale玩法之内网穿透、异地组网、全隧道模式、纯IP的双栈DERP搭建、Headscale协调服务器搭建,用一期搞定,看一看不亏吧?
  4. 纯 IP 配置 Derp 提供帮助的帖子:headscale组网自建derp中继节点,国内也可以
  5. Tailscale 基础教程:部署私有 DERP 中继服务器

以上的操作命令合集

————局域网1设置部分

tailscale up --netfilter-mode=off  --advertise-routes=局域网网段 --accept-routes

————群晖设置部分

sudo -i

echo -e '#!/bin/sh -e \ninsmod /lib/modules/tun.ko' > /usr/local/etc/rc.d/tun.sh
chmod a+x /usr/local/etc/rc.d/tun.sh
/usr/local/etc/rc.d/tun.sh
ls /dev/net/tun

参考ZeroTier群晖的安装
资料:https://docs.zerotier.com/devices/synology


docker run -d \
  --name=ts	\
  --restart=always	\
  -v /var/lib:/var/lib \
  -v /dev/net/tun:/dev/net/tun \
  --network=host	\
  --cap-add=NET_ADMIN	\
  --cap-add=NET_RAW	\
  --env TS_STATE_DIR=/etc/ts \
  --env TS_SOCKET=/var/run/tailscale/tailscaled.sock \
  --env TS_USERSPACE=false \
  --env TS_ROUTES=局域网网段  \
  --env TS_EXTRA_ARGS="--accept-routes --advertise-exit-node --reset" \
  --env TS_AUTHKEY=API密钥   \
tailscale/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

sleep 1m


————云服务器derp中转服务器搭建部分

apt update && apt upgrade

apt install -y wget git openssl curl

wget https://go.dev/dl/go1.20.5.linux-amd64.tar.gz

rm -rf /usr/local/go && tar -C /usr/local -xzf go1.20.5.linux-amd64.tar.gz

export PATH=$PATH:/usr/local/go/bin
go version

echo "export PATH=$PATH:/usr/local/go/bin" >> /etc/profile
source /etc/profile

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

go install tailscale.com/cmd/Derp@main

go build -o /etc/derp/Derp

ls /etc/derp

openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout /etc/derp/derp.myself.com.key -out /etc/derp/derp.myself.com.crt -subj "/CN=derp.myself.com" -addext "subjectAltName=DNS:derp.myself.com"

cat > /etc/systemd/system/derp.service <<EOF
[Unit]
Description=TS Derp
After=network.target
Wants=network.target
[Service]
User=root
Restart=always
ExecStart=/etc/derp/Derp -hostname derp.myself.com -a :33445 -http-port 33446 -certmode manual -certdir /etc/derp
RestartPreventExitStatus=1
[Install]
WantedBy=multi-user.target
EOF

systemctl enable derp
systemctl start derp


"derpMap": {
		"OmitDefaultRegions": true,
		"Regions": {
			"901": {
				"RegionID":   901,
				"RegionCode": "Myself",
				"RegionName": "Myself Derp",
				"Nodes": [
					{
						"Name":             "901a",
						"RegionID":         901,
						"DERPPort":         33445,
						"IPv4":   "服务器IP",
						"InsecureForTests": true,
					},
				],
			},
		},
	},




			"1":  null,
			"2":  null,
			"3":  null,
			"4":  null,
			"5":  null,
			"6":  null,
			"7":  null,
			"8":  null,
			"9":  null,
			"10": null,
			"11": null,
			"12": null,
			"13": null,
			"14": null,
			"15": null,
			"16": null,
			"17": null,
			"18": null,
			"19": null,
			"20": null,
			"21": null,
			"22": null,
			"23": null,
			"24": null,	
			"25": null,


tailscale netcheck

tailscale status

tailscale ping 

ping6 240C::6666

tailscale down 

tailscale up

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

nano /etc/systemd/system/derp.service

--verify-clients

systemctl daemon-reload

systemctl restart derp


————headscale搭建部分

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

sudo dpkg --install headscale.deb

sudo systemctl enable headscale

nano /etc/headscale/config.yaml

apt install -y nginx


map $http_upgrade $connection_upgrade {
    default      keep-alive;
    'websocket'  upgrade;
    ''           close;
}
server {
    listen 3355;
    listen [::]:3355;
    server_name 云服务器IP;
    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_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;

    }
    
    location /web {
		index  index.html;
        	alias  /var/www/web;
	}
}


wget https://github.com/gurucomputing/headscale-ui/releases/download/2023.01.30-beta-1/headscale-ui.zip

unzip -d /var/www headscale-ui.zip

systemctl start headscale

systemctl restart nginx

headscale apikeys create --expiration 9999d

tailscale logout
tailscale up --login-server=http://云服务器IP:3355

touch /var/www/derp.json


{
	"Regions": {
		"901": {
			"RegionID":   901,
			"RegionCode": "Myself",
			"RegionName": "Myself Derp",
			"Nodes": [
					{
					"Name":             "901a",
					"RegionID":         901,
					"DERPPort":         33445,
					"IPv4":   "IP地址",
					"IPv6":    "IP地址",
					"InsecureForTests": true
				}
			]
		}
	}
}



server {
	listen 80;
	listen [::]:80;

	server_name 127.0.0.1;

	root /var/www;
	index index.html index.htm index.nginx-debian.html;
	location /d {
		alias   /var/www;
		autoindex on;
	}
	location / {
		try_files $uri $uri/ =404;
	}
}


- http://127.0.0.1/d/derp.json


systemctl restart nginx
systemctl restart headscale

tailscale logout
tailscale up --login-server=http://你的云服务器ip:端口



————改善github下载速度慢的解决方案

下面代码可以放到/etc/hosts文件的末尾,然后重启云服务器就可以

20.205.243.166 github.com
159.24.3.173 gist.github.com
185.199.110.153 assets-cdn.github.com
185.199.110.153 raw.githubusercontent.com
185.199.110.153 gist.githubusercontent.com
185.199.110.153 cloud.githubusercontent.com
185.199.110.153 camo.githubusercontent.com
185.199.110.153 avatars0.githubusercontent.com
185.199.110.153 avatars1.githubusercontent.com
185.199.110.153 avatars2.githubusercontent.com
185.199.110.153 avatars3.githubusercontent.com
185.199.110.153 avatars4.githubusercontent.com
185.199.110.153 avatars5.githubusercontent.com
185.199.110.153 avatars6.githubusercontent.com
185.199.110.153 avatars7.githubusercontent.com
185.199.110.153 avatars8.githubusercontent.com


不过需要注意,ip可能之后需要更新,可以去站长工具,ping后面的域名来获取。