配置 RustDesk Server OSS
目标:在 Ubuntu 上部署 RustDesk Server OSS,运行 hbbs 和 hbbr,让客户端通过固定域名接入自建 ID / Relay 服务。
适用范围:
- 免费开源服务端 RustDesk Server OSS。
- 使用官方二进制文件和
systemd管理服务。 - RustDesk 文件统一放在
/root/rustdesk。 - Nginx 用于可选的 Web Client
WSS反向代理。
RustDesk Server Pro 还包含 Web Console、API、数据库、授权等内容,迁移时不能只复制 OSS 服务端文件。
核心概念
hbbs是 ID / 信令服务器,客户端会不断向它注册自己的 RustDesk ID、当前地址和端口。hbbr是中继服务器,直连或打洞失败时才走中继。id_ed25519是服务端私钥,id_ed25519.pub是给客户端填写的公钥。私钥仅保存在服务端。
客户端最小配置:
ID Server: rustdesk.example.com:21116
Relay Server: rustdesk.example.com:21117
Key: id_ed25519.pub 文件内容Relay Server 可以留空,由 hbbs 返回;使用非默认端口时,显式填写更稳妥。
1. 准备域名和端口
确定三个变量:
RUSTDESK_HOST=rustdesk.example.com
HBBS_PORT=21116
RUSTDESK_DIR=/root/rustdesk默认端口关系如下:
| 用途 | 协议 | 默认端口 | 说明 |
|---|---|---|---|
| NAT 类型检测 | TCP | 21115 | HBBS_PORT - 1 |
hbbs 主端口 | TCP/UDP | 21116 | 客户端 ID 注册、心跳、打洞 |
hbbr 主端口 | TCP | 21117 | 中继流量 |
hbbs WebSocket | TCP | 21118 | Web Client 可选 |
hbbr WebSocket | TCP | 21119 | Web Client 可选 |
DNS 里添加:
A记录:rustdesk.example.com指向服务器公网 IPv4。- 仅使用 IPv4 时,不创建
AAAA记录。 - 创建
AAAA记录时,防火墙和 Nginx 必须同时支持 IPv6。
2. 安装服务端二进制
以下命令默认以 root 执行:
sudo -i
apt update
apt install -y curl unzip
mkdir -p /root/rustdesk
cd /root/rustdesk
TAG=$(curl -fsSL https://api.github.com/repos/rustdesk/rustdesk-server/releases/latest \
| sed -n 's/.*"tag_name":[[:space:]]*"\([^"]*\)".*/\1/p' \
| head -n1)
curl -fL -o rustdesk-server-linux-amd64.zip \
"https://github.com/rustdesk/rustdesk-server/releases/download/${TAG}/rustdesk-server-linux-amd64.zip"
unzip -o rustdesk-server-linux-amd64.zip
chmod 755 ./amd64/hbbs ./amd64/hbbr ./amd64/rustdesk-utils下载完成后应有:
/root/rustdesk/amd64/hbbs
/root/rustdesk/amd64/hbbr
/root/rustdesk/amd64/rustdesk-utils3. 生成服务端密钥
新服务器第一次部署时生成一对密钥:
cd /root/rustdesk
./amd64/rustdesk-utils genkeypair | awk -F': ' '
/^Public Key:/ {print $2 > "id_ed25519.pub"}
/^Secret Key:/ {print $2 > "id_ed25519"}
'
chmod 600 /root/rustdesk/id_ed25519
chmod 644 /root/rustdesk/id_ed25519.pub检查公钥:
cat /root/rustdesk/id_ed25519.pub输出内容填入客户端网络设置里的 Key。/root/rustdesk/id_ed25519 是服务端私钥,不填入客户端。
迁移旧服务器时跳过本节密钥生成,直接复制旧服务器的 id_ed25519 和 id_ed25519.pub,操作见“完整迁移到新服务器”。
4. 写入统一环境文件
cat >/root/rustdesk/rustdesk.env <<'EOF'
RUSTDESK_HOST=rustdesk.example.com
HBBS_PORT=21116
HBBS_MAX_PACKET=52428800
EOF按实际情况修改:
RUSTDESK_HOST:客户端访问的域名。HBBS_PORT:hbbs主端口,默认21116。HBBS_MAX_PACKET:最大包大小,一般保持示例值。
5. 创建 systemd 服务
创建 hbbs 服务:
cat >/etc/systemd/system/rustdesk-hbbs.service <<'EOF'
[Unit]
Description=RustDesk ID/Signal Server (hbbs)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
Group=root
WorkingDirectory=/root/rustdesk
EnvironmentFile=/root/rustdesk/rustdesk.env
ExecStart=/bin/sh -lc 'exec /root/rustdesk/amd64/hbbs -p "${HBBS_PORT}" -r "${RUSTDESK_HOST}:$((HBBS_PORT + 1))" -M "${HBBS_MAX_PACKET}" -k _'
Restart=always
RestartSec=2
LimitNOFILE=100000
[Install]
WantedBy=multi-user.target
EOF创建 hbbr 服务:
cat >/etc/systemd/system/rustdesk-hbbr.service <<'EOF'
[Unit]
Description=RustDesk Relay Server (hbbr)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
Group=root
WorkingDirectory=/root/rustdesk
EnvironmentFile=/root/rustdesk/rustdesk.env
ExecStart=/bin/sh -lc 'exec /root/rustdesk/amd64/hbbr -p "$((HBBS_PORT + 1))" -k _'
Restart=always
RestartSec=2
LimitNOFILE=100000
[Install]
WantedBy=multi-user.target
EOF服务关键点:
WorkingDirectory=/root/rustdesk必须指向密钥所在目录,服务会从这里读取id_ed25519和id_ed25519.pub。hbbs -r "${RUSTDESK_HOST}:$((HBBS_PORT + 1))"用于返回中继服务器地址。hbbr不在默认推导路径上时必须显式配置。-k _表示使用工作目录里的服务端密钥文件。
启动服务:
systemctl daemon-reload
systemctl enable --now rustdesk-hbbs rustdesk-hbbr
systemctl status rustdesk-hbbs rustdesk-hbbr --no-pager6. 放行防火墙端口
原生客户端最小可用端口:
. /root/rustdesk/rustdesk.env
ufw allow $((HBBS_PORT - 1)):$((HBBS_PORT + 1))/tcp
ufw allow ${HBBS_PORT}/udp
ufw --force enable
ufw reload默认端口对应:
21115-21117/tcp
21116/udp使用 Web Client,并且由同机 Nginx 反向代理 21118 和 21119 时,公网额外放行:
ufw allow 80/tcp
ufw allow 443/tcp
ufw reload公网无需直接暴露 21118 和 21119。
7. 验证服务端
查看监听端口:
. /root/rustdesk/rustdesk.env
ss -lntup | grep -E ":($((HBBS_PORT - 1))|${HBBS_PORT}|$((HBBS_PORT + 1))|$((HBBS_PORT + 2))|$((HBBS_PORT + 3)))\\b"查看日志:
journalctl -u rustdesk-hbbs -u rustdesk-hbbr -n 100 --no-pager
journalctl -u rustdesk-hbbs -u rustdesk-hbbr -f从外部机器测试端口:
nc -vz rustdesk.example.com 21115
nc -vz rustdesk.example.com 21116
nc -vz rustdesk.example.com 21117UDP 端口不能只靠 nc -vz 判断,最终以两台客户端实际接入为准。
8. 配置客户端
在 RustDesk 客户端进入:
设置 -> 网络 -> 解锁网络设置填写:
ID Server:rustdesk.example.com:21116Relay Server:rustdesk.example.com:21117API Server:OSS 留空,Pro 才需要。Key:/root/rustdesk/id_ed25519.pub的内容。
控制端和被控端都要填同一组服务器信息。只配置一端是不够的,因为双方都需要向同一个 hbbs 注册。
推荐的客户端安全设置:
- 设置固定密码,或者使用确认连接。
- 禁止普通用户修改设备 ID。
- 关闭不需要的局域网发现。
- 不需要 IP 直连时关闭 IP 直连访问。
推荐的客户端网络设置:
- 开启 UDP 打洞。
- 网络支持 IPv6 时开启 IPv6 P2P。
9. 可选:配置 Web Client
OSS 服务端没有自带 Web 前端。浏览器访问的是 RustDesk 官方 Web Client:
https://rustdesk.com/web使用 Web Client 前,先在页面右上角菜单里配置自建服务器的 ID Server 和 Key。未配置时会连接 RustDesk 公共服务器。
Web Client 还需要通过 HTTPS 访问自建服务器的 WebSocket:
wss://rustdesk.example.com/ws/id-> 本机21118wss://rustdesk.example.com/ws/relay-> 本机21119
安装 Nginx 和 Certbot:
apt update
apt install -y nginx certbot python3-certbot-nginx
ufw allow 80/tcp
ufw allow 443/tcp
ufw reload先创建用于签证书的 HTTP 配置:
cat >/etc/nginx/sites-available/rustdesk-wss.conf <<'EOF'
server {
listen 80;
listen [::]:80;
server_name rustdesk.example.com;
location / {
default_type text/plain;
return 200 "rustdesk-wss\n";
}
}
EOF
rm -f /etc/nginx/sites-enabled/default
ln -sf /etc/nginx/sites-available/rustdesk-wss.conf /etc/nginx/sites-enabled/rustdesk-wss.conf
nginx -t
systemctl reload nginx
certbot --nginx -d rustdesk.example.com证书签发后,把配置替换为 WSS 反向代理:
cat >/etc/nginx/sites-available/rustdesk-wss.conf <<'EOF'
server {
listen 80;
listen [::]:80;
server_name rustdesk.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name rustdesk.example.com;
ssl_certificate /etc/letsencrypt/live/rustdesk.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/rustdesk.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
if ($http_origin ~* (https?://(www\.)?rustdesk\.com)) {
add_header Access-Control-Allow-Origin "$http_origin" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, PATCH, OPTIONS" always;
add_header Access-Control-Allow-Headers "Origin, Content-Type, Accept, Authorization" always;
add_header Access-Control-Allow-Credentials "true" always;
}
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin "$http_origin" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, PATCH, OPTIONS" always;
add_header Access-Control-Allow-Headers "Origin, Content-Type, Accept, Authorization" always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Content-Length 0;
return 204;
}
default_type text/plain;
return 200 "rustdesk-wss\n";
}
location /ws/id {
proxy_pass http://127.0.0.1:21118;
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;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 120s;
}
location /ws/relay {
proxy_pass http://127.0.0.1:21119;
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;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 120s;
}
}
EOFHBBS_PORT 变更时,这里的 21118 和 21119 同步改成 HBBS_PORT + 2 和 HBBS_PORT + 3。
验证:
nginx -t
systemctl reload nginx
curl -I https://rustdesk.example.com/10. 完整迁移到新服务器
OSS 服务端迁移的核心是保持“同域名、同端口、同密钥对”。满足这些条件后,客户端网络配置可以保持不变。
迁移条件:
- 客户端配置的是域名,例如
rustdesk.example.com:21116,不是旧服务器 IP。 - 新旧服务器使用同一对
id_ed25519和id_ed25519.pub。 - 新服务器开放相同端口。
hbbs的-r返回相同域名和中继端口。- DNS 最终指向新服务器。
迁移影响:
- 正在进行的远控会话可能中断。
- DNS 缓存未过期前,部分客户端可能还连到旧服务器。
- 新旧服务器同时在线时,客户端可能分散注册到两边,彼此短时间内看不到。迁移窗口内降低 DNS TTL,并在切换后停止旧服务器,可以减少分裂注册。
10.1 迁移前准备
提前一天把 DNS TTL 调低,例如 60 或 300 秒。递归 DNS 不一定严格遵守 TTL,低 TTL 只能降低切换时间,不能保证即时生效。
在旧服务器 A 上确认文件:
cd /root/rustdesk
ls -l id_ed25519 id_ed25519.pub rustdesk.env
sha256sum id_ed25519 id_ed25519.pub打包需要迁移的核心文件:
tar -C /root -czf /root/rustdesk-migrate.tgz \
rustdesk/id_ed25519 \
rustdesk/id_ed25519.pub \
rustdesk/rustdesk.envWeb Client 场景还需要迁移或重建:
/etc/nginx/sites-available/rustdesk-wss.conf- HTTPS 证书,或者在 B 上用 DNS-01 / 切换后 HTTP-01 重新签发。
- 与
ufw或云厂商安全组相关的端口规则。
10.2 在新服务器 B 上安装服务
在 B 上执行“安装服务端二进制”,跳过“生成服务端密钥”。
把 A 的迁移包复制到 B:
scp root@A_IP:/root/rustdesk-migrate.tgz /root/
mkdir -p /root/rustdesk
tar -C /root -xzf /root/rustdesk-migrate.tgz
chmod 600 /root/rustdesk/id_ed25519
chmod 644 /root/rustdesk/id_ed25519.pub在 B 上创建与 A 相同的 systemd 服务并启动:
systemctl daemon-reload
systemctl enable --now rustdesk-hbbs rustdesk-hbbr
journalctl -u rustdesk-hbbs -u rustdesk-hbbr -n 100 --no-pager确认 B 上公钥与 A 一致:
sha256sum /root/rustdesk/id_ed25519 /root/rustdesk/id_ed25519.pub
cat /root/rustdesk/id_ed25519.pubB 不得生成新密钥。新密钥会导致客户端原来的 Key 不匹配,连接时报 Key mismatch。
10.3 切换 DNS
确认 B 的端口已开放:
nc -vz B_IP 21115
nc -vz B_IP 21116
nc -vz B_IP 21117把 rustdesk.example.com 的 A / AAAA 记录改到 B。
切换后检查解析:
dig +short rustdesk.example.com @1.1.1.1
dig +short rustdesk.example.com @8.8.8.8DNS 切换后停止 A,减少“部分客户端注册到 A、部分客户端注册到 B”的分裂状态:
systemctl stop rustdesk-hbbs rustdesk-hbbr停止 A 后,仍缓存旧 IP 的客户端会短暂离线,并在 DNS 更新后集中注册到 B。保留 A 继续运行便于回滚,代价是迁移窗口内容易出现客户端分散注册。
10.4 回滚
B 连接异常时:
- DNS 改回 A。
- 启动 A 的
rustdesk-hbbs和rustdesk-hbbr。 - 停止 B 的服务,避免继续分裂注册。
A 和 B 使用同一对服务端密钥,回滚时客户端无需修改 Key。
11. 常见问题
Key mismatch
客户端里的 Key 和服务器当前使用的公钥不一致。
检查:
cat /root/rustdesk/id_ed25519.pub客户端 Key 必须使用该文件内容。迁移时同时确认 B 使用的是 A 的 id_ed25519 私钥,不能只复制 .pub 公钥。
Failed to connect to relay server
确认 hbbr 正在运行:
systemctl status rustdesk-hbbr --no-pager
journalctl -u rustdesk-hbbr -n 100 --no-pager确认 hbbs 的 -r 指向正确的中继地址:
rustdesk.example.com:21117hbbr 不在 hbbs 同机,或者不是默认 21117 时,必须在 hbbs -r 中显式声明。
域名解析正常但客户端离线
检查这些点:
- DNS 是否同时存在旧
AAAA记录。 - 云厂商安全组是否放行了
21115-21117/tcp和21116/udp。 - 本机
ufw是否放行。 - 客户端两端是否都配置了同一个
ID Server和Key。