☰
rtty-master.zip:浏览器远程登录内网设备的Web终端方案
2026/10/20 9:19:49 网站建设 项目流程

简介:rtty-master.zip 是一套面向系统管理员、DevOps 与网管人员的开源远程终端工具源码,核心价值在于把传统 SSH 终端搬到 Web 浏览器中,实现随时随地通过 URL 访问和管理服务器、路由器及物联网设备。资源共 41 个文件,以 C 源码(src 目录)、Markdown 文档、头文件为主,另含 CMake 构建配置、shell 脚本、yml 工作流文件及 gif 演示图;压缩包仅 1.58MB,结构紧凑。下载后可直接参考 README 与文档完成编译安装,源码中自带的 command/file 等模块支持命令历史、复制粘贴、文件传输等实用功能,也便于二次开发集成。目前已有 133 人学习,适合需要轻量级 Web 远程管理方案、或希望在现有设备管理体系中嵌入终端能力的运维开发者。

1. rtty-master.zip 是什么:一个用浏览器当终端的远程接入方案

拿到rtty-master.zip这个压缩包时,多数人以为它只是一个平平无奇的 GitHub 源码快照,解压完就扔到硬盘角落了。但真正在嵌入式开发和设备运维场景里待过的人会立刻意识到:这是一个"用一条curl命令、在一个浏览器标签页里远程登录任意 Linux 设备"的钥匙。rtty 的核心思路是反直觉的——明明 SSH 已经是事实标准,为什么还要再做一套 Web 终端?答案是场景:当设备位于内网、没有公网 IP,或者你不想在每台机器上装客户端、只想临时开个终端看一眼状态时,SSH 的链路打通成本远比 a WebSocket + 浏览器高。rtty-master.zip这个包,就是把服务端(rttyd)、客户端(rtty)和 Web 页面一次性给你打包好的源码。适合谁?适合被"设备分散在客户现场、偶尔要改个配置"这件事反复折磨的工程师;也适合想给自有设备管理平台内嵌一个远程终端能力的团队。这篇文章要讲的不是怎么解压运行就完事,而是把这个包拆开,讲清楚它的模块边界、参数含义和那些不跑一遍根本发现不了的坑。

2. 拆开 rtty-master.zip:文件结构与三个核心模块

2.1 源码包里到底有什么:先看目录再动手

解压rtty-master.zip之后,你得到的不只是一个 C 语言工程,而是一个前后端完整的小型系统。我一般会先不看 README,而是直接树状列出目录,快速判断这个项目的维护水平和扩展点在哪。

unzip rtty-master.zip cd rtty-master find . -maxdepth 2 -type f | sort | head -50

常见做法是你会看到CMakeLists.txt在最顶层,src/目录下躺着rtty.c、rttyd.c这类服务端与客户端的主程序文件,然后有一个web/或html/目录放着网页终端所需的静态文件。这里的关键判断是:这个项目把"网页怎么画"和"终端会话怎么管"拆成了两个部分,网页部分只是静态资源,真正的会话管理全部在rttyd这个守护进程里完成。

再往下看,libuwsc/、libev/这样的第三方依赖目录通常也被直接塞进了源码树,不需要你再去逐个安装依赖。这一点对离线编译非常友好,也是很多二线工具做不到的。这个包解压后,整个工程的依赖关系大致分三层:最底层是事件循环库(libev)和 WebSocket 客户端库(libuwsc),中间是 rtty 自己实现的终端会话管理和协议封装,最上层才是我们直接操作的rtty(客户端)和rttyd(服务端)两个可执行程序的入口。理解这个分层,后面调参数时就不会把客户端的参数误用到服务端上。

2.2 客户端与服务端的分工:设备主动拨号,而非服务端拉取

安装过 OpenSSH 的人会天然地认为"服务端监听端口,客户端发起连接",但 rtty 恰好是反过来的。被管理的设备(比如一台 ARM 开发板)上运行的是rtty这个客户端程序,它主动向rttyd服务端发起一条出方向的 WebSocket 连接。这条连接是设备主动拨号的,所以即使设备处于 NAT 后面的内网,只要它能访问外网的一台rttyd,服务端就能"够到"它。

这个模型的工程价值在于:你不需要在路由器上给每台设备做端口映射,也不需要在设备端开任何入方向端口,安全暴露面小了很多。服务端要做的只是维护一张"当前有哪些设备在线"的表,浏览器请求访问某台设备时,rttyd把浏览器发来的 WebSocket 帧转发给对应的rtty客户端进程,rtty进程则把帧里的数据写到它自己绑定到的伪终端(PTY)上。理解这个"设备呼叫中心"模型很重要,因为后面配置 token、配置设备 ID 时,所有逻辑都是围绕"服务端如何区分不同设备"展开的。

2.3 协议栈的分层:为什么 WebSocket 是恰当选择而不是性能妥协

有人会问,既然终端要传输键盘按键和屏幕输出,直接用裸 TCP 不是更高效?rtty 选择 WebSocket 的根本原因是浏览器这个终端。浏览器里没有办法直接建立裸 TCP 连接,但几乎所有的现代浏览器都对 WebSocket 有着完整支持。WebSocket 的帧开销确实比裸 TCP 大,但在终端这种低频、小数据包场景里,这点开销完全可以忽略。

/* 核心数据流:浏览器 WebSocket -> rttyd 转发 -> rtty 客户端 -> PTY -> shell */ /* rtty.c 中典型的读事件回调,注意它只负责把 WebSocket 数据丢给 PTY */ static void on_ws_read(struct uwsc_client *client, char *data, size_t len) { /* data 是浏览器传来的用户输入,写入伪终端主设备 */ write(pty_fd, data, len); }

这段代码虽然只是原型级示例,但揭示了数据流的本质。rttyd本身几乎不做协议解析,它更像一个 7×24 小时在线的交换机:把浏览器的数据帧原样扔给设备端,再把设备端 PTY 的输出原样扔回浏览器。所谓"协议"主要体现在 URL 路径和设备 ID 的编码规则上,数据面负载就是裸的终端字节流。所以你在排查问题时,如果发现终端输出乱码,问题往往不在 rtty 的协议层,而在 PTY 的终端类型设置或者 locale 环境上。

3. 把 rtty 跑起来:从编译到建立第一条连接

3.1 最小编译命令:不要上来就 make,先确认依赖

rtty-master.zip的解压目录里虽然有第三方依赖源码,但 CMake 在配置阶段还是会检查系统里有没有 openssl 的头文件和库。我踩过的第一个坑就是在一台精简版 Ubuntu 上编译,openssl 没装全,配置阶段直接失败。编译的最小命令序列如下:

sudo apt-get install -y build-essential cmake libssl-dev # Debian/Ubuntu 系 tar xzf rtty-master.tar.gz # 或者 unzip rtty-master.zip cd rtty-master mkdir build && cd build cmake .. make -j$(nproc)

如果你是从 zip 包解压而不是从 git clone 的,注意检查web/目录里的静态文件是否完整。有些 GitHub 的 zip 快照会忽略 submodule,如果web/目录是空的,后续 Web 界面会白屏,但编译不会报错。这是一个非常隐蔽的坑,后面会在避坑章节详细说。编译完成之后,build/目录下会出现rtty和rttyd两个二进制文件,前者是设备端,后者是服务端。

这里有一个值得说的选型判断:为什么不用 Docker 直接跑现成镜像?如果你手头有 x86 的服务器,用 Docker 确实快;但绝大多数场景下rtty客户端要跑在现场的 ARM 设备上,这种设备上装 Docker 本身就是一种负担。源码编译的方式能让你用交叉编译工具链直接把rtty编成 ARM 版本,体积小、依赖少,这才是这个项目在实际落地中的主流方式。

3.2 启动 rttyd 并接入第一个设备:两个进程、三条命令

先把服务端跑起来。假设你的服务端公网 IP 是203.0.113.10(示意地址),监听端口用默认的5912:

# 服务端:监听所有网卡,允许设备接入 ./rttyd -h 0.0.0.0 -p 5912

然后在设备端启动客户端:

# 设备端:主动连到服务端,给自己起一个唯一 ID ./rtty -h 203.0.113.10 -p 5912 -I my-device-001 -s your_token_here

此时用浏览器访问http://203.0.113.10:5912,页面上会出现一个名为my-device-001的在线设备图标,点它,就能打开一个终端。这里-I参数指定的是设备 ID,-s参数指定的是共享 token,这两者缺一不可。如果你已经在服务器上验证过,但页面上看不到设备,八成是防火墙没放行 TCP 5912 端口。

注意rtty客户端连接rttyd时,URL 默认是ws://,如果你给服务端配了 TLS 证书,那么客户端要加-S参数启用 SSL。这一条看似简单,但实际部署中"为什么我连不上"的排查里,有一半都是这个原因。

3.3 设备 ID、token、端口这三件事怎么设

设备 ID 是整个系统里最容易被低估的参数。我见过有人直接把设备 ID 命名为test、device1,导致管理几十台设备时完全分不清谁是谁。生产环境里建议用"项目代号-产品类型-序列号"的编码格式,比如optics-rpi4-000a3b,这样在 Web 页面上看列表时不需要点进去就能定位设备。而且设备 ID 一旦在rttyd侧重复,后接入的那台会把先接入的那台踢下线,行为非常粗暴。

Token 的作用是接入认证。rttyd启动时如果不指定-s参数,那么任何知道服务端地址的人都能通过 Web 页面连接到所有在线设备,这是绝对不能接受的。token 的语义有点像一个共享密钥:设备端和服务端必须都带同一个 token 才能握手成功。但要注意,token 是明文放在命令行参数里的,用ps就能看到,所以生产环境里要么用 systemd 的EnvironmentFile方式注入,要么写进配置文件。端口的选择上,默认 5912 并非特殊约定,如果你不想让扫描器一眼看出来这是个 rtty 服务,换成高位端口如 28431 会稍微好一点,但只增加了一点点安全性,不能替代 token 的必要性。

4. rtty 落地避坑:连接断开、端口被占、权限与网络环境的 5 条踩坑记录

4.1 设备显示在线但点开黑屏,终端没有任何输出

现象:Web 页面能看到设备卡片、状态是绿色的,但点击打开终端后,窗口里一片黑,敲键盘也没反应。

原因:这几乎可以断定是rtty客户端进程没能成功分配 PTY。PTY 的创建涉及/dev/ptmx和/dev/pts/文件系统,如果客户端进程是在 systemd 服务里以DynamicUser=true或者某个降权用户运行的,它可能没有权限访问这些设备节点。还有一种情况是容器里跑客户端,容器没有挂载/dev/pts的对应配置。它不是连接问题,而是本地终端分配问题,所以设备一直显示在线。

解决:在设备端手动停掉 rtty 进程,直接在终端前台跑一次/path/to/rtty -h ... -I ...,看它有没有打印 PTY 相关的报错。如果是权限问题,把客户端服务改成以 root 或tty组身份运行。在容器里则需要添加--privileged或者至少保证/dev/ptmx可用。

4.2 客户端一启动就连上,但几秒后掉线,循环重连

现象:客户端进程启动了,能看到 WebSocket 连接建立的日志,但过 3~5 秒就断开,然后它再次重连,反复循环,Web 页面上设备状态像心跳一样闪动。

原因:服务端rttyd在握手建立后要校验设备 ID 的唯一性。如果某台设备带着重复的 ID 接入,新连接会把旧连接顶掉,而旧连接被顶掉后如果还在重连,它又成为"新连接",又把原来的连接顶掉,于是两台设备之间无限互相踢下线,表现就是"连上又断"。这在不规范地使用同一个镜像批量部署设备时特别容易发生,因为所有设备上的-I参数值一样。

解决:逐个登录设备,检查命令行或配置文件里的-I参数,改成唯一值。如果设备太多,可以在部署脚本里用-I $(hostname)或读取/etc/machine-id的前几位来作为设备 ID 后缀。用/etc/machine-id有一个好处,它是一次写入、只读的,设备 ID 不会因为重启而漂移。

4.3 服务端能连,浏览器也能打开页面,但页面白屏或只有框架没有设备列表

现象:rttyd日志里显示浏览器顺利完成了 WebSocket 握手,但页面没有渲染出设备列表,只有空壳。

原因:这是本章开头埋的那个伏笔——web/目录下的静态文件缺失。特别是从源码 zip 包或某些镜像站下载的包,submodule 指向的 web 前端资源并没有被真正打包进来,导致rttyd启动了、WebSocket 服务也正常,但它没有可返回的 HTML/JS 资源。这类问题最坑的地方在于它不报错,服务端日志看不出任何异常。

解决:先去你解压的目录里确认web/是不是空的或缺失关键文件。如果是,从原始 git 仓库单独拉取 web 资源,或者干脆不去理会。更实际的办法是换一个发布渠道重新下载源码包。常见的做法是使用打包完整的 release 归档而不是 git 分支的 zip 快照。这里要养成一个习惯:任何源码包解压后先看 web 资源目录的完整性,再决定要不要继续编译。

4.4 公网能访问 rttyd,但设备端死活连不上,ping 也通

现象:服务器防火墙已放行 5912 端口,从服务器本机能连上 5912,设备也能 ping 通服务器,但设备端启动 rtty 客户端就是一直超时。

原因:这里的"超时"要看具体方向。如果设备在 NAT 后面,出方向连接本身没问题,但有个很容易被忽略的因素是运营商或企业防火墙做了基于协议的特征识别,对长时间空闲的 WebSocket 连接会静默中断。rtty 的客户端有 keepalive 机制,但如果设备端的系统时间和服务端偏差太大,TLS 证书校验(如果开了-S)会立刻失败。另一个常见原因是设备端没有正确设置默认路由,导致访问公网 IP 的流量走错网关。

解决:先在设备端用nc -vz <server_ip> 5912测试 TCP 连通性,这一步能区分是路由问题还是防火墙问题。如果 TCP 能通但 rtty 连不上,加-d参数启动调试模式看日志。如果系统时间差太多,开-S时记得用-v查看 TLS 报错,或者在 NTP 不可用的离线环境里改用不带 TLS 的内部网络部署。我一般会在项目初期就决定:设备流量走公网则必须上 TLS,走内网则可以不加密,省去证书维护成本。

4.5 部署脚本里同时启动多个设备实例,只有最后一个能连上

现象:在一台多网卡的服务器上想跑多个 rttyd 实例分别管理不同项目,结果启动第二个实例时第一个实例的 Web 页面立即挂掉,设备全部掉线。

原因:默认情况下rttyd只监听一个端口,如果你第二个实例没有改端口号,它要么因为地址占用启动失败,要么在SO_REUSEPORT的支持下和第一个实例共享同一个端口,导致内核把新连接随机分配到两个进程之一,于是设备时而连到 A、时而连到 B,行为完全随机。

解决:多个实例部署时要显式区分三样东西:监听端口(-p)、WebSocket 路径前缀(-P,不同实例用不同路径)、以及 token。然后在浏览器访问时用不同的 URL 路径进入对应的管理面。例如实例 A 用/a/路径,实例 B 用/b/路径,这样两台实例就可以在同一端口下共存,且设备列表互不可见。

5. 进阶:把 rtty 从玩具变成生产工具的三个改造方向

当你把上面这些坑都趟平,rtty 已经能稳定工作了。但要做成一个真正能交给运维同事使用的工具,还需要补三块短板:认证接入、可观测性和会话审计。rtty 原始功能里,token 只是一个极简的接入凭据,它没有用户体系、没有操作审计,这在公司内网还能接受,一旦设备暴露在合作方网络里,任何拿到 token 的人都能接管所有设备终端。

第一个改造方向是做一层反向代理的认证网关。常见的做法是在 rttyd 前面加一层 Nginx,用 Basic Auth 或者更正规的 OIDC 代理(例如某些开源的身份认证代理组件)做用户级认证,认证通过后再把请求反向代理到 rttyd 的 5912 端口。这样 token 变成服务端和客户端之间的底层层密钥,浏览器用户甚至不需要知道 token 是什么,只需要输入自己的账号密码。

location /rtty/ { auth_basic "RTTY Access"; auth_basic_user_file /etc/nginx/.rtty_htpasswd; proxy_pass http://127.0.0.1:5912/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }

这段配置的关键在于proxy_set_header Upgrade和Connection "upgrade"两行,它们保证了 WebSocket 协议能穿透 Nginx 反代。少了这两行,页面能打开,但设备列表的实时状态和终端数据全都不通。另外一个参数值得注意:proxy_read_timeout要调大,默认的 60 秒会在用户长时间不操作终端时切断连接,我一般习惯设成 3600 秒。

第二个改造方向是给 rtty 加会话录播。这不需要改动 rtty 源码,只需要在设备端包一层 script 录制工具:设备端把 rtty 客户端包在一个 script 命令里,把整个 PTY 会话写到本地日志文件。这样即使 Web 终端被关闭,回放记录仍然保留,审计和排障的时候能完整复盘。要注意磁盘占用,我一般会在日志轮转配置里限制单文件大小和保留天数。

第三个值得实践的方向是批量设备管理。rtty 本身一次只能打开一个设备的终端,没有"发给所有设备执行命令"的批量能力。我的做法是写一个循环脚本,遍历设备 ID 清单,用 WebSocket 客户端逐个连到 rttyd,下发指令并抓取返回。这个方案效率不高,但完全复用现有链路,不需要改服务端。如果未来设备规模超过几十台,再考虑是否值得二次开发。

最后说一个我自己的血泪习惯:任何这种 Web 终端工具,第一次部署时我都会用一台有固定 IP 的 Linux 虚拟机做全天连续运行测试,连续开 24 小时以上,期间人为制造网络抖动、重启服务端、重启客户端,看它能否自动恢复。rtty 的客户端重连机制是否可靠,很多隐性问题要在这个测试里才会暴露。如果你打算用它管理真正重要的生产设备,务必在接入前做一次这样的耐力测试。希望这篇笔记帮你在 rtty 这条路上少踩几个坑,把工具真正用成顺手的样子。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询