文档
快速开始 + 每部分每设备的功能说明(持续更新中)
SSH Everywhere 架构与技术栈
> 本文档说明 SSH Everywhere(SSH Everywhere Plus)的整体架构、用到的协议与技术栈,以及「为什么项目仍然叫 SSH Everywhere」。
---
一、项目定位
SSH Everywhere 是一套一站式服务器/设备远程运维面板,对标 1Panel / 宝塔。核心价值主张:无论设备在网络的哪个角落——有公网 IP、无公网 IP(NAT 后)、还是手机(Termux)——都能从这一个面板像 SSH 一样管理它。
面板本身部署在一台有公网 IP 的服务器上(本项目监听 0.0.0.0:5501),用户通过浏览器访问面板,再由面板通过不同协议「触达」目标设备。
---
二、整体架构(分层)
┌─────────────────────────────────────────────────────────────┐
│ 浏览器前端(单页应用,模拟桌面操作系统) │
│ templates/desktop.html + static/js/*.js(17 个模块) │
│ · 窗口管理器(WindowManager) · 任务栏 · 开始菜单 · 卡片仪表盘 │
│ · xterm.js 真终端 · Font Awesome 图标 · 原生 JS(无框架) │
└──────────────────────────┬──────────────────────────────────┘
│ HTTP REST + SocketIO(默认 namespace)
┌──────────────────────────┴──────────────────────────────────┐
│ 面板后端(Flask + Flask-SocketIO,Python) │
│ app.py(主应用/路由/SSH 连接池/健康检查) │
│ tunnel.py(反向隧道服务端,FRAME 协议) │
│ termux_sio.py(SocketIO /agent namespace 服务端) │
│ transfer.py(文件传输) crashmon*.py(崩溃防护) │
│ nginx_manager*.py(网站管理) backup*.py(备份) │
│ SQLite 数据库(data/ssheverywhere.db) │
└───┬───────────────┬──────────────────┬──────────────────────┘
│ SSH(paramiko) │ FRAME 反向隧道 │ SocketIO(长轮询)
│ 直连/经隧道 │ (0.0.0.0:4433) │ (走 HTTP)
▼ ▼ ▼
┌────────┐ ┌──────────────┐ ┌─────────────────┐
│ 有公网 │ │ 无公网 Linux │ │ Android 手机 │
│ 服务器 │ │ /NAS/树莓派等 │ │ (Termux) │
│ (sshd) │ │ (tunnel_agent)│ │ (termux_agent) │
└────────┘ └──────────────┘ └─────────────────┘
---
三、通信协议层(核心)
项目最初以 SSH 起家,如今内部实际运行着 4 种协议,各有分工:
1. SSH(paramiko)—— 主力通道
用途:所有「普通 Linux 服务器」的核心功能。
- 系统管理(概览、进程、计划任务、防火墙、Docker、网站、镜像源、崩溃防护)
- 终端(交互式 shell)
- 文件管理(SFTP 上传/下载/编辑/压缩)
- 健康检查(CPU/内存/磁盘/温度)
- 命令执行
连接方式:
- 有公网 IP:面板直连
host:port; - 无公网 IP:面板先通过反向隧道建一个本地代理端口,再 SSH 连
127.0.0.1:代理端口→ 设备 sshd。
> 换句话说,反向隧道的本质是「把 SSH 送到没有公网 IP 的设备上」,所以 SSH 仍然是最终落地协议。
2. FRAME 反向隧道协议 —— 穿透通道(自研)
用途:让「无公网 IP 的设备」能被面板触达。设备端主动「连出」到面板,建立一条反向 TCP 长连接,面板通过这条隧道下发命令、转发端口。
帧类型(tunnel.py,加密模式,magic = b'SSHE'):
| 帧 | 值 | 方向 | 说明 |
|---|---|---|---|
FRAME_HEARTBEAT | 0x01 | 双向 | 心跳(10s 间隔,120s 超时) |
FRAME_REGISTER | 0x02 | agent→服务端 | 注册(上报 token/系统信息) |
FRAME_FORWARD | 0x03 | 服务端→agent | 建立 SSH 转发通道 |
FRAME_CLOSE | 0x04 | 双向 | 关闭通道 |
FRAME_INFO | 0x05 | agent→服务端 | 健康信息上报 |
FRAME_FWD_OPEN | 0x06 | 服务端→agent | 端口穿透:请求打开目标端口连接 |
FRAME_FWD_DATA | 0x07 | 双向 | 端口穿透:数据转发 |
FRAME_FWD_CLOSE | 0x08 | 双向 | 端口穿透:关闭 |
FRAME_CMD | 0x09 | 服务端→agent | 远程命令执行 |
FRAME_CMD_RESP | 0x0A | agent→服务端 | 命令结果返回 |
传输:TCP 长连接 + 加密(tunnel_crypto.py,Ed25519 密钥协商)。隧道服务端监听 0.0.0.0:4433。
典型场景:
- 无公网 Linux 服务器的 SSH 穿透运维(隧道内再跑 SSH);
- 端口穿透:把设备上的服务端口(如
8090)映射到面板公网端口,供外网访问。
> 易混概念:端口转发 vs 端口穿透
>
> 两者都是「把设备端口暴露出去」,但适用场景和实现完全不同:
>
> | | 端口转发(port-forward) | 端口穿透(port-tunnel) |
> |---|---|---|
> | 适用设备 | 有公网 IP 的服务器 | 无公网 IP 的穿透设备 |
> | 实现方式 | iptables/nftables DNAT,在目标服务器本机做 | 走 FRAME 反向隧道(FRAME_FWD_OPEN/DATA/CLOSE 帧) |
> | 数据流 | 访问者 → 目标公网 → 目标端口 | 访问者 → 面板公网端口 → 反向隧道 → 设备端口 |
> | 依赖设备在线 | 不依赖(有公网 IP 随时可达) | 依赖(设备须保持 agent 在线) |
>
> 一句话:「转发」给有公网 IP 的服务器用(DNAT 直转);「穿透」给没公网 IP 的设备用(靠反向隧道搬运)。这也是项目里它们是两个独立功能面板的原因。
3. SocketIO(WebSocket 长轮询)—— Android 手机专用通道
用途:管理 Android 手机上的 Termux。手机移动网络 NAT 频繁切换、sshd 不稳,所以改用 SocketIO 稳定长轮询通道(方案照抄用户另一项目 phone2server,已在实机验证稳定)。
两个 namespace:
/agent(手机 agent ↔ 面板服务端):register/monitor_data/p2s_ping/exec_result/pty_data/disconnect;- 默认 namespace(浏览器 xterm ↔ 面板):
agent_term_start/agent_term_input/agent_term_resize/agent_term_stop。
跑在手机上的 termux_agent.py 通过 SocketIO 提供:
- 系统管理(概览/进程/计划任务)
- 终端(PTY 桥接)
- 文件管理(exec 执行
python3 -c出 JSON) - 健康监控(每 30s 上报:负载/内存/磁盘/电池/温度)
> 这是项目里唯一真正「不走 SSH」的通道——因为 Android 手机彻底去掉了 sshd。
4. HTTP REST —— 前端与后端之间
浏览器前端通过 REST API(/api/...)调用面板后端,同时用 SocketIO 默认 namespace 做终端等实时双向通信。
---
四、后端模块(Python,约 1.18 万行)
| 模块 | 行数 | 职责 |
|---|---|---|
app.py | 5217 | Flask 主应用:全部 API 路由(138 个)、SSH 连接池、健康检查、SocketIO 挂载 |
tunnel.py | 2412 | 反向隧道服务端(FRAME 协议)、SSH 代理、端口转发管理 |
tunnel_agent.py | 713 | 反向隧道 agent(跑在设备端) |
tunnel_crypto.py | — | 隧道加密(Ed25519 密钥协商) |
termux_agent.py | 445 | SocketIO agent(跑在手机 Termux 端) |
termux_sio.py | 328 | SocketIO 服务端(/agent namespace + PTY 桥接) |
transfer.py | 373 | 文件传输(「发送到」功能,SFTP 中转) |
crashmond.py | 575 | 崩溃防护守护(部署到目标机) |
crashmon.py | 214 | 崩溃防护面板端逻辑 |
nginx_manager.py | 550 | Nginx 网站管理 |
nginx_sites_ext.py | 232 | Nginx 站点扩展(SSL/伪静态等) |
backup.py | 283 | 备份/还原 |
remote_backup.py | 443 | 远程备份(跨设备) |
languages.py | — | 多语言(i18n) |
依赖(requirements.txt,极简):flask、flask-socketio、paramiko、werkzeug。
---
五、前端模块(原生 JS,17 个模块)
| 模块 | 职责 |
|---|---|
desktop.js | 桌面主界面:窗口管理器、任务栏、开始菜单、卡片仪表盘 |
server.js | 服务器增删改查、通用弹窗(showModal) |
system-panel.js | Linux 服务器系统管理面板(走 SSH) |
agent-panel.js | Termux 手机系统管理面板(走 SocketIO) |
filemgr.js | Linux 文件管理器(SFTP) |
terminal.js | 终端(xterm.js) |
tunnel.js | 穿透运维面板 |
port-tunnel.js | 端口穿透管理 |
docker.js / docker-gallery*.js | Docker 容器管理 + 镜像大全 |
app-store.js | 应用大全 |
task.js | 后台任务面板 |
backup.js | 备份面板 |
termux.js | Termux 安装/使用教程 |
i18n.js | 国际化 |
cms-install.js | CMS 一键安装 |
前端无框架,纯原生 JS + xterm.js(终端)+ Font Awesome(图标),整个界面模拟一个桌面操作系统(可拖拽窗口、任务栏、开始菜单)。
---
六、数据存储
- SQLite(
data/ssheverywhere.db):服务器卡片、端口转发、穿透记录、用户、任务等。 - 文件系统:备份文件、隧道密钥(
tunnel_keys/)、静态资源。
---
七、部署
- 面板:systemd 服务
ssh-everywhere.service,监听0.0.0.0:5501。 - 反向隧道:监听
0.0.0.0:4433(FRAME 协议)。 - 目标设备端 agent 以服务形式常驻(Linux 用 systemd / Termux 用 termux-services)。
---
八、三种设备的触达路径一览
| 设备类型 | 连接方式 | 最终落地协议 | 说明 |
|---|---|---|---|
| 有公网 IP 的 Linux 服务器 | 面板直连 | SSH | 最直接的场景 |
| 无公网 IP 的 Linux 服务器(NAS/树莓派等) | 反向隧道建代理 → SSH | SSH(经 FRAME 隧道搬运) | FRAME 是 SSH 的「搬运工」 |
| Android 手机(Termux) | SocketIO 长轮询 | SocketIO(唯一不用 SSH 的) | 手机 sshd 已彻底移除 |
---
九、关于项目名称「SSH Everywhere」
结论:不建议改名。 理由:
1. SSH 仍是绝对主体:除了 Android 手机这一个子场景,其余所有功能(Linux 服务器管理、穿透运维、文件传输、健康检查)最终都落在 SSH 上。
2. FRAME 反向隧道的本质就是「把 SSH 送到任何地方」:它解决的是「设备没公网 IP 时,怎么让 SSH 触达」的问题,语义上仍是「SSH 无处不在」。
3. SocketIO 只是实现细节,不是品牌定位:它是「Android 手机因为 sshd 不稳」这一特定场景的技术兜底,用户不会因为「手机不走 SSH」而觉得项目名「名不副实」。
4. 改名成本高、收益低:项目名散布在代码、文档、安装脚本、README、用户认知里,改名反而制造困惑。
若要微调,可在品牌宣传语上强调「SSH 为核心、多协议协同」,或在文档(如 docs/termux.md)里明确标注「Android 手机走 SocketIO 稳定通道」,把「SSH Everywhere」理解为「像 SSH 一样随处可管理」,而非字面的「只用 SSH 协议」。