这份记录面向一台 Ubuntu 22.04、AMD64、1 核 2 GB 的 VPS。目标是在同一台服务器上运行 RustDesk Server OSS 与 FRP 服务端(FRPS),并通过 systemd 管理进程和开机自启。
最终方案里,RustDesk 使用 Techahold 的安装脚本部署 hbbs 与 hbbr;FRPS 使用原生二进制、TOML 配置和独立低权限用户。FRPS 控制端口为 7000/TCP,Dashboard 只监听 127.0.0.1:7500,需要时通过 SSH 隧道访问,不直接暴露到公网。
执行远程脚本和启用 UFW 都可能影响服务器可用性。操作前先保留一个可用的 SSH 会话,并确认实际 SSH 端口已经在系统防火墙与云安全组中放行。
部署方案与端口规划
RustDesk Server OSS 由两个程序组成:
| 程序 | 作用 |
|---|---|
hbbs |
ID 注册、心跳、NAT 类型测试与连接协调 |
hbbr |
P2P 无法建立时中继流量 |
FRP 部分只在 VPS 上部署 frps。内网设备运行 frpc,主动连接 VPS 的 7000/TCP,再按需创建业务端口映射。服务端通过 allowPorts 将可申请的远程端口限制在 30000–39999。
部署前先安装基础工具并确认架构:
apt update
apt install -y curl wget unzip tar openssl ca-certificates tmux ufw
dpkg --print-architecture
uname -m
在本文环境中,AMD64 主机应分别显示 amd64 与 x86_64。如果结果不同,后续 RustDesk 和 FRP 二进制包也要改成对应架构。
部署 RustDesk Server OSS
下载并检查安装脚本
RustDesk 官方文档将 Techahold 脚本列为一种 systemd 安装方式。脚本会从 RustDesk Server Release 下载当前版本的 hbbs、hbbr,写入 /opt/rustdesk,并创建 rustdesksignal.service 与 rustdeskrelay.service。
远程脚本会变化,因此先保存到本地并检查内容,不直接通过管道执行:
mkdir -p /root/rustdesk-install
cd /root/rustdesk-install
wget https://raw.githubusercontent.com/techahold/rustdeskinstall/master/install.sh
chmod +x install.sh
less install.sh
直接使用 VPS 公网 IP:
./install.sh --resolveip --skip-http --no-sudo
使用已经解析到 VPS 的域名:
./install.sh \
--resolvedns "rd.example.com" \
--skip-http \
--no-sudo
这些参数的含义如下:
| 参数 | 说明 |
|---|---|
--resolveip |
由脚本解析当前 VPS 公网 IP |
--resolvedns |
使用指定的完整域名 |
--skip-http |
不安装额外的客户端下载 HTTP 服务 |
--no-sudo |
当前已经使用 root 执行,不再调用 sudo |
服务器上若已有 Nginx、WordPress 或其他 Web 服务,保留 --skip-http 可以避免脚本额外启用 8000/TCP。
检查服务和开机自启
脚本安装完成后,先检查两个服务的完整状态:
systemctl status rustdesksignal --no-pager -l
systemctl status rustdeskrelay --no-pager -l
再分别检查是否已经启用开机启动、当前是否处于运行状态:
systemctl is-enabled rustdesksignal
systemctl is-enabled rustdeskrelay
systemctl is-active rustdesksignal
systemctl is-active rustdeskrelay
正常情况下,前两条命令应返回 enabled,后两条应返回 active。如果服务存在但尚未启用:
systemctl enable --now rustdesksignal
systemctl enable --now rustdeskrelay
配置 RustDesk 防火墙
启用 UFW 前,先放行服务器实际使用的 SSH 端口:
ufw allow SSH_PORT/tcp comment 'SSH'
不使用 RustDesk Web 客户端时,最小端口集合如下:
ufw allow 21115/tcp comment 'RustDesk NAT test'
ufw allow 21116/tcp comment 'RustDesk connection'
ufw allow 21116/udp comment 'RustDesk ID heartbeat'
ufw allow 21117/tcp comment 'RustDesk relay'
其中 21115/TCP 用于 NAT 类型测试,21116/TCP 用于 TCP 打洞与连接服务,21116/UDP 用于 ID 注册和心跳,21117/TCP 用于中继。21118/TCP 与 21119/TCP 面向 Web 客户端;不使用该功能时保持关闭。
确认 SSH 规则无误后再启用并检查 UFW:
ufw enable
ufw status numbered
VPS 服务商的云防火墙或安全组也要放行相同的公网入站端口,否则只修改 UFW 仍无法建立连接。
检查实际监听状态:
ss -lntup | grep -E '21115|21116|21117'
正常情况下应能看到 21115/TCP、21116/TCP、21116/UDP 和 21117/TCP 对应的监听项。
获取公钥并配置客户端
Techahold 脚本将服务文件放在 /opt/rustdesk。查看服务端公钥:
cat /opt/rustdesk/id_ed25519.pub
在 Windows RustDesk 客户端进入“设置 → 网络 → ID/中继服务器”,填写:
ID 服务器:VPS 公网 IP 或域名
中继服务器:留空
API 服务器:留空
Key:id_ed25519.pub 的完整内容
使用默认端口并且 hbbs、hbbr 位于同一台服务器时,客户端通常可以根据 ID 服务器推导中继地址,因此中继服务器可以留空。Key 是服务端生成的公钥,不是私钥。
日志、重启与备份
查看最近日志或持续跟踪日志:
journalctl -u rustdesksignal -n 100 --no-pager
journalctl -u rustdeskrelay -n 100 --no-pager
journalctl -u rustdesksignal -f
journalctl -u rustdeskrelay -f
重启两个服务:
systemctl restart rustdesksignal rustdeskrelay
备份整个工作目录:
tar -czf "/root/rustdesk-backup-$(date +%F).tar.gz" /opt/rustdesk
至少要保留以下密钥文件:
/opt/rustdesk/id_ed25519
/opt/rustdesk/id_ed25519.pub
私钥 id_ed25519 不应公开,也不要粘贴到文章、工单或聊天记录中。
部署 FRP 服务端
安装二进制并规划目录
本文使用以下路径:
/usr/local/bin/frps
/etc/frp/frps.toml
/etc/frp/server_token
/etc/systemd/system/frps.service
从 FRP 官方 Release 下载与架构匹配的压缩包并解压后,安装 frps。目录中的版本号应替换为实际下载版本:
cd /tmp/frp_<FRP_VERSION>_linux_amd64
install -m 0755 frps /usr/local/bin/frps
frps --version
frps.toml 是服务端配置,frpc.toml 是客户端配置。两者的校验命令不要混用:
frps verify -c /etc/frp/frps.toml
frpc verify -c /etc/frp/frpc.toml
[[proxies]] 只能出现在 frpc.toml。如果把客户端配置交给 frps 校验,可能看到 json: unknown field "proxies"。
创建低权限用户与目录
为 FRPS 创建不可登录的系统用户:
useradd \
--system \
--home-dir /var/lib/frp \
--create-home \
--shell /usr/sbin/nologin \
frp
如果 frp 用户已经存在,可以跳过创建。随后准备配置目录和运行目录:
install -d -m 0750 -o root -g frp /etc/frp
install -d -m 0750 -o frp -g frp /var/lib/frp
使用文件保存认证 Token
生成随机 Token,并只允许 root 写入、frp 组读取:
openssl rand -hex 32 > /etc/frp/server_token
chown root:frp /etc/frp/server_token
chmod 640 /etc/frp/server_token
需要将同一个 Token 配置到 FRPC,但不要把真实值写进公开文档。FRP 的 auth.tokenSource 文件读取方式从 v0.64.0 开始提供,因此实际版本必须满足这一条件。
编写 frps.toml
编辑服务端配置:
nano /etc/frp/frps.toml
配置内容如下:
bindAddr = "0.0.0.0"
bindPort = 7000
auth.method = "token"
auth.tokenSource.type = "file"
auth.tokenSource.file.path = "/etc/frp/server_token"
transport.tls.force = true
transport.maxPoolCount = 5
allowPorts = [
{ start = 30000, end = 39999 }
]
log.to = "console"
log.level = "info"
log.disablePrintColor = true
webServer.addr = "127.0.0.1"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "替换为独立强密码"
allowPorts 限制 FRPC 可以申请的远程端口范围。Dashboard 只绑定环回地址,因此无法直接从公网访问。密码仍需设置为独立强密码,不能照抄占位文本。
设置权限并校验配置:
chown root:frp /etc/frp/frps.toml
chmod 640 /etc/frp/frps.toml
frps verify -c /etc/frp/frps.toml
只有校验通过后再创建和启动 systemd 服务。
创建 frps.service
编辑服务文件:
nano /etc/systemd/system/frps.service
写入:
[Unit]
Description=FRP Server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=frp
Group=frp
WorkingDirectory=/var/lib/frp
ExecStart=/usr/local/bin/frps -c /etc/frp/frps.toml
Restart=on-failure
RestartSec=5s
LimitNOFILE=1048576
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict
ReadWritePaths=/var/lib/frp
[Install]
WantedBy=multi-user.target
重新加载 systemd,并立即启动、启用开机自启:
systemctl daemon-reload
systemctl enable --now frps
验证服务、日志和监听端口
分层检查服务状态:
systemctl is-enabled frps
systemctl is-active frps
systemctl status frps --no-pager -l
is-enabled 返回 enabled 表示已设置开机启动;is-active 返回 active 表示当前进程正在运行。若状态异常,查看日志:
journalctl -u frps -n 100 --no-pager
journalctl -u frps -f
检查控制端口与 Dashboard:
ss -lntp | grep -E '7000|7500'
期望的绑定关系是:
0.0.0.0:7000
127.0.0.1:7500
前者允许 FRPC 从公网连接,后者只允许 VPS 本机访问。
配置 FRPS 防火墙
开放 FRP 控制端口:
ufw allow 7000/tcp comment 'FRP control'
云安全组也要开放 7000/TCP。不要为 Dashboard 开放 7500/TCP;只监听 127.0.0.1 时,公网防火墙规则本身也没有必要。
业务端口按需放行。例如 FRPC 将 SSH 映射到 30022/TCP:
ufw allow 30022/tcp comment 'FRP SSH'
该端口必须同时位于 allowPorts 指定的范围内。如果使用“FRP 32401 → VPS 本机 Nginx → HTTPS 域名”的链路代理 Plex,公网通常只开放 80/TCP 与 443/TCP,不直接开放 32401/TCP;但具体反向代理监听方式需要与 Nginx 配置一致。
通过 SSH 隧道访问 Dashboard
在本机 PowerShell 建立端口转发:
ssh -p SSH_PORT -L 7500:127.0.0.1:7500 ADMIN_USER@VPS_PUBLIC_IP
保持 SSH 会话开启,然后在本机浏览器访问:
http://127.0.0.1:7500
这里的 SSH_PORT、ADMIN_USER 与 VPS_PUBLIC_IP 都要替换为实际值。Dashboard 流量经 SSH 隧道进入服务器,不需要把 7500/TCP 暴露到公网。
FRPC 的 Plex 映射示例
内网设备上的 frpc.toml 可以按下面的结构配置:
serverAddr = "VPS_PUBLIC_IP"
serverPort = 7000
auth.method = "token"
auth.token = "填写与服务器一致的 Token"
transport.tls.enable = true
[[proxies]]
name = "plex"
type = "tcp"
localIP = "127.0.0.1"
localPort = 32400
remotePort = 32401
校验并前台运行:
frpc verify -c /etc/frp/frpc.toml
frpc -c /etc/frp/frpc.toml
示例为了说明对应关系而直接写了 auth.token。生产环境应限制 frpc.toml 的读取权限;如果客户端版本支持,也可以改为文件 Token。
端口汇总
| 端口 | 协议 | 用途 | 公网开放 |
|---|---|---|---|
| 自定义 SSH 端口 | TCP | SSH 管理 | 是 |
| 80 | TCP | HTTP、证书签发或反向代理 | 按需 |
| 443 | TCP | HTTPS、WordPress 或反向代理 | 按需 |
| 7000 | TCP | FRPC 连接 FRPS | 是 |
| 7500 | TCP | FRPS Dashboard | 否 |
| 21115 | TCP | RustDesk NAT 类型测试 | 是 |
| 21116 | TCP | RustDesk TCP 打洞与连接 | 是 |
| 21116 | UDP | RustDesk ID 注册与心跳 | 是 |
| 21117 | TCP | RustDesk 中继 | 是 |
| 21118 | TCP | RustDesk Web 客户端 | 未使用则否 |
| 21119 | TCP | RustDesk Web 中继 | 未使用则否 |
| FRP 业务端口 | TCP/UDP | 内网服务映射 | 按需 |
端口需要同时考虑进程监听、UFW 和云安全组。三处任意一处缺失,外部连接都可能失败。
一次性检查清单
RustDesk:
systemctl is-enabled rustdesksignal rustdeskrelay
systemctl is-active rustdesksignal rustdeskrelay
systemctl status rustdesksignal rustdeskrelay --no-pager -l
ss -lntup | grep -E '21115|21116|21117'
FRPS:
frps verify -c /etc/frp/frps.toml
systemctl is-enabled frps
systemctl is-active frps
systemctl status frps --no-pager -l
ss -lntp | grep -E '7000|7500'
journalctl -u frps -n 50 --no-pager
防火墙:
ufw status verbose
检查完成后,FRPS 至少应满足:服务为 enabled 和 active,7000 监听 0.0.0.0,7500 只监听 127.0.0.1。RustDesk 两个服务也应同时处于启用和运行状态。