使用 FRP + Guacamole 搭建个人远程桌面访问方案全过程记录
项目背景
由于家庭网络通常没有固定公网 IP,且部分办公环境无法安装传统远程控制软件,需要搭建一套:
不依赖家庭公网 IP、不需要路由器端口转发、支持纯浏览器访问、可远程控制 Windows 桌面的方案。
最终方案:用 FRP 打通「公网 VPS → 家庭 Windows」的隧道,再用部署在 VPS 上的 Apache Guacamole 提供浏览器端远程桌面(RDP)访问。
整体架构
外部客户端(任意浏览器)
↓
公网
↓
阿里云 VPS
├── frps(FRP 服务端,Docker)
└── Guacamole + guacd + postgres(Docker)
↓ FRP 隧道
家庭 Windows 主机
└── frpc(FRP 客户端,开机自启)
↓
目标服务 RDP(127.0.0.1:3389)
数据流:浏览器 → Guacamole(8080) → guacd → VPS:13389 → frps → frpc → 127.0.0.1:3389
环境信息
| 项目 | 说明 |
|---|---|
| VPS | 阿里云,Ubuntu 24.04,有公网 IPv4 |
| FRP 版本 | VPS 端 frps 用 Docker 镜像 snowdreamtech/frps:0.70.1-debian;家庭端 frpc 用 frp_0.71.0 |
| Guacamole | guacamole/guacamole:latest(8080)+ guacamole/guacd:latest(4822)+ postgres:16 |
| 家庭 Windows | Windows 11 企业版 LTSC 24H2,显卡 NVIDIA RTX 4060 Ti |
| 端口规划 | frps 控制端口 7000;RDP 映射端口 13389;Guacamole 8080 |
一、VPS 端部署 frps
1.1 确认 frps 以 Docker 方式运行
|
|
应看到 frps 容器,端口映射包含 7000->7000 和 13389->13389。
1.2 frps 配置
frps 跑在 Docker 里,宿主机配置文件一般在 /opt/frp/frps.toml(挂载进容器 /etc/frp/frps.toml):
|
|
注意点:
auth.token必须与 frpc 端完全一致,否则 frpc 登录会报token in login doesn't match。
1.3 查看运行中的真实配置
若不确定 frps 配置文件在哪,用:
|
|
1.4 阿里云安全组
需要在阿里云控制台安全组放行:7000(frpc 连接用)、8080(Guacamole 网页用)。
注意点:13389 不需要在安全组放行。Guacamole 在 VPS 内部通过
172.18.0.1:13389访问 frps,全程不经过公网,所以外部访问 13389 不通是正常现象,不影响使用。
二、Windows 端部署 frpc
2.1 准备文件
目录 D:\frp,放 frpc.exe 和 frpc.toml。
2.2 frpc 配置(D:\frp\frpc.toml)
|
|
注意点:
loginFailExit = false非常重要。frp 0.71 默认loginFailExit = true,一旦网络短暂不可达(如开机时网卡还没就绪),frpc 会直接退出且不重试,导致隧道永久断开。设为false后会自动重连。- 日志用
log.to = "D:/frp/frpc.log"(把路径直接写进log.to)。不要写log.path,frp 没有这个字段,会报unknown field "path"。
2.3 验证 frpc 连接
|
|
看到以下日志即成功:
login to server success
proxy added: [home-rdp]
start proxy success
三、frpc 开机自启(Windows 计划任务)
frpc 需要在系统启动时(无需用户登录)自动运行,用计划任务以 SYSTEM 身份运行。
注意点:创建「系统启动时」+「SYSTEM 身份」的计划任务需要管理员权限。在非管理员 PowerShell 里直接
schtasks /create会报「拒绝访问」。
3.1 用提权方式创建计划任务
|
|
若当前 shell 非管理员,用以下方式提权(会弹 UAC,点「是」):
|
|
3.2 验证计划任务
|
|
确认:任务要运行 D:\frp\frpc.exe -c D:\frp\frpc.toml、触发器为「系统启动时」、运行身份为 SYSTEM。
注意点:非管理员查询 SYSTEM 任务时
schtasks /query可能报「拒绝访问」,需用提权方式查看。
四、Guacamole 部署(VPS,Docker)
4.1 容器组成
| 容器 | 镜像 | 端口 |
|---|---|---|
| guacamole | guacamole/guacamole:latest | 8080 |
| guacd | guacamole/guacd:latest | 4822(内部) |
| guacamole-postgres | postgres:16 | 5432(内部) |
4.2 网络结构(关键)
需要搞清楚各容器所在的 Docker 网络,因为 Guacamole 连接里要填的目标地址由它决定:
|
|
本案例结果:
guacd:网络guacamole_guacnet,网关172.18.0.1frps:网络bridge,IP172.17.0.2
注意点:guacd 和 frps 不在同一个 Docker 网络。guacd 无法用
frps容器名或172.17.0.2直连 frps。正确做法是让 guacd 访问宿主机网关172.18.0.1(frps 的 13389 已通过 docker-proxy 发布到宿主机0.0.0.0:13389)。
4.3 Guacamole 管理员登录
后台地址:http://VPS公网IP:8080/guacamole/#/
五、Guacamole 连接配置(核心)
在「连接 → HOME-PC」里,最终可用参数如下:
| 字段 | 值 |
|---|---|
| 协议 | RDP |
| 主机名 (hostname) | 172.18.0.1 |
| 端口 (port) | 13389 |
| 用户名 (username) | DESKTOP-T8BSD18\archai(或 archai + 域 DESKTOP-T8BSD18) |
| 密码 (password) | 你的 Windows 登录密码 |
| 安全模式 (security) | rdp |
| 忽略服务器证书 (ignore-cert) | 勾选(true) |
| 色彩深度 (color-depth) | 32 |
| 分辨率调整 (resize-method) | reconnect |
| DPI | 96 |
| 启用字体平滑 (enable-font-smoothing) | 勾选(true) |
注意点:
- 「主机名」不要填
guacd。guacd是 guacd 服务的容器名(它在 guacamole 容器环境变量GUACD_HOSTNAME里配置,与连接目标无关)。连接里的主机名必须填 RDP 目标地址172.18.0.1。- 剪贴板默认就是双向开启的,无需额外参数(
disable-copy/disable-paste不填即为开启)。- 若填
security = nla,需把用户名/域分开填(username = archai+domain = DESKTOP-T8BSD18),DESKTOP-T8BSD18\archai这种合并格式在 NLA 下可能认证失败。
六、排障全过程记录(重要)
按实际遇到问题的顺序整理。
6.1 frpc 登录失败:token 不匹配
- 现象:frpc 日志
login to the server failed: token in login doesn't match。 - 原因:frpc 与 frps 的
auth.token不一致。 - 处理:在 VPS 上
cat /opt/frp/frps.toml找到真实 token,把 frpc.toml 改成一致。
6.2 frpc 突然退出不再重连
- 现象:frpc 日志出现
connect to server error: ... unreachable network后直接stopped。 - 原因:frp 0.71 默认
loginFailExit = true,网络抖动即退出不重试。 - 处理:frpc.toml 加
loginFailExit = false。
6.3 frpc 日志字段报错 unknown field "path"
- 原因:frp 的日志字段是
log.to,没有log.path。 - 处理:写
log.to = "D:/frp/frpc.log"。
6.4 Guacamole 连不上:主机名填错
- 现象:连接目标填成
guacd。 - 原因:把 guacd 服务名当成了 RDP 目标。
- 处理:改成
172.18.0.1(guacd 所在网络的宿主机网关)。
6.5 网页手动保存连接导致参数丢失
- 现象:手动在网页勾选「Trust host certificate on first use」(cert-tofu),并取消了「忽略服务器证书」,导致连接反复断开。
- 原因:网页保存会重写整套参数,关键项(ignore-cert 等)容易弄丢或改错。
- 处理:
- 用「忽略服务器证书」(
ignore-cert = true),不要用 cert-tofu。 - 建议以后通过 REST API 改连接参数,别在网页里手动保存(见 7.1)。
- 用「忽略服务器证书」(
6.6 图形崩溃:远程桌面服务器因为发生错误而关闭了本连接
- 现象:连接建立后黑屏,随即断开;Windows 事件日志会话断开原因码
2147500036(0x800703E4,图形 I/O 中断)。 - 原因:NVIDIA RTX 4060 Ti 驱动 + Windows 11 24H2 的 RDP 兼容性 bug,显卡驱动处理 RDP 图形 I/O 时崩溃。此问题会反复发作,重启只能临时缓解。
- 尝试过但未根治的办法:
disable-gfx(禁用 RDP 图形管线)、bEnumerateHWBeforeSW=0(强制软件渲染)。 - 根治办法:更新 NVIDIA 驱动。本案例从
591.86(32.0.15.9186)升级到610.88后解决。- 更新路径:NVIDIA App / 官网下载,安装时选「自定义 → 执行清洁安装」。
- 设备管理器「更新驱动 → 自动搜索」往往提示已是最新(Windows Update 驱动库滞后),需去 NVIDIA 官网下。
6.7 安全模式不匹配:Server refused connection (wrong security type?)
- 现象:guacd 日志报
wrong security type。 - 原因:Windows 端
UserAuthentication = 1(强制 NLA),而 Guacamole 用了security = rdp(不走 NLA)。 - 处理(二选一):
- 方案 A:Guacamole 改
security = nla,并把用户名/域拆开填(archai+DESKTOP-T8BSD18)。 - 方案 B(本案例最终采用):把 Windows 端 NLA 关掉,Guacamole 用
security = rdp。1 2 3# 需管理员权限,改完重启 TermService Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name "UserAuthentication" -Value 0 Restart-Service TermService -Force
- 方案 A:Guacamole 改
6.8 前端崩溃:RawAudioRecorder ... reading 'bind'
- 现象:控制台报
TypeError: Cannot read properties of undefined (reading 'bind') at new Guacamole.RawAudioRecorder,连接被拖垮。 - 原因:Guacamole 走
http://(明文,非安全上下文),浏览器禁用了getUserMedia(麦克风 API)。Guacamole 前端在连接建立后会无条件初始化音频录制器,在受限环境崩溃。 - 处理(临时):Chrome 开启 flag
chrome://flags/#unsafely-treat-insecure-origin-as-secure,把http://VPS:8080加入安全来源,重启浏览器。 - 彻底方案:给 Guacamole 加 HTTPS(自签名证书 + nginx 反向代理)。
6.9 剪贴板失效
- 现象:双向复制粘贴不可用。
- 原因:同样因为
http://非安全上下文,浏览器禁用了navigator.clipboard(剪贴板 API)。 - 处理:与 6.8 相同,开启 Chrome flag,或改用 HTTPS。临时替代:连接后按
Ctrl+Alt+Shift呼出菜单,在「剪贴板」栏手动粘贴/复制。
6.10 NLA 认证失败:Authentication failure (invalid credentials?)
- 现象:改成
security = nla后,guacd 报认证失败。 - 原因:用户名用
DESKTOP-T8BSD18\archai合并格式,NLA(CredSSP) 没正确拆分。 - 处理:拆开填
username = archai+domain = DESKTOP-T8BSD18;或改回security = rdp(本案例最终方案)。
七、最终可用配置与维护
7.1 用 REST API 修改连接参数(推荐,避免网页保存重写参数)
|
|
注意点:Guacamole 的
/connections/{id}/parameters子资源只支持 GET(Allow: GET,OPTIONS),改参数要用PUT /connections/{id},把parameters放进连接对象一起提交。
7.2 常用排查命令
家庭 Windows 端:
|
|
VPS 端:
|
|
八、踩坑总结(速查)
- frpc 必加
loginFailExit = false,否则网络抖动即永久断开。 - frpc/frps token 必须一致。
- frp 日志字段是
log.to,没有log.path。 - Guacamole 连接的主机名填
172.18.0.1,不是guacd。 - 不要用网页手动保存连接,会重写整套参数;用 REST API 或至少核对清楚每个勾选项。
- 证书用
ignore-cert,别用 cert-tofu(trust on first use)。 - NVIDIA + Win11 24H2 的 RDP 崩溃,靠更新显卡驱动根治,重启只是临时。
security=rdp要求 Windows 关闭 NLA;security=nla要求用户名/域分开填。- Guacamole 用 HTTP 访问会导致音频崩溃、剪贴板失效(安全上下文限制),临时用 Chrome flag 解决,彻底用 HTTPS。
- 外部访问 13389 不通是正常的,Guacamole 在 VPS 内部走
172.18.0.1,安全组只需放行 7000 和 8080。