# 使用 Docker 搭建 WebSSH 服务:浏览器里直接玩转终端 > 还在为无法远程访问服务器发愁?你需要的是一个浏览器就能直接登录SSH的工具。本文手把手教你搭建 WebSSH。 ## 前言 WebSSH 是一种通过浏览器直接访问服务器终端的技术。无需安装 Xshell、Putty 等客户端软件,打开浏览器就能连接服务器。本文将基于开源项目,手把手教你搭建自己的 WebSSH 服务。 ## 一、HuggingFace Spaces 的困境 [HuggingFace Spaces](https://huggingface.co/docs/hub/spaces-overview) 是一个非常好用的平台,可以快速部署机器学习 Demo,支持 Gradio、Streamlit、Docker 等多种方式。 然而,在实际使用过程中,很多开发者遇到了以下令人头疼的问题: ### 1.1 只读文件系统问题 ``` Cannot use Hugging Face cache on a read-only filesystem Error: [Errno 13] Permission denied: '/.streamlit' ``` HuggingFace Spaces 对文件系统有严格限制,应用无法随意写入数据。这导致: - 无法安装额外的 Python 包 - 无法使用 HuggingFace 缓存目录 - 配置文件无法保存 ### 1.2 无法执行 Shell 命令 Spaces 环境中没有终端访问权限,开发者无法: - 手动安装缺失的系统依赖 - 调试运行状态 - 执行 git、conda 等命令 - 查看进程状态 ### 1.3 存储限制 每个 Space 只有 1GB 的临时存储空间,且重启后数据会丢失。无法进行大规模的数据处理或模型下载。 ### 1.4 包管理限制 `packages.txt` 经常失效,无法按预期安装依赖包,导致项目无法正常运行。 > 这时,WebSSH 就显得尤为重要——它可以让你在浏览器中直接访问终端,完全绕过这些限制! ## 二、解决方案:WebSSH WebSSH 通过浏览器为你提供一个完整的终端会话,让你能够: - 自由访问文件系统 - 执行任意 Shell 命令 - 安装系统依赖 - 调试运行状态 - 就像在本地终端一样操作服务器 ## 三、技术架构 WebSSH 项目包含三个核心部分: | 组件 | 技术选型 | 作用 | |------|----------|------| | 后端 | Tornado + WebSocket | 建立与浏览器的双向实时通信 | | 前端 | xterm.js | 在浏览器中模拟终端显示 | | 终端 | pty (伪终端) | 在服务器端创建 shell 会话 | 整体架构如下: ``` 浏览器 <--WebSocket--> Tornado后端 <--pty--> /bin/sh ``` ## 四、核心功能特性 ### 4.1 用户认证 ```python USERS = { "admin": "admin123", "user": "user123" } ``` - 支持 Basic 认证 - 连接时验证用户名密码 - 认证失败拒绝连接 ### 4.2 命令审计日志 ```python def log_command(username, command): log_entry = { "timestamp": datetime.now().isoformat(), "user": username, "command": command } logger.info(f"COMMAND: {json.dumps(log_entry)}") ``` - 记录所有用户执行的命令 - 保存时间、用户、操作信息 - 日志文件持久化存储 ### 4.3 HTTPS 支持 ```python ssl_options = { "certfile": "/app/cert.pem", "keyfile": "/app/key.pem", } ``` - 自动检测 SSL 证书 - 支持 HTTPS 加密传输 - 生产环境安全保障 ### 4.4 自动重连 ```javascript ws.onclose = function() { if (reconnectAttempts < maxReconnectAttempts) { setTimeout(() => { reconnectAttempts++; connect(); }, reconnectDelay); } }; ``` - 自动重连机制 - 最大重试次数限制 - 用户友好体验 ### 4.5 主题切换 ```javascript const themes = { dark: { background: '#000000', foreground: '#ffffff' }, light: { background: '#ffffff', foreground: '#000000' }, hacker: { background: '#0d0208', foreground: '#00ff41' }, dracula: { background: '#282a36', foreground: '#f8f8f2' } }; ``` - 4 种预设主题 - 实时切换无需刷新 - 自定义终端外观 ### 4.6 心跳保活 ```python elif "ping" in msg: self.write_message(json.dumps({"pong": True})) ``` - 定期 ping/pong 检测 - 超时自动断开 - 连接状态监控 ### 4.7 危险命令拦截 ```python BLOCKED_COMMANDS = ["rm -rf", "mkfs", "dd if=", ":(){:|:&};:", "chown", "chmod 777"] ``` - 阻止危险操作 - 保护系统安全 - 可扩展白名单 ## 五、核心代码解析 ### 5.1 伪终端创建 (handler.py) ```python def start_shell(self): pid, fd = pty.fork() if pid == 0: os.execv("/bin/sh", ["-sh"]) else: self.ptyslave = fd self.shell_pid = pid ``` `pty.fork()` 是整个系统的核心: - 它创建一对伪终端(master/slave) - 子进程被连接到 slave 端,执行 `/bin/sh` - 父进程通过 master 端读写数据 ### 5.2 数据双向传递 **后端 → 前端:** ```python async def read_from_shells(): while True: for handler in list(ShellHandler.connections): if handler.ptyslave: ready, _, _ = select.select([handler.ptyslave], [], [], 0.05) if handler.ptyslave in ready: data = os.read(handler.ptyslave, 4096) if data: handler.write_message(data.decode("utf-8", errors="replace")) ``` **前端 → 后端:** ```javascript term.onData(function(data) { ws.send(data); }); ``` ### 5.3 终端大小自适应 当浏览器窗口大小变化时,前端发送新尺寸,后端通过 `ioctl` 更新终端: ```python def on_message(self, data): msg = json.loads(data) if "resize" in msg: cols, rows = msg["resize"] fcntl.ioctl( self.ptyslave, termios.TIOCSWINSZ, struct.pack("HHHH", rows, cols, 0, 0), ) ``` ## 六、Docker 部署 ### 构建镜像 ```bash docker build -t webssh:0.0.1 . ``` ### 运行容器 ```bash docker run -d -p 7860:7860 --name webssh webssh:0.0.1 ``` 参数说明: - `-d`:后台运行 - `-p 7860:7860`:端口映射(主机端口:容器端口) - `--name webssh`:容器名称 ### 启用 HTTPS ```bash # 生成自签名证书(测试用) openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes # 运行容器并挂载证书 docker run -d -p 7860:7860 -v $(pwd)/cert.pem:/app/cert.pem -v $(pwd)/key.pem:/app/key.pem --name webssh webssh:0.0.1 ``` ### 常用操作 ```bash # 查看运行状态 docker ps # 查看日志 docker logs webssh # 停止容器 docker stop webssh # 重新启动 docker start webssh # 进入容器调试 docker exec -it webssh /bin/sh ``` ## 七、访问使用 容器启动后,打开浏览器访问: ``` http://你的服务器IP:7860 ``` 登录界面: - 输入用户名和密码 - 默认账户:`admin / admin123`,`user / user123` - 支持主题切换 ## 八、效果演示 ``` === Connected to terminal === $ ls -la total 32 drwxr-xr-x 1 root root 4096 Apr 4 12:00 . drwxr-xr-x 1 root root 4096 . ... $ whoami root $ pip install numpy Successfully installed numpy-1.26.0 ``` 审计日志: ```json {"timestamp": "2026-04-04T12:00:00", "user": "admin", "command": "ls -la"} {"timestamp": "2026-04-04T12:00:01", "user": "admin", "command": "pip install numpy"} ``` ## 九、未来待完善功能 当前项目已完成基础功能,但仍有许多可以改进的地方: ### 9.1 用户认证与安全 - [x] 添加用户登录认证机制 ✅ - [x] 支持 HTTPS/SSL 加密传输 ✅ - [x] 实现命令审计和日志记录 ✅ - [ ] 限制可执行的命令白名单 - [ ] 添加 IP 白名单/黑名单 - [ ] JWT/Session 认证 ### 9.2 多用户支持 - [ ] 支持多个用户同时连接 - [ ] 用户隔离(每个用户独立的 session) - [ ] 会话管理(查看、强制断开) - [ ] 在线用户列表 ### 9.3 功能增强 - [ ] 支持 SSH 远程连接(连接到其他服务器) - [ ] 文件上传/下载功能 - [ ] 历史命令记录 - [ ] 标签页多终端支持 ### 9.4 体验优化 - [x] 主题自定义(配色、字体大小)✅ - [ ] 快捷键支持 - [ ] 声音提示 - [ ] 移动端适配 ### 9.5 稳定性提升 - [x] 连接超时自动重连 ✅ - [x] 异常断开时的资源清理 ✅ - [ ] 内存和进程监控 ## 十、总结 WebSSH 技术让你可以: 1. **跨平台访问** - 只需浏览器,无需安装客户端 2. **绕过限制** - 解决 HuggingFace Spaces 等平台的文件系统和终端限制 3. **无需配置SSH** - 解决了防火墙、密钥等繁琐配置 4. **安全可控** - 建立在 WebSocket 之上,支持 HTTPS 5. **易于部署** - 一行命令启动 Docker 容器 6. **审计合规** - 完整记录操作日志 项目代码已开源,部署过程非常简单。有兴趣的同学可以继续扩展功能,比如添加用户认证、命令审计等。 --- *参考资料:* - [HuggingFace Spaces 文档](https://huggingface.co/docs/hub/spaces-overview) - [Tornado WebSocket 文档](https://www.tornadoweb.org/en/stable/websocket.html) - [xterm.js 官方文档](https://xtermjs.org/) - [Python pty 模块](https://docs.python.org/3/library/pty.html) - [HuggingFace Spaces 存储限制](https://www.huggingface.co/docs/hub/main/en/spaces-storage)