WeTTY 3.0.0 介绍与选型指南
WeTTY 3.0.0 浏览器 SSH 终端组件详解:架构原理、xterm.js/Socket.IO 技术栈、与 ttyd/sshx/Guacamole/ShellHub 等同类组件横向对比及选型建议。
WeTTY 3.0.0 介绍与选型指南
目标:说清 WeTTY(Web + TTY)这个「浏览器里的 SSH 终端」是什么、怎么工作、和 ttyd/sshx/Guacamole/ShellHub 等同类组件差异在哪,并给出明确的选型建议。本文所有结论均基于 2026-10-30 对 WeTTY v3.0.0(Docker 镜像 wettyoss/wetty)的真实部署与终端登录实测,部署过程见 《WeTTY 3.0.0 Docker Compose 部署实战》。
一、WeTTY 是什么
WeTTY = Web + TTY,一句话定位:把 SSH 终端搬进浏览器。它本身不是 Shell,也不是 SSH 服务器,而是一个架在「浏览器」与「SSH 服务端」之间的转换层——浏览器里看到的是一个完整的终端模拟器,背后的命令实际跑在你指定的 SSH 服务器上(远程主机、同宿主的 sshd 容器,甚至本机 login)。
项目由 Cian Butler(butlerx)开发并维护,GitHub 仓库为 butlerx/wetty,MIT 协议。Docker Hub 官方镜像为 wettyoss/wetty(累计拉取超 180 万次)。需要特别提醒:不少旧教程写的镜像名 buttermilk/wetty 已经失效(Docker Hub 返回 object not found,本次实测确认),认准 wettyoss 组织。
本次实测版本为 v3.0.0(npm 包版本,Node v22.23.4 运行时),镜像构建于 2026-10-25。实验中真实登录后的终端回显:
Enter your username: admin
Warning: Permanently added '[sshd]:2222' (ED25519) to the list of known hosts.
admin@sshd's password:
Welcome to OpenSSH Server
453d12874af2:~$ whoami; hostname; uname -sr; cat /etc/alpine-release
admin
453d12874af2
Linux 7.0.0-38-generic
3.24.3
从浏览器 Socket.IO 连接、输入用户名密码,到远端 Alpine 容器里执行命令拿到真实回显,整条链路无需安装任何客户端插件——这是 WeTTY 的核心价值。
1.1 技术栈拆解
| 层 | 技术 | 作用 |
|---|---|---|
| 前端终端 | xterm.js | 纯 JS 实现的完整终端模拟器(支持 256 色、滚动回看、复制粘贴) |
| 传输层 | Socket.IO(WebSocket) | 浏览器与 WeTTY 服务端之间的双向低延迟通道 |
| 服务端 | Node.js + Express | HTTP 服务、静态资源、会话管理 |
| 会话后端 | node-pty | 在服务端分配伪终端(PTY),供 SSH 子进程挂载 |
| 连接目标 | OpenSSH 客户端(ssh 命令) | WeTTY 为每个会话 spawn 一个 ssh -t 子进程连到目标 sshd |
💡 技术拓展:PTY(伪终端,pseudo-terminal) 是 Unix 下让「程序以为自己在跟真终端对话」的内核机制,由主从两端(master/slave)组成。SSH 服务端、
script、screen、tmux 都依赖 PTY 才能提供行编辑、控制序列、信号传递等终端行为。浏览器本身没有 PTY,所以所有「Web 终端」方案的共同核心动作都是:在服务端创建 PTY,把 PTY 的输出编码后推给浏览器渲染。WeTTY 用 node-pty 库做这件事;如果目标 Shell 缺少 PTY,你会看到命令能执行但没有提示符、vim 全屏错乱等现象——这也是排查 Web 终端问题时的第一个检查点。
1.2 工作原理(一次会话的生命周期)
以本次实测「浏览器 → WeTTY(8152 端口)→ 容器 sshd(2222 端口)」为例,一次完整会话的流转:
- 浏览器打开
http://<host>:8152/,WeTTY 返回 xterm.js 页面(实测响应标题<title>WeTTY Lab</title>,由 TITLE 环境变量控制); - 页面通过 Socket.IO 握手连到服务端(实测:不带合法 Origin 的握手会被拒
{"code":4,"message":"Origin not allowed"},带允许 Origin 则返回 sid); - 服务端解析目标用户名:优先 HTTP 头
remote-user,其次 URL 路径/ssh/<user>,再次 SSHUSER 配置项,都没有则在终端里交互式提示Enter your username:(实测存在该交互); - 服务端为该会话 spawn
ssh -t -p <port> -o UserKnownHostsFile=... -- <user>@<host>,并挂上 node-pty 伪终端; - 用户输入密码(实测回显
admin@sshd's password:),SSH 认证成功后进入远端 Shell(实测Welcome to OpenSSH Server+ 提示符); - 此后双方全双工:键盘敲击以
input事件上行,远端输出以data事件下行渲染进 xterm.js; - 断开页面或会话空闲超时,服务端回收 PTY 与 ssh 子进程。
理解第 4 步很关键:WeTTY 只负责「转发」,认证仍由标准 OpenSSH 完成。因此服务器上的 authorized_keys、sshd_config、PAM、fail2ban 等一切 SSH 侧管控对 WeTTY 会话同样生效,不需要重复建设。
二、核心特性清单(v3.0.0 实测核对)
以下特性均在本次 v3.0.0 容器内以 wetty --help 输出与实际行为逐项核对:
- 单二进制单容器:一个 Node 进程 + 一个静态页面,无数据库、无状态,资源占用极小(实测容器常驻内存 32.59MiB);
- 连接目标可配可传:SSHHOST/SSHPORT/SSHUSER 环境变量设定默认目标;v3 支持 URL 参数传 host/port(需显式开启 allow-remote-hosts);
- 三种认证方式:
password(默认,可配 SSHPASS 自动输密)、publickey(SSHKEY 指定客户端私钥)、none(依赖服务器侧免密); - HTTPS/TLS 内建:SSLKEY/SSLCERT 直接挂证书,也官方支持 Nginx/Apache 反代(见 C1 篇反向代理一节);
- BASE 子路径部署:BASE=/wetty 可挂在反代子路径下,适合与既有站点共存;
- v3 新增强制 CORS:ALLOWEDORIGINS 必配(不配直接拒绝启动,实测崩溃循环),ALLOWMISSINGORIGIN 放行无 Origin 的客户端,ALLOWEDORIGINS 支持多值逗号分隔;
- v3 新增心跳可调:PINGINTERVAL/PINGTIMEOUT 环境变量,针对高延迟链路防「transport close」误断;
- v3 新增 iframe 策略:ALLOWIFRAME 控制是否允许被第三方页面内嵌(默认仅同源);
- v3 新增 remote-user 头接入:便于与反向代理身份认证层(如 Authelia、Pomerium)联动实现免输入用户名。
💡 技术拓展:CORS(跨源资源共享) 是浏览器对「页面 A 里的脚本请求资源 B」的安全策略,Socket.IO 这类 WebSocket 长连接同样受 Origin 校验约束。Web 终端能执行任意命令,属于高危入口,v3 把「允许哪些源连接」从可选变成强制配置,本质是把这道安全闸门前置到启动阶段。部署时 ALLOWEDORIGINS 应精确列出用户实际访问用的
协议://域名:端口,多了等于裸奔,少了则浏览器侧握手 403。本次实测中遗漏该配置直接导致容器重启循环,是 v3 相对 v2 最容易踩的坑。
三、同类组件对比
「浏览器终端」这个赛道按实现路线分四类,WeTTY 属于第一类。对比先看横向全景:
| 组件 | 路线 | 认证体系 | 后端目标 | 部署重量 | 许可证 |
|---|---|---|---|---|---|
| WeTTY | SSH 转发网关 | 复用目标 sshd(密码/密钥) | 任一 sshd | 单容器,无状态 | MIT |
| ttyd | 本机 PTY 直出 | Basic Auth(可挂反代) | 仅本机 Shell | 单二进制极轻 | MIT |
| sshx | 托管共享终端 | 链接即凭证 | sshx 自有会话 | 托管 SaaS | 闭源 |
| Apache Guacamole | 多协议网关(RDP/VNC/SSH) | 独立用户体系+数据库 | RDP/VNC/SSH/Telnet | 多容器(guacd+Tomcat+DB) | Apache-2.0 |
| ShellHub | SSH 资产管理网关 | 独立用户体系+密钥管理 | 纳管的设备/容器 | 四服务编排+PostgreSQL | Apache-2.0 |
| MeshCentral | 远程管理平台 | 独立账户体系 | 自有 Agent | 单容器+数据卷 | Apache-2.0 |
| code-server | 浏览器 IDE(内置终端) | password 环境变量/代理 | 本机文件系统 | 单容器 | MIT |
逐项说明差异与取舍:
- WeTTY vs ttyd:ttyd 把本机 Shell 直接 web 化,安装最简单,但目标只能是 ttyd 所在的那台机器,没有 SSH 层,也意味着给浏览器用户的权限就是 ttyd 进程的权限;WeTTY 每个会话都是标准 SSH 认证,可以指向不同主机、不同账号,安全边界清晰。只要你的诉求是「远程机器的终端」,WeTTY 比 ttyd 更合适。
- WeTTY vs sshx:sshx 主打「一条链接共享终端给多人」,适合临时协作与教学演示,但它是闭源托管服务,终端落在第三方;WeTTY 完全自托管,数据不出内网。
- WeTTY vs Apache Guacamole:Guacamole 是重型多协议网关(RDP 远程桌面、VNC、SSH 全覆盖),带数据库和完整用户体系,适合「给几十上百人开图形+终端混合入口」的组织场景;如果只需要字符终端,Guacamole 的部署与维护成本(guacd + Tomcat + 数据库三个常驻组件)明显过重。
- WeTTY vs ShellHub:ShellHub 定位是 SSH 资产网关(设备接入、公钥集中管理、审计、审批),WeTTY 只做「浏览器到 SSH 的转发」。两者可以互补:ShellHub 管资产与权限,WeTTY 提供浏览器入口。站内已有完整实测系列:《ShellHub 介绍与选型指南》、《ShellHub Docker Compose 部署实战》。
- WeTTY vs MeshCentral:MeshCentral 是远程运维全家桶(远程桌面、文件管理、Agent 常驻),终端只是其功能之一,适合设备运维管理场景;纯终端诉求下它同样偏重。参考站内 《MeshCentral 1.3.1 介绍与选型指南》。
- WeTTY vs code-server:code-server 是「浏览器里的 VS Code」,自带集成终端,适合开发场景;但它绑定本机工作区,不是通用 SSH 网关。开发自用可选 code-server(见 《code-server 4.143.1 介绍与选型指南》),运维给团队开终端入口选 WeTTY。
四、适用场景与选型建议
4.1 适合用 WeTTY 的场景
- 内网跳板:给运维/开发团队一个浏览器可达的终端入口,机器不出公网、22 端口不对办公网开放;
- 受控远程支援:给外部支持人员开通限定账号的 SSH 会话,走完即走,权限由服务器侧 SSH 管控;
- 容器/实验环境接入:Web 控制台类产品的配套终端(本次实验即以 sshd 容器为跳板验证);
- 低配设备批量终端化:WeTTY 单实例即可服务多并发会话,32MiB 级内存占用对 NAS、树莓派友好。
4.2 不适合用 WeTTY 的场景
- 需要图形远程桌面(RDP/VNC)——选 Guacamole 或 MeshCentral;
- 需要终端审计录制、会话回放——WeTTY 无审计能力,选 ShellHub 或 Teleport;
- 需要多人共享同一终端协作——选 sshx 或 tmux + 只读镜像方案;
- 只想在本机快速起个 Web Shell 临时用一下——ttyd 一条命令更省事。
4.3 选型结论
WeTTY 的甜点位非常清晰:「自托管、轻量、以标准 SSH 认证为安全边界」的浏览器终端入口。它不引入第二套账号体系,部署与心智成本都极低(一个镜像 + 一组环境变量),代价是功能单一(无审计、无资产管理、无图形协议)。如果你的需求是给团队开一个内网终端跳板,WeTTY 是这个细分场景下最轻的正解;要往上叠管理能力,再考虑 ShellHub/Guacamole 这类重装方案。
五、本系列文档导航
- 部署实操:《WeTTY 3.0.0 Docker Compose 部署实战》(含本次 8152 端口 + sshd 容器的完整从 0 到 1 过程);
- 参数字典:《WeTTY 3.0.0 配置参数详解》(全部环境变量/命令行参数逐项说明);
- 运维手册:《WeTTY 3.0.0 常用操作与排障详解》(日常操作 + 本次实测踩坑的完整排障记录)。