自托管RustDesk用了一段时间之后,我最大的感受是:远程桌面工具本身好不好用是一回事,能不能在出问题时把当时谁连了谁、做了什么、会话持续了多久这些事说清楚,是另一回事。尤其当RustDesk承担的是办公终端远程维护、业务系统排障这类工作时,“连接成功就算完事”的思路根本撑不住审计需求。这篇文章我会把RustDesk会话记录到底能拿到什么、操作记录和审计日志应该怎么补、以及我在实际搭建过程中踩过的坑,一次性讲透。
适合看这篇内容的人,主要是两类:一类是把RustDesk自托管在机房或云主机上、需要给内部维护团队提供远程支持通道的运维人员;另一类是公司有合规审查要求、需要证明某一时间段内哪些人通过RustDesk访问过哪些设备的IT管理岗。
1. RustDesk会话审计先要搞清的事:你到底能看到什么
很多刚上手自托管RustDesk的人,第一反应是“既然是自己的服务器,那所有连接一定都留痕了”。这个理解不算错,但不完整。RustDesk的数据链路由三个角色组成:客户端(被控端)、客户端(控制端)、服务器。服务器里又分信令服务(通常叫hbbs)和中继服务(通常叫hbbr)。这三者都会产生日志,但日志的粒度完全不一样。
先说结论:RustDesk默认能稳定记录的是“连接事件”,也就是谁在什么时间请求了哪个ID、是否建立连接、连接持续多久、最后怎么断开的。但“操作记录”这个层面,也就是控制端在屏幕上移动了鼠标、点了哪个按钮、改了哪些配置,这些内容默认不会进日志。要实现完整的操作审计,必须在RustDesk之外再做一层采集和录制。
1.1 日志在哪些地方产生
我以最常见的自托管部署方式为例,服务器跑在Linux上,hbbs和hbbr以systemd服务或Docker容器运行。两种方式的日志出口不同:
- systemd方式:日志写到journald,用
journalctl -u rustdesk-hbbs可查看,也可以配置成输出到/var/log/rustdesk/目录。 - Docker方式:日志走容器的stdout,默认被Docker的json-file驱动落地到宿主机,路径一般在
/var/lib/docker/containers/<容器ID>/<容器ID>-json.log。
也可以显式指定RustDesk Server的日志路径,两种方式都支持将日志重定向到固定文件。客户端这边,Windows上日志在%AppData%\RustDesk\log目录下,Linux上通常在~/.config/rustdesk/log或~/.local/share/rustdesk/log,具体看发行版。日志文件按天分割,文件名会带上日期,比如2025-06-10.log。
1.2 服务器端日志里有什么
hbbs负责ID注册、心跳、连接协商,因此它的日志里最常见的记录是客户端上线、下线事件。一条典型的hbbs日志会包含时间戳、客户端ID、客户端来源IP、UUID、操作系统类型、连接是否成功等字段。这些字段非常重要,因为它们是构建审计证据链的基础。
hbbr的日志则记录中继连接,也就是当两个客户端无法点对点直连时,数据流经中继服务器的转发情况。可以看到哪个中继会话建立、哪条连接被关闭或超时。如果排查远程卡顿或会话中断问题,hbbr日志比hbbs更有说服力。
这里要提醒一句:如果你一开始部署RustDesk Server时没有注意日志保留策略,默认情况下日志只按启动参数里的配置滚动,一旦超出保留数量,最老的日志会被覆盖。这在审计场景里是致命的,所以第2章会专门讲集中采集和归档。
1.3 客户端日志里有什么
客户端日志是操作审计里容易被忽略的部分。控制端发起连接后,本机日志会记录目标ID、连接是否成功、失败原因(比如密码错误、超时、被对方拒绝)。被控端的日志则会记录“有来自哪个ID的连接请求”、是否接受请求、会话开始与结束时间。
很多企业在做审计时只看服务器日志,这是不够的。服务器日志只能证明“ID A与ID B之间发生过连接”,而客户端日志能提供更细的本地时间线,比如用户手工输入了远程密码、用户主动断开了连接。两者交叉比对,才能还原一次完整会话的来龙去脉。
1.4 必须直说的短板:画面、键盘和文件传输默认不记录
RustDesk的核心功能是远程桌面,但远程桌面的“内容”默认不会留下痕迹。控制端看到什么画面、输入了什么键盘指令、通过内置的文件传输功能拷了哪些文件,这些都不在默认日志范围内。
看到这里,如果你的预期是“部署完RustDesk就能自动生成一份审计报告”,那可能要调整一下方案。完整的企业级审计,必须靠访问控制策略、外部屏幕录制、日志集中管理等手段去补。本章先把RustDesk能提供的原始数据讲清楚,接下来的章节就是具体怎么把这些数据变成可用的审计证据。
2. 搭一套合格的会话审计日志体系
审计日志体系的核心目标只有一个:任何一次远程会话,都能追溯到唯一的发起者、接受者、时间范围和结果。更进一步,如果配合屏幕录制,还能追溯到操作内容。
2.1 先定义好最小审计字段
在动手配日志采集之前,先列一张表,明确审计需要哪些字段。不要等到归档之后再后悔漏字段。
| 字段 | 含义 | 默认能否拿到 |
|---|---|---|
| 会话开始时间 | 连接建立的时间点 | 能,服务器与客户端都有 |
| 会话结束时间 | 断开或超时的时间点 | 能,断开事件会写入日志 |
| 发起方ID | 谁主动发起连接 | 能,客户端日志与服务器日志都有 |
| 接受方ID | 谁被连接 | 能,同上 |
| 发起方来源IP | 控制端所处地址 | 服务器日志能拿到 |
| 中继服务器IP | 是否走了中继通道 | 服务器日志能拿到 |
| 会话总时长 | 开始到结束的差值 | 需要二次计算 |
| 连接失败原因 | 密码错误、超时、拒绝等 | 能,日志中有明确原因 |
| 操作内容 | 屏幕动作、键盘事件 | 默认拿不到,需外部方案 |
| 审批记录 | 谁批准了这次连接 | 看是否启用了访问控制流程 |
这张表的用意很明确:先按“能拿到”的数据建立基础审计,再按“拿不到”的数据规划外部增强方案。不要一上来就追求面面俱到,那样实施成本会失控。
2.2 服务器日志集中采集:rsyslog加文件监听
服务器日志在本地滚动,是审计体系里最薄弱的一环。最好的做法是实时转发到独立日志服务器。我推荐用rsyslog的imfile模块监听日志文件,把新增内容转发到中心日志服务器。
在hbbs宿主机上增加配置:
module(load="imfile") input(type="imfile" File="/var/log/rustdesk/hbbs.log" Tag="rustdesk-hbbs" Severity="info") input(type="imfile" File="/var/log/rustdesk/hbbr.log" Tag="rustdesk-hbbr" Severity="info") action(type="omfwd" Target="192.168.6.10" Port="514" Protocol="tcp")中心日志服务器侧,直接接收即可。这样RustDesk Server本地的日志文件被清理了一部分,中心仍然保留完整记录。
注意:用TCP协议转发比UDP靠谱。UDP转发在高并发时会丢日志,审计场景下丢一条关键连接记录,可能等于整个证据链断了。
2.3 客户端日志回收:脚本化打包归档
服务器日志解决了大半问题,但客户端日志也不能放任不管。尤其被控端是企业内网里的员工电脑,这些机器的日志分散在各个用户目录下。我建议在受管终端上定期执行一个回收脚本。
以Linux被控端为例,把日志打包上传到内部审计存储:
#!/usr/bin/env bash HOST=$(hostname) DAY=$(date +%Y%m%d) mkdir -p /audit/rustdesk/${HOST}/${DAY} tar czf /tmp/rustdesk_log_${HOST}_${DAY}.tar.gz -C ~/.config/rustdesk/log . scp /tmp/rustdesk_log_${HOST}_${DAY}.tar.gz audit-user@192.168.6.20:/audit/rustdesk/${HOST}/${DAY}/Windows终端可以通过计划任务执行PowerShell脚本完成同样的事。这里不展开脚本细节,核心思路是:客户端日志必须从每台电脑上“收”回来,否则审计的时候你只能逐台登入查看,根本不现实。
2.4 日志保留周期与分级
不同日志的价值周期不一样。纯连接事件类的日志,保留一年已经足够应对绝大多数审计要求;屏幕录制这类体积大的文件,建议只保留90到180天。不要把两者混在一个生命周期里管理,否则存储成本会变得离谱。
同时给日志分级:一级为原始日志,只能追加、不能修改;二级为解析后的结构化数据,方便检索;三级为告警与统计报表,供日常运维参考。分级之后,权限控制也更清晰:能改报表的人,不一定能看原始日志。
3. 操作记录的强化方案:从“有连接”到“有内容”
如果你所在的场景明确要求“知道远程维护过程中做了什么”,那么只看连接日志是不够的。必须引入操作记录强化方案。这一部分没有开箱即用的RustDesk插件,至少我目前没有找到,所以要用工程手段组合实现。
3.1 用访问控制策略制造可追踪的事件闭环
RustDesk的密码和访问控制本身也是审计的一部分。启用强密码、设置连接确认、限制无人值守访问,这些配置直接决定了哪些连接能被成功建立。一个有意思的误区是,很多人觉得“密码只是控制访问的”,实际上在审计场景里,密码校验失败的记录同样价值巨大。它能证明某人或某个设备试图访问但没有被授权,这在异常行为排查时非常关键。
建议开启以下设置:必须输入密码才能连接、控制端需要被控端手动接受、轮流访问时强制重新验证。每一次验证都会产生相应的日志,最终形成“尝试—验证—接受—建立—断开”的完整闭环。
3.2 屏幕录制:合规要求高时的唯一硬方案
如果想记录远程会话中实际看到的画面,目前只有屏幕录制一条路。在Linux被控端,我用的方案是ffmpeg加X11捕获。部署时按被控端会话启动录制:
ffmpeg -f x11grab -video_size 1920x1080 -framerate 2 -i :0.0 \ -c:v libx264 -crf 28 -preset veryfast \ session_${REMOTE_ID}_$(date +%Y%m%d%H%M%S).mp4参数说明:-framerate 2表示每秒录2帧,日常远程维护的屏幕变化频率不高,2帧足够还原操作过程,同时大幅压缩文件体积;-crf 28在清晰度和体积之间取一个平衡。如果录制帧率设成25或30,一天的录制文件能轻松吃掉几十GB,完全不现实。
Windows被控端则用系统自带的屏幕录制能力或第三方录制工具,这里就不列具体软件名了,选型时优先考虑能按时间戳生成文件、支持加密存储、能设定保留时限的即可。
注意:屏幕录像涉及最终用户可见内容,必须提前向被控端使用者明确告知。这个不是技术问题,是合规底线问题。没做好告知就录制,后续一旦引发争议,技术方案再好也救不回来。
3.3 键盘输入记录要谨慎再谨慎
有一种强化方案是记录键盘输入,用来还原操作命令。我必须先明确表态:这个功能在大多数场景下不适合启用,因为它能采集到的不只是运维命令,还可能包含用户正在编辑的文档内容、输入的账号密码等敏感信息。每多记录一种数据,风险敞口就大一分。
如果确实需要捕获被控端上执行的命令行操作,优先考虑在目标应用侧做日志,比如将终端会话记录到独立日志文件,而不是做全局键盘钩子。这样既能满足操作审计需求,又不会过度采集。
3.4 操作记录的权限管控与告知机制
操作记录采集回来之后,读取权限必须严格限制。在审计存储端,建议分三档权限:审计管理员可查看原始记录和屏幕录像;普通管理员只能查看连接事件统计;普通用户无权进入审计存储目录。权限控制可以用系统ACL实现,也可以用审计存储系统自带的角色管理实现。
另一个经常被忽略的点是,操作记录本身要有“防删改”能力。系统管理员如果既管RustDesk服务器,又管审计存储,那他完全可以先删日志、再删录像。所以审计存储必须独立于日常运维体系,可以单独一台低配机器,甚至放到不同的管理域中。
4. 把审计日志接进私有化运维链路
日志收集到这一步,你需要一套能查询、能统计、能告警的检索体系。很多团队会直接搬一套ELK,但对于审计日志这种相对固定格式的数据,我有更轻的方案。
4.1 轻量落库:Promtail加Loki
单机版日志检索,我用Loki加Promtail,比ELK少了一半组件,内存占用只有几百MB。中心日志服务器上安装Promtail,配置里直接抓取RustDesk日志文件:
scrape_configs: - job_name: rustdesk static_configs: - targets: [localhost] labels: job: rustdesk __path__: /var/log/rustdesk/*.log再加一个客户端日志入口,把之前脚本回收的客户端日志也指向同一套Loki。这样无论服务器还是客户端日志,都在同一套查询接口里。
4.2 实用查询场景一:按连接者ID还原时间线
假设审计人员收到一个任务:查某ID在6月10日上午都连过哪些设备。在Loki里直接查询:
{job="rustdesk"} |= "1234567890"把日志按时间排序,就能还原出该ID从上线注册、发起连接、连接成功到断开的全过程。如果端口日志和客户端日志都采集到了,还可以再叠加job="rustdesk-client"来交叉验证。
4.3 实用查询场景二:异常连接告警
审计日志不只是事后查询,更应该提供实时告警。比如同一来源IP在短时间内尝试连接多个不同ID,大概率是自动化扫描或暴力尝试。在Loki里用一个统计查询:
sum(count_over_time({job="rustdesk"} |= "auth_failed" [5m])) by (source_ip) > 20这个条件一旦触发,就说明某个IP五分钟内失败认证超过20次。配合告警通知,能在攻击初期就收到提醒,而不是等用户反馈“我电脑好像被连过”才发现。
心得:告警阈值一定要结合自己的业务规模设定。内部维护团队正常操作时,五分钟内失败认证超过5次都算异常;但如果你的使用场景里有大量新员工批量初始化终端,失败次数天然就高,阈值设太低会告警轰炸。
4.4 日志备份与防篡改
日志进了Loki只能解决查询问题,不能解决“这条日志是不是被人改过”的问题。审计场景要求原始日志具备强完整性。我的做法是在日志落盘的文件上启用追加写属性:
chattr +a /var/log/rustdesk/hbbs.log追加写属性意味着即使root用户也只能追加、不能覆盖已有内容,对防止日志被事后篡改非常有效。同时每天生成一次校验和,存储到独立审计机器:
sha256sum /var/log/rustdesk/hbbs.log >> /secure/audit/checksum_$(date +%Y%m%d).txt这样即便某天日志文件真的被动过,也能通过校验和比对发现。审计机与运维机权限隔离是底线,这一点必须坚持。
5. 常见问题与排查技巧实录
这部分是硬碰硬的排障经验,我复盘自己踩过的坑,整理成几个高频问题。如果有读者正在实施同样的方案,大概率会遇到其中的几个。
5.1 明明有远程会话,日志里却是空的
最常见的诱因是日志权限不对。Linux下用systemd方式运行hbbs时,如果程序启动早于用户创建日志目录,程序可能会在启动时静默失败,导致日志不进文件。排查方法很简单,先重启服务,再立刻查看对应文件是否更新:
systemctl restart rustdesk-hbbs tail -f /var/log/rustdesk/hbbs.log如果重启后仍然无输出,检查进程实际运行身份:
ps aux | grep hbbs ls -ld /var/log/rustdesk另一个低级原因是启动参数里日志等级被设置成了error或warn,info级别的连接记录根本不会写出来。RustDesk Server的日志参数要设为debug或info级别,否则审计字段严重缺失。
5.2 时间戳差8个小时,会话时间线对不上
这是时区问题。服务器日志默认采用UTC时间,客户端日志则可能使用本地时间。当你把两条日志放在一起比对时,一个显示10点,一个显示18点,如果不加注意,会误判为“两个不同时间的会话”。
统一做法:所有审计采集端都使用同一时区,我习惯全部设为东八区。在systemd服务单元中加入环境变量:
Environment=TZ=Asia/ShanghaiDocker部署则要在启动时挂载时区文件:
-v /etc/localtime:/etc/localtime:ro -v /etc/timezone:/etc/timezone:ro更重要的是,在集中存储阶段统一转换成ISO 8601格式并携带时区偏移量,彻底避免“这个日志到底是UTC还是本地”的模糊地带。
5.3 日志把磁盘塞爆了
高并发环境下,hbbs日志增长比想象中快。我遇到过一次,单日hbbs.log涨到800MB,磁盘直接报警。解决方案分两层。第一层设在RustDesk Server侧,限制日志保留数量和等级;第二层设在系统侧,用logrotate做轮转压缩:
/var/log/rustdesk/*.log { daily rotate 60 compress delaycompress missingok notifempty }这里压缩方案用的gzip,压缩后日志体积能降到原来的十分之一左右。日志轮转之后要记得通知rsyslog重新打开文件,在logrotate配置里加一行sharedscripts加postrotate脚本,否则rsyslog会一直向已轮转的旧文件写内容,导致日志不更新。
5.4 有人绕过审计通道怎么办
这是最让人头大的问题。客户端配置被私自改动、自定义服务器地址、甚至直接卸掉客户端,都会让被控端脱离审计范围。对抗思路不是靠日志系统去解决,而是在分发和终端管控层面做文章。
我能给的有效手段有这么几条:在受管客户端配置策略文件,锁定RustDesk的服务器地址和访问参数,普通用户无权修改;对安装目录和配置文件目录做ACL限制,禁止非管理员写入;把客户端日志打包脚本设成开机触发,一旦发现某台机器连续N个周期没有上传日志,自动生成告警。
最后一条是我个人的体会:任何日志和审计方案都不是绝对可靠的,它只能不断压缩“不可审计”的空间。真正重要的不是追求100%覆盖,而是每次会话都有独立的时间戳、可交叉验证的对端信息、可追溯的连接ID。把这三样东西守住了,RustDesk的会话审计体系就算立住了。至于屏幕录制这类增强功能,建议先从单台测试机跑起来,确认录制文件大小在可接受范围之后,再逐步铺开到整个终端池。