# Tunne **Repository Path**: style1987_admin_admin/tunne ## Basic Information - **Project Name**: Tunne - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-11-08 - **Last Updated**: 2026-11-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Tunnel · 内网穿透工具(FastTunnel 协议兼容) 服务端部署在 Linux,客户端为 WPF 桌面程序(WPF-UI 4.3.0)。 控制协议与 [FastTunnel v2](https://github.com/FastTunnel/FastTunnel) 严格一致,双方可互相连通: 本服务端可接受官方 FastTunnel 客户端,本客户端也可连接官方 FastTunnel 服务端。 ## 功能 | 能力 | 说明 | |---|---| | TCP 端口转发 | 服务端监听公网端口(建议 `15000~15100`)转发到内网 `127.0.0.1:3389`,支持 RDP / SSH / 数据库等长连接 | | HTTP 子域名穿透 | 服务端按 `Host` 匹配 `{SubDomain}.{WebDomain}`,反向代理到内网站点(基于 YARP 直转,支持流式响应) | | Token 鉴权 | 个人使用:服务端 `Tunnel:Token` 与客户端 Token 填同一个值即可(默认 `tunnel-shared-token`,开箱即用) | | 流量与会话审计 | 每次连接记录会话、上下行字节数;实时在线客户端 / 规则 / 站点快照 | | 管理接口 | `/api/monitor/*`,通过 `X-Api-Key` 保护 | ## 解决方案结构 ``` src/ Tunnel.Core/ 协议模型、命令编解码、WebSocket 通道、PROXY 握手、流桥接、实体与 DTO(服务端/客户端共用) Tunnel.Client/ 客户端引擎(登录、断线重连、隧道建链),WPF 与控制台共用 Tunnel.Application/ Furion 动态 API 服务(监控查询)、SqlSugar 存储实现 Tunnel.Web.Core/ 服务端运行时(控制通道 / 数据通道 / HTTP 穿透中间件、端口监听)、SqlSugar 注册、Furion Startup Tunnel.Web.Entry/ 服务端入口(Program.cs + appsettings.json),发布目标 Linux Tunnel.Client.App/ WPF-UI 4.3.0 桌面客户端(命名空间 Tunnel.Client.App) tests/ Tunnel.SmokeTest/ 端到端冒烟测试(TCP 转发 + HTTP 穿透 + 管理接口) deploy/ tunnel.service systemd 单元 publish-linux.sh Linux 发布脚本 ``` 依赖关系单向:`Web.Entry → Web.Core → Application → Core`。 ## 快速开始 > 前置要求:开发机安装 **.NET 8 SDK**;服务端安装 **ASP.NET Core Runtime 8**(框架依赖部署),或用自包含发布免装运行时。 ### 1. 服务端(Linux) **一键部署(推荐)**:把仓库上传到服务器,root 执行一条命令即可完成发布、建用户、安装、生成 systemd 服务、开机自启与健康检查。 ```bash sudo bash deploy/install-server.sh -d tunnel.example.com -t your-shared-token -k your-admin-api-key ``` 已有 `out/server` 就直接用它,没有则现场 `dotnet publish`;重复执行会覆盖程序文件,但保留 `config/appsettings.json` 和 `Data/`。 **手动部署**(等价步骤): ```bash # 构建发布(在开发机执行,也可以直接在 Linux 上构建) bash deploy/publish-linux.sh # 服务器上 sudo useradd -r -s /usr/sbin/nologin tunnel || true sudo mkdir -p /opt/tunnel/Data && sudo cp -r out/server/* /opt/tunnel/ sudo chown -R tunnel:tunnel /opt/tunnel # SQLite 要在 Data/ 下建库,必须可写 sudo cp deploy/tunnel.service /etc/systemd/system/ sudo systemctl daemon-reload && sudo systemctl enable --now tunnel sudo systemctl status tunnel ``` 默认监听 `http://0.0.0.0:1270`(同时在 `Data/tunnel.db` 创建 SQLite 数据库并自动建表)。 需要把 `config/appsettings.json` 放到运行目录可覆盖配置,或用环境变量: ```bash Tunnel__WebDomain=tunnel.example.com Tunnel__Token=your-shared-token Tunnel__ApiKey=your-admin-api-key ``` ### 2. 客户端(Windows) ```powershell dotnet build src/Tunnel.Client.App/Tunnel.Client.App.csproj -c Release # 运行产物:src/Tunnel.Client.App/bin/Release/net8.0-windows/Tunnel.Client.App.exe ``` 界面分四块:**运行日志**、**端口转发**、**隧道链接**(地址 / 端口 / ws·wss / Token + 实时流量)、**设置**。 配置保存在 `%AppData%\Tunnel\client.json`,字段与官方客户端配置一致,可直接互换。 首次运行(无配置文件)默认连接 `ws://124.223.58.244:1270`,Token 默认 `tunnel-shared-token`,与服务端 `Tunnel:Token` 保持一致即可直接连上;程序启动后会自动连接。 > 增删转发规则后客户端会自动重连,服务端映射随即更新,无需手动断开。 > Web 子域名穿透功能目前暂时隐藏(`MainWindow.xaml.cs` 中注释保留,恢复时取消注释即可)。 ### 3. 打包 Windows 安装包 **推荐:Inno Setup 单文件 EXE**(不依赖 Windows Installer,安装/卸载都不需要管理员权限) ```powershell winget install JRSoftware.InnoSetup # 首次需要 powershell -ExecutionPolicy Bypass -File installer\build-installer-inno.ps1 ``` 产物:`dist\Tunnel-Setup-2.3.0.exe`(约 57 MB)。带中文向导(欢迎 → 许可协议 → 选择安装目录 → 附加任务 → 安装 → 完成),装到 `%LocalAppData%\Programs\Tunnel`。 **备选:WiX MSI** ```powershell powershell -ExecutionPolicy Bypass -File installer\build-installer.ps1 ``` 产物:`dist\Tunnel-Setup-2.3.0.msi`(约 67 MB)。注意 MSI 依赖 Windows Installer,某些机器上 `Config.Msi` 目录权限异常会导致安装/卸载报 `Could not set file security ... Error: 5`,遇到这类环境请改用上面的 EXE 安装包。 两种包都会创建桌面与开始菜单快捷方式,图标取自 `src/Tunnel.Client.App/Assets/app.ico`;中文向导文案在 `installer/Languages/ChineseSimplified.isl`。 ## 服务端配置(appsettings.json) ```jsonc { "urls": "http://0.0.0.0:1270", "Database": { "ConnectionString": "Data Source=Data/tunnel.db", "AutoMigrate": true }, "Tunnel": { "WebDomain": "tunnel.example.com", // Web 穿透根域名 "EnableForward": true, // 是否允许 TCP 端口转发 "Token": "tunnel-shared-token", // 客户端填同一个值;留空表示不校验 "ApiKey": "CHANGE_ME_ADMIN_API_KEY", // 管理接口密钥,留空不校验 "RewriteHostHeader": true, // 反代时把 Host 改写为内网地址(绕开 Vite 等 Host 校验) "SwapTimeoutSeconds": 15 // 等待客户端建立数据通道的超时 } } ``` 生产环境建议:`AutoMigrate` 保持 `true` 仅适用于 SQLite 单机场景;如需关闭,请自行执行 `CodeFirst.GetDifferenceTables(...).ToDiffString()` 导出 DDL 人工执行。 ## 管理接口 所有 `/api` 请求需带请求头 `X-Api-Key`。 | 方法 | 路径 | 说明 | |---|---|---| | GET | `/api/monitor/overview` | 在线客户端数、隧道数、累计流量、运行时长 | | GET | `/api/monitor/clients` | 在线客户端列表(含会话、上下行字节数) | | GET | `/api/monitor/forwards` | 端口转发规则(含活跃连接数、流量) | | GET | `/api/monitor/websites` | HTTP 穿透站点 | | GET | `/api/monitor/sessions` | 历史会话分页(`page`、`pageSize`、`clientIp`、`online`) | 返回结构:`{ "succeeded": true, "message": null, "data": ... }`。 ## 协议要点(与官方兼容的关键) 1. **控制通道**:客户端以 WebSocket 连接服务端端口,携带请求头 `FT_VERSION`(主版本必须与服务端一致,当前 `2.3.0`)与 `FT_TOKEN`。 2. **命令格式**:`{类型字节}{内容}\n`,类型 `1=Login`、`2=Swap(HTTP)`、`3=Forward(TCP)`、`4=Log`。 注意官方读取逻辑会在收到 `EndOfMessage=true` 的帧时丢弃数据,因此本实现**以 `endOfMessage:false` 单帧发送**,接收端按 `\n` 自行切分。 3. **登录体**:`{"Webs":[{"SubDomain","LocalIp","LocalPort","WWW"}],"Forwards":[{"LocalIp","LocalPort","RemotePort","Protocol"}]}`(PascalCase)。 4. **数据通道**:服务端下发 `{requestId}|{ip}:{port}` 后,客户端**新建一条 TCP 连接**到服务端同一端口并发送 `PROXY /{requestId} HTTP/1.1\r\nHost: {addr}:{port}\r\n\r\n`,随后该连接即为裸双向字节流(服务端通过 `IConnectionTransportFeature` 接管连接)。 5. **HTTP 穿透**:服务端用 YARP 直转,`ConnectCallback` 打开上面的数据通道,由 YARP 与内网站点完成 HTTP/1.1 会话。 ## 已知限制 - 仅实现 TCP 隧道;配置 `Protocol: "UDP"` 的规则会被跳过(官方 UDP 隧道未复刻)。 - 控制通道、数据通道、管理接口、HTTP 穿透共用同一个监听端口;如需 80/443,请在前置 Nginx 上做端口映射或反向代理(WebSocket 需 `Upgrade` 支持)。 - HTTP 穿透基于 HTTP/1.1;TLS/SNI 分流未实现。 - 会话与流量统计存储使用 SQLite(单机、零外部依赖);Token 只有服务端配置里的一个,不做多 Token/过期管理。 ## 验证 ```bash # 1. 启动服务端 dotnet run --project src/Tunnel.Web.Entry --no-launch-profile --urls http://127.0.0.1:1270 # 2. 另开终端跑冒烟测试(默认 token = tunnel-shared-token,api key 见 appsettings.json) dotnet run --project tests/Tunnel.SmokeTest ``` 覆盖:控制通道登录、TCP 端口转发回环、HTTP 子域名穿透、管理接口与流量统计。 冒烟测试支持环境变量覆盖,可用于与官方实现做互通验证: | 变量 | 说明 | |---|---| | `TUNNEL_SERVER_PORT` | 服务端端口,默认 1270 | | `TUNNEL_CLIENT_TOKEN` | 客户端 Token | | `TUNNEL_API_KEY` | 管理接口密钥,设为 `none` 或留空则跳过管理接口校验 | | `TUNNEL_WEB_DOMAIN` | Web 穿透根域名 | | `TUNNEL_LOCAL_ONLY` | 设为 `1` 时只启动本地待穿透服务,由外部客户端接入 | ### 互通性验证结论(已实测) | 方向 | 结果 | |---|---| | 本客户端 → 官方 FastTunnel v2 服务端(`dotnet run --project FastTunnel.Server`) | 登录、TCP 端口转发、HTTP 子域名穿透全部通过 | | 官方 FastTunnel v2 客户端 → 本服务端 | 登录、映射注册、TCP 端口转发、HTTP 子域名穿透全部通过 | > 注:官方服务端使用的是 `config/appsettings.json` 中的 `WebDomain=test.cc`、`Tokens` 等默认值,验证时把对应环境变量改成一致即可。 ## 数据与日志位置 - SQLite 数据库:内容根目录下的 `Data/tunnel.db`(未指定绝对路径时);开发期内容根即 `src/Tunnel.Web.Entry`,发布后为程序所在目录。 - 表结构由 SqlSugar CodeFirst 自动创建(`tunnel_session`)。 - 客户端配置:`%AppData%\Tunnel\client.json`。