WeTTY 3.0.0 介绍与选型指南

WeTTY 3.0.0 浏览器 SSH 终端组件详解:架构原理、xterm.js/Socket.IO 技术栈、与 ttyd/sshx/Guacamole/ShellHub 等同类组件横向对比及选型建议。

WeTTYSSH终端工具2026/10/30

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 + ExpressHTTP 服务、静态资源、会话管理
会话后端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 端口)」为例,一次完整会话的流转:

  1. 浏览器打开 http://<host>:8152/,WeTTY 返回 xterm.js 页面(实测响应标题 <title>WeTTY Lab</title>,由 TITLE 环境变量控制);
  2. 页面通过 Socket.IO 握手连到服务端(实测:不带合法 Origin 的握手会被拒 {"code":4,"message":"Origin not allowed"},带允许 Origin 则返回 sid);
  3. 服务端解析目标用户名:优先 HTTP 头 remote-user,其次 URL 路径 /ssh/<user>,再次 SSHUSER 配置项,都没有则在终端里交互式提示 Enter your username:(实测存在该交互);
  4. 服务端为该会话 spawn ssh -t -p <port> -o UserKnownHostsFile=... -- <user>@<host>,并挂上 node-pty 伪终端;
  5. 用户输入密码(实测回显 admin@sshd's password:),SSH 认证成功后进入远端 Shell(实测 Welcome to OpenSSH Server + 提示符);
  6. 此后双方全双工:键盘敲击以 input 事件上行,远端输出以 data 事件下行渲染进 xterm.js;
  7. 断开页面或会话空闲超时,服务端回收 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 属于第一类。对比先看横向全景:

组件路线认证体系后端目标部署重量许可证
WeTTYSSH 转发网关复用目标 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
ShellHubSSH 资产管理网关独立用户体系+密钥管理纳管的设备/容器四服务编排+PostgreSQLApache-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 的场景

  1. 内网跳板:给运维/开发团队一个浏览器可达的终端入口,机器不出公网、22 端口不对办公网开放;
  2. 受控远程支援:给外部支持人员开通限定账号的 SSH 会话,走完即走,权限由服务器侧 SSH 管控;
  3. 容器/实验环境接入:Web 控制台类产品的配套终端(本次实验即以 sshd 容器为跳板验证);
  4. 低配设备批量终端化:WeTTY 单实例即可服务多并发会话,32MiB 级内存占用对 NAS、树莓派友好。

4.2 不适合用 WeTTY 的场景

  1. 需要图形远程桌面(RDP/VNC)——选 Guacamole 或 MeshCentral;
  2. 需要终端审计录制、会话回放——WeTTY 无审计能力,选 ShellHub 或 Teleport;
  3. 需要多人共享同一终端协作——选 sshx 或 tmux + 只读镜像方案;
  4. 只想在本机快速起个 Web Shell 临时用一下——ttyd 一条命令更省事。

4.3 选型结论

WeTTY 的甜点位非常清晰:「自托管、轻量、以标准 SSH 认证为安全边界」的浏览器终端入口。它不引入第二套账号体系,部署与心智成本都极低(一个镜像 + 一组环境变量),代价是功能单一(无审计、无资产管理、无图形协议)。如果你的需求是给团队开一个内网终端跳板,WeTTY 是这个细分场景下最轻的正解;要往上叠管理能力,再考虑 ShellHub/Guacamole 这类重装方案。

五、本系列文档导航