目 录CONTENT

文章目录

搭建derper服务实现异地组网

geekrabbit
2023-03-03 / 0 评论 / 0 点赞 / 181 阅读 / 8,938 字 / 正在检测是否收录...
温馨提示:
创作不易,转载请注明出处

DERP

DERP 即 Detoured Encrypted Routing Protocol,这是 Tailscale 自研的一个协议:

它是一个通用目的包中继协议,运行在 HTTP 之上,而大部分网络都是允许 HTTP 通信的。
它根据目的公钥(destination’s public key)来中继加密的流量(encrypted payloads)。

image.png

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

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

tailscale以及headscale是当下最好的组网方案,可以搭建私有的vpn网络实现,

用来内网穿透,用来神奇上网,用来组建异地集群,配图

对个人用户来说,所处的网络环境比较复杂,很多时候会无法建立点对点的直连,配图,连接失败

这就需要 derp relay server,derp不仅是一个中转服务器,它也有stun的功能

tailscale官方在许多国家都有derp 服务器,这是列表,如果没有条件自建的可以去挑官方的来使用,

https://login.tailscale.com/derpmap/default

一方面毕竟是异国他乡,一方面公共服务器带宽有限用的人多了就体验很差了。

为了保证穿透的可用性和体验,我们就要付出一些成本,搭建一个私有的中转服务 derp relay server

derp服务有一个特点

节点与节点进行连接时,会首先通过derp服务进行中转连接,以此让穿透立刻实现,因为中转服务是可以保证100%连接成功的,配图

然后,derp服务尝试让两个节点进行点对点的直连,如果直连成功,derp不再中转数据

否则,穿透会一直通过derp进行中转 

所以derp是可以极大的提高穿透体验的,但是,总要有个但是

derp服务搭建完毕后,别人只要知道了你的域名和端口就可以白嫖你的服务了,难受

我的物理拓扑图

网物理拓扑.png

我的网络拓扑图

最终实现把4个不同地区的4条宽带下的设备连到一起,在不同网络下客户端设备实现通过内网ip来访问内网设备资源,实现异地组网,不用通过端口映射到公网再去访问

image.png

搭建derp服务有两种办法

方案一是通过docker安装,但是需要下依赖包,速度会比较慢,甚至安装失败,最好的办法其实就是要么不停的重试,要么用神奇上网

一种是下载安装二进制文件,在服务器或者vps上配置golang环境,编译安装,但是如果你的服务器在中国国内,那安装依赖和编译都是非常痛苦的

docker安装

确保vps上docker运行正常

# 安装docker
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
systemctl start docker
systemctl enable docker
docker info

部署derper


  docker run --restart always \
  --name derper -p 81:12345 -p 3478:3478/udp \
  -e DERP_ADDR=:12345 \
  -e DERP_DOMAIN=域名 \
  -d ghcr.io/yangchuansheng/derper:latest
  
  # nginx会把81反代到443
  
  
  # 如果不是用nginx代理的话就要直接把证书申请好
  docker run --restart always \
  --name derper -p 12345:12345 -p 3478:3478/udp \
  -e DERP_CERT_MODE=manual \
  -e DERP_ADDR=:12345 \
  -e DERP_DOMAIN=域名 \
  -d ghcr.io/yangchuansheng/derper:latest
  
  # 查看容器运行情况
  docker logs -f derper
  

编译安装

上面是docker安装的过程,如果你不想用docker,也可以直接编译安装

安装golang环境,版本必须大于1.16

wget https://golang.google.cn/dl/go1.19.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.19.linux-amd64.tar.gz 
# 注意 #
# 如果是升级golang,先删掉原来的go目录,不然可能会有问题#

在/etc/profile添加

export GOROOT=/usr/local/go
export GOPATH=/usr/local/gopath
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOROOT/bin
export PATH=$PATH:$GOPATH/bin

刷新

source /etc/profile

安装derp

go version
# 国内可以尝试代理
#go env -w GOPROXY=https://goproxy.cn,direct
#go env -u GOPROXY
go install tailscale.com/cmd/derper@main
derper -h

解析一个域名到这个vps,如果是国内的话域名必须备案才能用,香港的目前还不用备案

域名可以是二级域名,必须是A记录

使用supervisor守护

sudo yum install supervisor

/etc/supervisord.d/derper.conf

[program:derper]
command=/usr/local/gopath/bin/derper --hostname=域名  -c $HOME/derper.conf --stun -http-port -1   -a :81
autorestart=true
user=root
redirect_stderr=true
stdout_logfile=/var/log/supervisor/derper.log
stderr_logfile=/var/log/supervisor/derper-err.log
stdout_logfile_maxbytes=5MB
stdout_logfile_backups=1

重启supervisord

sudo systemctl restart supervisord
sudo systemctl enable supervisord

申请证书

sudo yum install epel-release -y


sudo pip uninstall urllib3 -y
sudo pip uninstall requests -y
sudo yum remove python-urllib3 -y
sudo yum remove python-requests -y


sudo yum install python-urllib3 -y
sudo yum install python-requests -y
sudo yum install certbot -y



# 申请证书,注意此时vps上的80端口必须是未被占用状态,否则失败#
sudo certbot certonly --standalone -d 域名

# 证书路径为/etc/letsencrypt/live/域名/
# 证书有效期只有3个月,每次更新的时候要先关掉nginx服务,在执行#
certbot renew
systemctl start nginx

nginx反向代理

# centos7 为例
sudo yum install epel-release -y
sudo yum install nginx -y

添加/etc/nginx/conf.d/derper.conf,内容如下


server {
    listen 443 ssl;
    server_name 域名;
    charset utf-8;

    ssl_certificate /etc/letsencrypt/live/域名/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/域名/privkey.pem;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 5m;
    keepalive_timeout 70;


    location / {
        proxy_redirect off;
        proxy_pass http://127.0.0.1:81; # port
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

systemctl start nginx

systemctl enable nginx

tailscale测试derp

derper搭建完毕,但是要注意,现在任何人都可以使用我们的derper服务,一会加个认证,在此之前,我们先测试下效果

确保你的vps的443端口与3478端口开放

如果你用的是tailscale,打开tailscale控制台,打开access controls

// Example/default ACLs for unrestricted connections.
{
  // Declare static groups of users beyond those in the identity service.
  "Groups": {
    "group:example": [ "user1@example.com", "user2@example.com" ],
  },
  // Declare convenient hostname aliases to use in place of IP addresses.
  "Hosts": {
     "example-host-1": "100.100.100.100",
  },
  "ACLs": [
    // Match absolutely everything. Comment out this section if you want
    // to define specific ACL restrictions.
    { "Action": "accept", "Users": ["*"], "Ports": ["*:*"] },
  ],
  "derpMap": {
    "OmitDefaultRegions": true,
    "Regions": { "900": {
      "RegionID": 900,
      "RegionCode": "mangoderp",
      "RegionName": "AliHongkong",
      "Nodes": [{
          "Name": "1",
          "RegionID": 900,
          "HostName":"域名",
          "DERPPort": 443
      }]
    }}
  }
}

以下是原内容备份

// Example/default ACLs for unrestricted connections.
{
	// Declare static groups of users beyond those in the identity service.
	"groups": {
		"group:example": ["user1@example.com", "user2@example.com"],
	},

	// Declare convenient hostname aliases to use in place of IP addresses.
	"hosts": {
		"example-host-1": "100.100.100.100",
	},

	// Access control lists.
	"acls": [
		// Match absolutely everything.
		// Comment this section out if you want to define specific restrictions.
		{"action": "accept", "users": ["*"], "ports": ["*:*"]},
	],
	"ssh": [
		// Allow all users to SSH into their own devices in check mode.
		// Comment this section out if you want to define specific restrictions.
		{
			"action": "check",
			"src":    ["autogroup:members"],
			"dst":    ["autogroup:self"],
			"users":  ["autogroup:nonroot", "root"],
		},
	],
}

headscale使用derp

修改主配置文件config.yaml

paths:
    - /etc/headscale/derp.yaml
    

/etc/headscale/derp.yaml添加内容

# /etc/headscale/derp.yaml
regions:
  900:
    regionid: 900
    regioncode: ahk 
    regionname: AliHongkong 
    nodes:
      - name: 900a
        regionid: 900
        hostname: 域名
        # ipv4: ip
        stunport: 3478
        # stunonly: false
        derpport: 443

重启headscale

# 查看节点#
tailscale netcheck

截止到目前,已经能够使用了

image.png

开启https验证

刚才说了,现在derp是没有加验证的,谁都可以白嫖我们的服务,这是不允许的

安装tailscale客户端

直接下载。例如:

https://pkgs.tailscale.com/stable/

wget <https://pkgs.tailscale.com/stable/tailscale_1.28.0_amd64.tgz>

解压:

tar zxvf tailscale_1.28.0_amd64.tgz x tailscale_1.28.0_amd64/ x

tailscale_1.28.0_amd64/tailscale x tailscale_1.28.0_amd64/tailscaled x tailscale_1.28.0_amd64/systemd/ x tailscale_1.28.0_amd64/systemd/tailscaled.defaults x tailscale_1.28.0_amd64/systemd/tailscaled.service

将二进制文件复制到官方软件包默认的路径下:

cp tailscale_1.28.0_amd64/tailscaled /usr/sbin/tailscaled
cp tailscale_1.28.0_amd64/tailscale /usr/bin/tailscale
chmod +x /usr/sbin/tailscaled
chmod +x /usr/bin/tailscale

将 systemD service 配置文件复制到系统路径下:

cp tailscale_1.28.0_amd64/systemd/tailscaled.service /lib/systemd/system/tailscaled.service

将环境变量配置文件复制到系统路径下:

cp tailscale_1.28.0_amd64/systemd/tailscaled.defaults /etc/default/tailscaled

启动 tailscaled.service 并设置开机自启:

$ systemctl enable --now tailscaled

查看服务状态:

$ systemctl status tailscaled

修改derp启动,加上验证

command=/usr/local/gopath/bin/derper --hostname=域名  -c $HOME/derper.conf -http-port -1 -a :81 --verify-clients=true --stun 

这个验证只是验证是否是允许的域名,并不做身份验证,这意味着,别人只要知道了你的域名和端口,就可以白票你的derper服务,这一点请知晓

相比而言,zerotier的moon服务就没有这个问题了。

避坑指南

  • 在 tailscale 的实现里,即使没配置好 https 也会在控制页面显示 derp 服务可用,但实际不能用,也没有看到日志输出,难排查错误
  • caddy 反向代理 https 但上游用的是 ip 地址时,加上 tls_server_name 选项,这个我找了好久,虽然解决了对最后也没啥帮助,相关讨论。 之前没有折腾过,一直以为 https 的反向代理就是一句配置就完事了,但事实上比想象中要复杂。

多节点配置文件

// Example/default ACLs for unrestricted connections.
{
	// Declare static groups of users beyond those in the identity service.
	"Groups": {
		"group:example": ["user1@example.com", "user2@example.com"],
	},
	// Declare convenient hostname aliases to use in place of IP addresses.
	"Hosts": {
		"example-host-1": "100.100.100.100",
	},
	"ACLs": [
		// Match absolutely everything. Comment out this section if you want
		// to define specific ACL restrictions.
		{"Action": "accept", "Users": ["*"], "Ports": ["*:*"]},
	],
	"derpMap": {
		"OmitDefaultRegions": true,
		"Regions": {
			"900": {
				"RegionID":   900,
				"RegionCode": "hb",
				"RegionName": "xingtai",
				"Nodes": [{
					"Name":     "1",
					"RegionID": 900,
					"HostName": "aaaa.com",
					"DERPPort": 3489,
				}],
			},

			"901": {
				"RegionID":   901,
				"RegionCode": "xg",
				"RegionName": "Hongkong",
				"Nodes": [{
					"Name":     "1",
					"RegionID": 901,
					"HostName": "xxx.com",
					"DERPPort": 443,
				}],
			},
		},
	},
}
0

评论区