# cec-tunnel **Repository Path**: civil-engineering-cloud/cec-tunnel ## Basic Information - **Project Name**: cec-tunnel - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-02-08 - **Last Updated**: 2026-05-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # CEC-Tunnel - 内网穿透 基于 WebSocket 协议的反向隧道工具,通过 ws (明文) 和 wss (加密) 双端口提供内网穿透能力。 ## 技术栈 - 核心: Rust - 协议: WebSocket(控制消息 JSON / 数据消息 Binary,16 字节 UUID prefix) - 平台: Linux / macOS / Windows ## 功能特性 - 🚀 反向隧道,无需公网 IP - 🔒 双端口: 9998 (ws 明文) + 9999 (wss 加密),独立的 9997 管理端口(仅 127.0.0.1) - 🔑 NPS 风格客户端鉴权:admin 预先 `register-client` 拿到 vkey,客户端用 vkey 启动,未注册的连接一律拒绝 - 🔄 自动重连 + 指数退避 + 抖动;稳定连接后自动重置退避 - 💓 心跳超时检测(60 秒),自动接管半开连接 - 🔐 管理 API 仅 127.0.0.1,不内置鉴权(需远程暴露走 APISIX/nginx 等外部网关) - 🧯 优雅关停:服务端响应 SIGINT/SIGTERM 时通知所有客户端、合理回收资源 - 📦 单文件,无依赖 ## 鉴权模型 只有一个凭据: | 凭据 | 作用 | 配置位置 | |---|---|---| | `vkey` | 客户端连接 WS | admin 用 `register-client` 创建,每个客户端一个 | vkey 持久化在 `--clients-file`(默认 `/var/lib/cec-tunnel/clients.json`)。删除/吊销一个客户端就是 `delete-client`。 管理 HTTP API(9997)仅监听 `127.0.0.1`,**不内置鉴权**——同机进程可以直连。 如需远程访问,请用 APISIX / nginx / k8s NetworkPolicy 等外部层做鉴权。这是有意为之: cec-tunnel 是一个功能模块,不重复实现已有平台 auth 层。 ## 隧道持久化(v0.6 起) 隧道配置(不是流量统计)持久化在 `--tunnels-file`(默认 `/var/lib/cec-tunnel/tunnels.json`)。 行为: - `add-tunnel` 立刻写盘;**客户端在线则同时启动 listener**,离线只持久化(state=offline) - 客户端**重连/服务端重启**后,对应客户端在线时自动重建 listener,admin 不需要重做 add-tunnel - 客户端离线时,对应的 listener 关闭(端口释放)但 store 条目保留 - `delete-tunnel` 永久删除(停 listener + 删 store) - `delete-client` 级联清掉该客户端的所有隧道 - 流量计数(bytes_sent/recv)**仅内存**,重启或客户端重连会归零 跟 NPS 的两点差异: - **lazy listener**:服务端启动时不会预占所有端口;只在客户端注册成功后才 bind。NPS 是启动即占,外部连得上但没人转发,假活。 - **atomic write**:tunnels.json 通过 `.tmp + rename` 写入,断电不会损坏。NPS 是直接覆盖。 ## 安装 ### Linux / macOS ```bash # 客户端 curl -fsSL https://gitee.com/civil-engineering-cloud/cec-tunnel/raw/main/install.sh | bash # 服务端 curl -fsSL https://gitee.com/civil-engineering-cloud/cec-tunnel/raw/main/install.sh | bash -s -- -t server # 国内 (Gitee) curl -fsSL https://gitee.com/civil-engineering-cloud/cec-tunnel/raw/main/install.sh | MIRROR=gitee bash ``` ### Windows ```powershell irm https://gitee.com/civil-engineering-cloud/cec-tunnel/raw/main/install.ps1 | iex ``` ### 手动下载 - GitHub: https://github.com/civil-engineering-cloud/cec-tunnel/releases - Gitee: https://gitee.com/civil-engineering-cloud/cec-tunnel/releases ### 卸载 ```bash # 卸载客户端二进制(保留日志/数据) curl -fsSL https://gitee.com/civil-engineering-cloud/cec-tunnel/raw/main/uninstall.sh | bash # 卸载服务端 curl -fsSL https://gitee.com/civil-engineering-cloud/cec-tunnel/raw/main/uninstall.sh | bash -s -- -t server # 全卸 + 清数据(删 /var/log/cec-tunnel/、/var/lib/cec-tunnel/、/etc/cec-tunnel/,不可恢复) curl -fsSL https://gitee.com/civil-engineering-cloud/cec-tunnel/raw/main/uninstall.sh | bash -s -- -t both --purge ``` ## 快速开始 ### 1. 部署服务端 ```bash # 启动(同时开 ws + wss + admin) cec-tunnel-server run --enable-ws --enable-wss # 后台运行 cec-tunnel-server run --enable-ws --enable-wss -d # 自定义端口范围(不传则 OS 自动分配,无范围限制)/ 持久化文件路径 cec-tunnel-server run --enable-ws \ --port-start 30000 --port-end 40000 \ --clients-file /etc/cec-tunnel/clients.json \ --tunnels-file /etc/cec-tunnel/tunnels.json ``` ### 2. 注册客户端(admin 在服务端操作) ```bash # 创建一个 vkey cec-tunnel-server register-client --name office # 输出: # ID: 1 # 名称: office # vkey: 8f3c1e2a... # # 启动客户端: # cec-tunnel-client -s ws://:9998 --vkey 8f3c1e2a... # 查看所有客户端 cec-tunnel-server clients # 查看详情(含 vkey) cec-tunnel-server get-client 1 # 断开但保留 vkey cec-tunnel-server kick 1 # 吊销 vkey(同时断开) cec-tunnel-server delete-client 1 ``` ### 3. 运行客户端 ```bash # 用 vkey 启动 cec-tunnel-client -s ws://your-server:9998 --vkey 8f3c1e2a... # 通过环境变量传 vkey(避免泄漏到进程列表) CEC_TUNNEL_VKEY=8f3c1e2a... cec-tunnel-client -s wss://your-server:9999 # 后台运行 CEC_TUNNEL_VKEY=8f3c1e2a... cec-tunnel-client -s wss://your-server:9999 -d ``` ### 4. 给客户端添加隧道 隧道一律由服务端管理。admin 在服务端执行: ```bash # 暴露 client_id=1 的 22 端口到服务端 10022 cec-tunnel-server add-tunnel --client-id 1 --local-port 22 --server-port 10022 # 不指定 server-port 则在 port_start..=port_end 自动分配 cec-tunnel-server add-tunnel --client-id 1 --local-port 3306 --name mysql # 隧道也可以通过 HTTP API 添加 curl -X POST http://127.0.0.1:9997/api/clients/1/tunnels \ -H "Content-Type: application/json" \ -d '{"local_port": 22, "name": "ssh", "server_port": 10022}' ``` ### 5. 访问内网服务 ```bash ssh -p 10022 user@your-server ``` ## 端口说明 | 端口 | 协议 | 默认 bind | 用途 | |------|------|-----------|------| | 9997 | HTTP | 127.0.0.1 | 管理 API | | 9998 | ws:// | 0.0.0.0 | 客户端连接(明文) | | 9999 | wss:// | 0.0.0.0 | 客户端连接(TLS) | | OS 自动分配 | TCP | 0.0.0.0 | 隧道映射端口;默认不限范围,由 OS 选空闲端口。需要限制可加 `--port-start`/`--port-end`(成对) | ## TLS 证书 wss 加密需要 TLS 证书。默认路径: - 证书: `/etc/cec-tunnel/cert.pem` - 私钥: `/etc/cec-tunnel/key.pem` ```bash cec-tunnel-server run --enable-wss --tls-cert /path/to/cert.pem --tls-key /path/to/key.pem ``` 如果证书文件不存在,wss 端口会跳过,仅提供 ws 服务。 ### Let's Encrypt ```bash sudo certbot certonly --standalone -d your-domain.com sudo mkdir -p /etc/cec-tunnel sudo ln -sf /etc/letsencrypt/live/your-domain.com/fullchain.pem /etc/cec-tunnel/cert.pem sudo ln -sf /etc/letsencrypt/live/your-domain.com/privkey.pem /etc/cec-tunnel/key.pem ``` ### 自签名(仅测试) ```bash openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes sudo mkdir -p /etc/cec-tunnel sudo mv cert.pem key.pem /etc/cec-tunnel/ ``` ## HTTP API(管理端口 9997) 管理 API 不内置鉴权(仅监听 127.0.0.1)。 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/status` | 服务状态概览 | | POST | `/api/clients` | 注册新客户端(body: `{name}`),返回 `{id, vkey}` | | GET | `/api/clients` | 列出所有客户端(不含 vkey) | | GET | `/api/clients/:id` | 详情(含 vkey + 当前会话 + 隧道列表) | | POST | `/api/clients/:id/kick` | 断开但保留注册条目 | | DELETE | `/api/clients/:id` | 删除注册条目(自动断开) | | POST | `/api/clients/:id/tunnels` | 给客户端添加隧道 | | GET | `/api/tunnels` | 列出所有隧道 | | GET | `/api/tunnels/:id` | 隧道详情 | | DELETE | `/api/tunnels/:id` | 关闭隧道 | ```bash # 注册 curl -X POST http://127.0.0.1:9997/api/clients \ -H "Content-Type: application/json" \ -d '{"name": "office"}' # → { "code": 0, "data": { "id": "1", "name": "office", "vkey": "..." } } # 列出 curl http://127.0.0.1:9997/api/clients # 鉴权时 curl -H "Authorization: Bearer mysecret" http://127.0.0.1:9997/api/clients ``` ## 架构 ``` ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ 外部用户 │ │ CEC Tunnel │ │ 内网机器 │ │ │ │ Server │ │ │ │ ssh -p 10022 │────────▶│ ws: 9998 │◀────────│ cec-tunnel-client│ │ your-server │ │ wss: 9999 │ vkey 鉴权│ --vkey xxx │ │ │ │ admin: 9997 │ │ │ │ │ │ tunnels: 3xxxx │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ 注册表: clients.json (id, name, vkey) ``` ## 许可证 MIT License