feat: 移除了多余的pprof包导入 fix: 服务器关闭时不再等待5s |
||
|---|---|---|
| src | ||
| .gitignore | ||
| DEBUG_GUIDE.md | ||
| README.md | ||
| TRAFFIC_MONITORING.md | ||
| monitor.sh | ||
README.md
端口转发和内网穿透系统
一个高性能、生产级别的 TCP 端口转发和内网穿透系统,使用 Go 语言编写。采用自定义隧道协议实现透明代理,支持多路复用和自动重连。
功能特性
- ✅ 透明隧道协议: 基于自定义应用层协议的透明代理,外部完全不可见
- ✅ 多路复用: 单个隧道连接支持多个并发TCP会话
- ✅ 端口转发: 支持配置化的 TCP 端口范围管理和转发
- ✅ 内网穿透: 支持通过隧道连接实现内网服务穿透
- ✅ 持久化存储: 使用 SQLite 数据库持久化端口映射配置
- ✅ 动态管理: 通过 HTTP API 动态创建和删除端口映射
- ✅ 自动恢复: 服务器启动时自动恢复已保存的端口映射
- ✅ 连接池管理: 高效的连接池和并发管理
- ✅ 优雅关闭: 支持优雅关闭和信号处理
- ✅ 自动重连: 客户端支持断线自动重连
- ✅ 生产级代码: 完善的错误处理、日志记录和性能优化
系统架构
整体架构图
graph TB
subgraph "外部网络"
Client[外部客户端]
Internet[互联网]
end
subgraph "公网服务器"
Server[转发服务器]
API[HTTP API]
DB[(SQLite数据库)]
Forwarder[端口转发器]
TunnelServer[隧道服务器]
end
subgraph "内网环境"
TunnelClient[隧道客户端]
LocalService[本地服务]
end
Client -->|TCP连接| Server
Server --> Forwarder
Server --> TunnelServer
API --> DB
API --> Forwarder
API --> TunnelServer
TunnelServer <-->|隧道协议| TunnelClient
TunnelClient --> LocalService
style Server fill:#e1f5fe
style TunnelServer fill:#f3e5f5
style TunnelClient fill:#f3e5f5
style LocalService fill:#e8f5e8
隧道协议设计
我们的隧道协议采用自定义应用层协议,格式如下:
| 版本(1B) | 类型(1B) | 长度(4B) | 数据 |
协议特点:
- 版本: 0x01 (当前版本)
- 类型: 消息类型 (连接请求/响应/数据/关闭/心跳)
- 长度: 数据部分长度 (大端序)
- 数据: 消息载荷
消息类型
graph LR
subgraph "隧道协议消息类型"
ConnReq[0x01<br/>连接请求]
ConnResp[0x02<br/>连接响应]
Data[0x03<br/>数据传输]
Close[0x04<br/>关闭连接]
KeepAlive[0x05<br/>心跳]
end
ConnReq --> ConnResp
ConnResp --> Data
Data --> Close
KeepAlive --> KeepAlive
style ConnReq fill:#ffcdd2
style ConnResp fill:#dcedc8
style Data fill:#bbdefb
style Close fill:#ffcc80
style KeepAlive fill:#d1c4e9
工作流程详解
1. 直接端口转发模式
当目标服务可以直接访问时,使用直接转发模式:
sequenceDiagram
participant C as 外部客户端
participant S as 转发服务器
participant T as 目标服务
Note over C,T: 直接端口转发模式
C->>S: TCP SYN (端口10001)
S->>S: 查找端口映射
S->>T: 建立连接 (192.168.1.100:22)
T-->>S: 连接确认
S-->>C: TCP SYN-ACK
loop 数据传输
C->>S: 数据包
S->>T: 转发数据
T-->>S: 响应数据
S-->>C: 转发响应
end
C->>S: 关闭连接
S->>T: 关闭连接
2. 隧道穿透模式 (核心特性)
当目标服务在内网时,使用隧道穿透模式。这是本系统的核心创新点:
sequenceDiagram
participant C as 外部客户端
participant S as 转发服务器
participant TS as 隧道服务器
participant TC as 隧道客户端
participant L as 本地服务
Note over C,L: 隧道穿透模式 - 透明代理
rect rgb(255, 245, 245)
Note over TS,TC: 1. 隧道连接建立
TC->>TS: 连接隧道服务器
TS-->>TC: 接受连接
end
rect rgb(245, 255, 245)
Note over C,L: 2. 外部客户端请求处理
C->>S: TCP SYN (端口10022)
S->>S: 检查端口映射
Note over S: 发现需要使用隧道
S->>TS: 请求转发连接
end
rect rgb(245, 245, 255)
Note over TS,L: 3. 隧道协议交互
TS->>TC: ConnectRequest(ID=1, Port=22)
Note over TC: 协议格式: |0x01|0x01|0x00000006|ID+Port|
TC->>L: 尝试连接本地服务
L-->>TC: 连接成功/失败
TC->>TS: ConnectResponse(ID=1, Status=Success)
Note over TS: 协议格式: |0x01|0x02|0x00000005|ID+Status|
TS-->>S: 连接建立完成
end
rect rgb(255, 255, 245)
Note over C,L: 4. 透明数据转发
S-->>C: TCP SYN-ACK (对外部客户端响应)
loop 数据传输 (对外部完全透明)
C->>S: 应用数据
S->>TS: 转发到隧道
TS->>TC: Data(ID=1, 数据)
Note over TS: 协议格式: |0x01|0x03|长度|ID+数据|
TC->>L: 转发到本地服务
L-->>TC: 本地服务响应
TC->>TS: Data(ID=1, 响应数据)
TS->>S: 从隧道返回
S-->>C: 返回给外部客户端
end
end
rect rgb(250, 250, 250)
Note over C,L: 5. 连接关闭
C->>S: 关闭连接
S->>TS: 通知关闭
TS->>TC: Close(ID=1)
Note over TC: 协议格式: |0x01|0x04|0x00000004|ID|
TC->>L: 关闭本地连接
end
3. 多路复用演示
单个隧道连接支持多个并发会话:
sequenceDiagram
participant C1 as 客户端1
participant C2 as 客户端2
participant S as 转发服务器
participant T as 隧道连接
participant TC as 隧道客户端
participant L1 as 本地服务1
participant L2 as 本地服务2
Note over C1,L2: 隧道多路复用
rect rgb(255, 245, 245)
Note over C1,L1: 连接1 - SSH服务
C1->>S: 连接端口10022
S->>T: ConnectRequest(ID=1, Port=22)
T->>TC: 转发请求
TC->>L1: 连接SSH服务
L1-->>TC: 连接成功
TC->>T: ConnectResponse(ID=1, Success)
T->>S: 确认
S-->>C1: 建立连接
end
rect rgb(245, 255, 245)
Note over C2,L2: 连接2 - HTTP服务 (同时进行)
C2->>S: 连接端口10080
S->>T: ConnectRequest(ID=2, Port=80)
T->>TC: 转发请求 (同一隧道)
TC->>L2: 连接HTTP服务
L2-->>TC: 连接成功
TC->>T: ConnectResponse(ID=2, Success)
T->>S: 确认
S-->>C2: 建立连接
end
Note over C1,L2: 两个连接同时传输数据
par 连接1数据传输
C1->>S: SSH数据
S->>T: Data(ID=1, SSH数据)
T->>TC: 转发
TC->>L1: 发送到SSH
and 连接2数据传输
C2->>S: HTTP请求
S->>T: Data(ID=2, HTTP数据)
T->>TC: 转发 (同一隧道)
TC->>L2: 发送到HTTP
end
4. 系统组件交互
graph TB
subgraph "服务器端组件"
Main[main.go]
Config[config.go]
API[api.go]
DB[database.go]
Forwarder[forwarder.go]
TunnelServer[tunnel/server.go]
end
subgraph "客户端组件"
ClientMain[client/main.go]
TunnelClient[tunnel/client.go]
end
subgraph "外部接口"
HTTP[HTTP API]
TCP[TCP端口]
TunnelPort[隧道端口]
end
Main --> Config
Main --> API
Main --> TunnelServer
API --> DB
API --> Forwarder
Forwarder --> TCP
TunnelServer --> TunnelPort
HTTP --> API
TunnelPort <--> TunnelClient
ClientMain --> TunnelClient
style Main fill:#e3f2fd
style TunnelServer fill:#f3e5f5
style TunnelClient fill:#f3e5f5
style API fill:#e8f5e8
5. 错误处理和重连机制
stateDiagram-v2
[*] --> 初始化
初始化 --> 连接中 : 启动连接
连接中 --> 已连接 : 连接成功
连接中 --> 重连等待 : 连接失败
已连接 --> 传输中 : 开始传输
传输中 --> 已连接 : 传输完成
传输中 --> 重连等待 : 连接断开
重连等待 --> 连接中 : 重连尝试
已连接 --> [*] : 正常关闭
state 重连等待 {
[*] --> 等待5秒
等待5秒 --> 重试连接
重试连接 --> [*]
}
项目结构
go-tunnel/
├── README.md # 项目文档
├── config.yaml # 配置文件
├── src/ # 源代码目录
│ ├── go.mod # Go 模块文件
│ ├── Makefile # 构建脚本
│ ├── server/ # 服务器端
│ │ ├── main.go # 服务器主程序
│ │ ├── config/ # 配置管理
│ │ │ ├── config.go
│ │ │ └── config_test.go
│ │ ├── db/ # 数据库管理
│ │ │ ├── database.go
│ │ │ └── database_test.go
│ │ ├── forwarder/ # 端口转发
│ │ │ ├── forwarder.go
│ │ │ └── forwarder_test.go
│ │ ├── tunnel/ # 隧道服务器
│ │ │ ├── tunnel.go # 新隧道协议实现
│ │ │ └── tunnel_test.go
│ │ └── api/ # HTTP API
│ │ ├── api.go
│ │ └── api_test.go
│ ├── client/ # 客户端
│ │ ├── main.go # 客户端主程序
│ │ └── tunnel/ # 隧道客户端
│ │ ├── client.go # 新隧道协议实现
│ │ └── client_test.go
│ └── test/ # 集成测试
│ ├── integration_test.go
│ ├── run_tests.sh
│ └── README.md
└── bin/ # 编译输出目录
├── server
└── client
核心技术特点
1. 透明代理机制
flowchart TD
A[外部TCP连接请求] --> B{检查端口映射}
B -->|直接转发| C[建立目标连接]
B -->|隧道模式| D[发送隧道请求]
D --> E[等待客户端确认]
E -->|成功| F[建立隧道会话]
E -->|失败| G[拒绝连接]
F --> H[开始透明转发]
C --> H
G --> I[关闭客户端连接]
H --> J[数据传输]
style D fill:#e1f5fe
style F fill:#e8f5e8
style H fill:#fff3e0
2. 协议栈对比
graph LR
subgraph "传统方案"
A1[应用数据] --> A2[TCP] --> A3[IP] --> A4[以太网]
end
subgraph "我们的隧道协议"
B1[应用数据] --> B2[隧道协议] --> B3[TCP] --> B4[IP] --> B5[以太网]
end
subgraph "隧道协议详细"
C1[版本] --> C2[类型] --> C3[长度] --> C4[数据]
end
style B2 fill:#e3f2fd
style C1 fill:#ffebee
style C2 fill:#e8f5e8
style C3 fill:#fff3e0
style C4 fill:#f3e5f5
3. 连接状态管理
服务器端维护两种连接状态:
graph TB
subgraph "服务器状态管理"
Pending[待处理连接<br/>PendingConnection]
Active[活跃连接<br/>ActiveConnection]
Pending --> |客户端确认| Active
Pending --> |超时/失败| Closed[关闭]
Active --> |正常关闭| Closed
Active --> |异常断开| Closed
end
subgraph "连接生命周期"
Create[创建] --> Wait[等待确认]
Wait --> Establish[建立]
Establish --> Transfer[传输]
Transfer --> Close[关闭]
end
style Pending fill:#fff3e0
style Active fill:#e8f5e8
style Closed fill:#ffebee
协议详细规范
隧道协议消息格式
| 字段 | 大小 | 描述 |
|---|---|---|
| 版本 | 1字节 | 协议版本,当前为0x01 |
| 类型 | 1字节 | 消息类型 |
| 长度 | 4字节 | 数据部分长度(大端序) |
| 数据 | 变长 | 消息载荷 |
消息类型详解
1. 连接请求 (0x01)
数据格式: [连接ID(4字节)] + [目标端口(2字节)]
示例: 00 00 00 01 00 16 (连接ID=1, 端口=22)
2. 连接响应 (0x02)
数据格式: [连接ID(4字节)] + [状态(1字节)]
状态码: 0x00=成功, 0x01=失败
示例: 00 00 00 01 00 (连接ID=1, 状态=成功)
3. 数据传输 (0x03)
数据格式: [连接ID(4字节)] + [实际数据]
示例: 00 00 00 01 + [SSH数据包]
4. 关闭连接 (0x04)
数据格式: [连接ID(4字节)]
示例: 00 00 00 01 (关闭连接ID=1)
5. 心跳 (0x05)
数据格式: 无数据
用途: 保持连接活跃,检测连接状态
TCP请求处理流程
flowchart TD
Start[TCP SYN到达] --> Check{检查端口映射}
Check -->|未找到| Reject[拒绝连接]
Check -->|直接转发| Direct[建立目标连接]
Check -->|隧道模式| Tunnel{隧道是否连接}
Tunnel -->|未连接| Reject
Tunnel -->|已连接| CreateReq[创建连接请求]
CreateReq --> SendReq[发送ConnectRequest]
SendReq --> WaitResp[等待ConnectResponse]
WaitResp -->|超时| Timeout[连接超时]
WaitResp -->|失败| Failed[连接失败]
WaitResp -->|成功| Success[连接成功]
Direct --> DataForward[数据转发]
Success --> DataForward
DataForward --> Monitor[监控连接状态]
Monitor -->|断开| Cleanup[清理资源]
Timeout --> Reject
Failed --> Reject
Reject --> End[结束]
Cleanup --> End
style CreateReq fill:#e3f2fd
style SendReq fill:#e1f5fe
style WaitResp fill:#f3e5f5
style Success fill:#e8f5e8
style DataForward fill:#fff3e0
快速开始
1. 环境要求
- Go 1.19+
- Linux/macOS/Windows
- 网络端口访问权限
2. 安装和编译
# 克隆项目
git clone <repository-url>
cd go-tunnel
# 进入源代码目录
cd src
# 安装依赖
go mod download
# 编译项目
make clean
make
# 或者分别编译
make server # 编译服务器
make client # 编译客户端
3. 配置服务器
编辑 config.yaml 文件:
# 端口范围配置
port_range:
from: 10000 # 起始端口
end: 10100 # 结束端口
# 内网穿透配置
tunnel:
enabled: true # 是否启用内网穿透
listen_port: 9000 # 隧道监听端口
# HTTP API 配置
api:
listen_port: 8080 # API服务端口
# 数据库配置
database:
path: "./data/mappings.db" # 数据库文件路径
4. 启动服务器
# 使用默认配置启动
cd bin
./server
# 或指定配置文件
./server -config ../config.yaml
# 查看帮助
./server -help
5. 启动客户端(内网穿透模式)
# 连接到服务器
cd bin
./client -server <服务器IP>:9000
# 例如
./client -server 1.2.3.4:9000
# 查看帮助
./client -help
6. 运行测试
# 运行所有测试
make test
# 运行特定组件测试
go test ./server/tunnel -v
go test ./client/tunnel -v
# 运行集成测试
./test/run_tests.sh
使用示例
示例1: SSH内网穿透
sequenceDiagram
participant User as 用户
participant Server as 公网服务器
participant Client as 内网客户端
participant SSH as SSH服务器
Note over User,SSH: SSH内网穿透示例
User->>Server: 创建端口映射
Note over Server: POST /api/mapping/create<br/>{"port": 10022}
Client->>Server: 建立隧道连接
Server-->>Client: 隧道连接确认
User->>Server: SSH连接 (port 10022)
Server->>Client: 隧道协议: ConnectRequest(ID=1, Port=22)
Client->>SSH: 连接本地SSH服务
SSH-->>Client: 连接成功
Client->>Server: 隧道协议: ConnectResponse(ID=1, Success)
Server-->>User: SSH连接建立
loop SSH会话
User->>Server: SSH命令
Server->>Client: 隧道协议: Data(ID=1, SSH数据)
Client->>SSH: 转发SSH命令
SSH-->>Client: 命令输出
Client->>Server: 隧道协议: Data(ID=1, 输出数据)
Server-->>User: 返回命令输出
end
操作步骤:
# 1. 在公网服务器启动服务
./server -config config.yaml
# 2. 创建SSH端口映射
curl -X POST http://server:8080/api/mapping/create \
-H "Content-Type: application/json" \
-d '{"port": 10022}'
# 3. 在内网机器启动客户端
./client -server server:9000
# 4. 用户通过公网服务器连接内网SSH
ssh user@server -p 10022
示例2: Web服务穿透
# 1. 创建HTTP服务映射
curl -X POST http://server:8080/api/mapping/create \
-H "Content-Type: application/json" \
-d '{"port": 10080}'
# 2. 用户访问内网Web服务
curl http://server:10080
# 实际访问的是内网机器的80端口服务
示例3: 数据库穿透
# 1. 创建MySQL映射
curl -X POST http://server:8080/api/mapping/create \
-H "Content-Type: application/json" \
-d '{"port": 13306}'
# 2. 连接内网数据库
mysql -h server -P 13306 -u username -p
HTTP API 参考
API概览
graph LR
subgraph "HTTP API端点"
Health[GET /health]
Create[POST /api/mapping/create]
Remove[POST /api/mapping/remove]
List[GET /api/mapping/list]
end
subgraph "功能"
Health --> HealthCheck[健康检查]
Create --> CreateMapping[创建端口映射]
Remove --> RemoveMapping[删除端口映射]
List --> ListMappings[列出所有映射]
end
style Health fill:#e8f5e8
style Create fill:#e3f2fd
style Remove fill:#ffebee
style List fill:#fff3e0
创建端口映射
请求:
curl -X POST http://localhost:8080/api/mapping/create \
-H "Content-Type: application/json" \
-d '{
"port": 10001,
"target_ip": "192.168.1.100"
}'
响应:
{
"success": true,
"message": "端口映射创建成功",
"data": {
"port": 10001,
"target_ip": "192.168.1.100",
"use_tunnel": false
}
}
删除端口映射
请求:
curl -X POST http://localhost:8080/api/mapping/remove \
-H "Content-Type: application/json" \
-d '{
"port": 10001
}'
响应:
{
"success": true,
"message": "端口映射删除成功",
"data": {
"port": 10001
}
}
列出所有映射
请求:
curl http://localhost:8080/api/mapping/list
响应:
{
"success": true,
"message": "获取映射列表成功",
"data": {
"mappings": [
{
"id": 1,
"source_port": 10001,
"target_ip": "192.168.1.100",
"target_port": 10001,
"created_at": "2024-01-01 12:00:00"
}
],
"count": 1,
"use_tunnel": false
}
}
健康检查
请求:
curl http://localhost:8080/health
响应:
{
"status": "ok",
"tunnel_enabled": true,
"tunnel_connected": true
}
使用场景
场景 1: 直接端口转发(无隧道)
适用于服务器可以直接访问目标服务的情况。
- 配置
tunnel.enabled: false - 启动服务器
- 创建映射时指定
target_ip
curl -X POST http://localhost:8080/api/mapping/create \
-H "Content-Type: application/json" \
-d '{
"port": 10022,
"target_ip": "192.168.1.100"
}'
场景 2: 内网穿透(隧道模式)
适用于目标服务在内网,服务器无法直接访问的情况。
- 配置
tunnel.enabled: true - 启动服务器
- 在内网机器上启动客户端
- 创建映射(无需指定 target_ip)
curl -X POST http://localhost:8080/api/mapping/create \
-H "Content-Type: application/json" \
-d '{
"port": 10022
}'
性能优化与监控
系统性能架构
graph TB
subgraph "性能优化层次"
App[应用层优化]
Protocol[协议层优化]
Network[网络层优化]
System[系统层优化]
end
subgraph "应用层优化"
ConnPool[连接池管理]
Buffer[缓冲区优化]
Goroutine[协程池]
Memory[内存复用]
end
subgraph "协议层优化"
Multiplex[多路复用]
Compression[数据压缩]
KeepAlive[连接保活]
BatchSend[批量发送]
end
subgraph "监控指标"
Metrics[性能指标]
Logs[日志记录]
Health[健康检查]
Alert[告警机制]
end
App --> ConnPool
App --> Buffer
Protocol --> Multiplex
Protocol --> KeepAlive
ConnPool --> Metrics
Buffer --> Metrics
Multiplex --> Logs
style App fill:#e3f2fd
style Protocol fill:#e8f5e8
style Metrics fill:#fff3e0
连接池配置
数据库连接池在 db/database.go 中配置:
// 数据库连接池优化
db.SetMaxOpenConns(25) // 最大打开连接数
db.SetMaxIdleConns(5) // 最大空闲连接数
db.SetConnMaxLifetime(300*time.Second) // 连接最大生存时间
缓冲区大小优化
数据转发缓冲区配置:
// 不同场景的缓冲区配置
const (
SmallBuffer = 4 * 1024 // 4KB - 适用于控制消息
MediumBuffer = 32 * 1024 // 32KB - 适用于一般数据传输
LargeBuffer = 64 * 1024 // 64KB - 适用于大文件传输
)
并发控制架构
graph TB
subgraph "并发控制"
MainGoroutine[主协程]
TunnelGoroutine[隧道协程]
ForwarderGoroutine[转发协程]
ConnGoroutines[连接协程池]
end
subgraph "同步机制"
WaitGroup[WaitGroup]
Context[Context取消]
Channel[Channel通信]
Mutex[互斥锁]
end
MainGoroutine --> TunnelGoroutine
MainGoroutine --> ForwarderGoroutine
ForwarderGoroutine --> ConnGoroutines
TunnelGoroutine -.-> WaitGroup
ForwarderGoroutine -.-> Context
ConnGoroutines -.-> Channel
style MainGoroutine fill:#e3f2fd
style TunnelGoroutine fill:#f3e5f5
style ForwarderGoroutine fill:#e8f5e8
style ConnGoroutines fill:#fff3e0
监控指标
关键性能指标 (KPI)
graph LR
subgraph "连接指标"
TotalConn[总连接数]
ActiveConn[活跃连接数]
ConnRate[连接建立速率]
ConnDuration[连接持续时间]
end
subgraph "传输指标"
Throughput[吞吐量]
Latency[延迟]
PacketLoss[丢包率]
ErrorRate[错误率]
end
subgraph "资源指标"
CPUUsage[CPU使用率]
MemoryUsage[内存使用量]
GoroutineCount[协程数量]
FileDescriptor[文件描述符]
end
TotalConn --> Dashboard[监控面板]
Throughput --> Dashboard
CPUUsage --> Dashboard
style Dashboard fill:#e3f2fd
建议监控以下指标:
| 类别 | 指标 | 说明 | 阈值建议 |
|---|---|---|---|
| 连接 | 活跃端口映射数量 | 当前转发的端口数 | < 1000 |
| 连接 | 并发连接数 | 同时处理的连接数 | < 10000 |
| 性能 | 数据传输速率 | MB/s | 根据网络带宽 |
| 性能 | 连接建立延迟 | 毫秒 | < 100ms |
| 资源 | 内存使用量 | MB | < 512MB |
| 资源 | CPU使用率 | % | < 80% |
| 隧道 | 隧道连接状态 | 布尔值 | = true |
| 隧道 | 心跳响应时间 | 毫秒 | < 1000ms |
部署架构建议
生产环境部署
graph TB
subgraph "互联网"
Users[用户]
Internet[Internet]
end
subgraph "DMZ区域"
LB[负载均衡器]
Firewall[防火墙]
end
subgraph "应用服务器区域"
Server1[转发服务器1]
Server2[转发服务器2]
Database[(数据库)]
Monitor[监控系统]
end
subgraph "内网环境"
Client1[隧道客户端1]
Client2[隧道客户端2]
Services[内网服务]
end
Users --> Internet
Internet --> Firewall
Firewall --> LB
LB --> Server1
LB --> Server2
Server1 --> Database
Server2 --> Database
Monitor --> Server1
Monitor --> Server2
Server1 <--> Client1
Server2 <--> Client2
Client1 --> Services
Client2 --> Services
style LB fill:#e3f2fd
style Server1 fill:#e8f5e8
style Server2 fill:#e8f5e8
style Database fill:#fff3e0
style Monitor fill:#f3e5f5
Docker部署
Dockerfile示例
# 服务器端Dockerfile
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY src/ .
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux go build -o server ./server
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/server .
COPY config.yaml .
EXPOSE 8080 9000
CMD ["./server", "-config", "config.yaml"]
Docker Compose配置
version: '3.8'
services:
go-tunnel-server:
build: .
ports:
- "8080:8080" # API端口
- "9000:9000" # 隧道端口
- "10000-10100:10000-10100" # 转发端口范围
volumes:
- ./config.yaml:/root/config.yaml
- ./data:/root/data
environment:
- GO_ENV=production
restart: unless-stopped
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
安全建议
安全架构
graph TB
subgraph "安全层次"
Network[网络安全]
Transport[传输安全]
Application[应用安全]
Access[访问控制]
end
subgraph "网络安全"
Firewall[防火墙规则]
VPN[VPN接入]
IPWhitelist[IP白名单]
end
subgraph "传输安全"
TLS[TLS加密]
CertValidation[证书验证]
MTLS[双向TLS]
end
subgraph "应用安全"
Authentication[身份认证]
Authorization[权限控制]
RateLimit[速率限制]
Logging[安全日志]
end
Network --> Firewall
Transport --> TLS
Application --> Authentication
style Network fill:#ffebee
style Transport fill:#e8f5e8
style Application fill:#e3f2fd
1. 网络安全配置
防火墙规则示例
# iptables 规则示例
# 允许API端口(仅内网)
iptables -A INPUT -p tcp --dport 8080 -s 192.168.0.0/16 -j ACCEPT
iptables -A INPUT -p tcp --dport 8080 -j DROP
# 允许隧道端口(公网)
iptables -A INPUT -p tcp --dport 9000 -j ACCEPT
# 允许转发端口范围(公网)
iptables -A INPUT -p tcp --dport 10000:10100 -j ACCEPT
# 默认拒绝
iptables -A INPUT -j DROP
端口安全配置
# config.yaml 安全配置
security:
# API访问控制
api:
enable_auth: true
allowed_ips:
- "192.168.1.0/24"
- "10.0.0.0/8"
# 隧道安全
tunnel:
enable_tls: true
cert_file: "/etc/ssl/server.crt"
key_file: "/etc/ssl/server.key"
client_ca: "/etc/ssl/ca.crt"
# 端口范围限制
port_range:
blacklist:
- 22 # SSH
- 3389 # RDP
- 5432 # PostgreSQL
2. 传输安全
TLS配置示例
// 服务器端TLS配置
func createTLSConfig() *tls.Config {
cert, err := tls.LoadX509KeyPair("server.crt", "server.key")
if err != nil {
log.Fatal(err)
}
caCert, err := ioutil.ReadFile("ca.crt")
if err != nil {
log.Fatal(err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
return &tls.Config{
Certificates: []tls.Certificate{cert},
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: caCertPool,
MinVersion: tls.VersionTLS12,
}
}
3. 访问控制
JWT认证示例
// API认证中间件
func authMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
if token == "" {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
// 验证JWT token
if !validateJWT(token) {
http.Error(w, "Invalid token", http.StatusUnauthorized)
return
}
next(w, r)
}
}
4. 监控和审计
安全事件监控
# 监控脚本示例
#!/bin/bash
# 监控异常连接
netstat -an | grep :9000 | wc -l > /var/log/tunnel-connections.log
# 监控失败的认证尝试
grep "Unauthorized" /var/log/go-tunnel/server.log | tail -10
# 监控端口扫描
iptables -L -n -v | grep DROP
5. 生产环境清单
部署前检查清单
-
网络配置
- 防火墙规则配置正确
- 端口范围合理设置
- DNS解析正确
-
安全配置
- TLS证书有效
- 认证机制启用
- 访问控制列表配置
-
性能配置
- 缓冲区大小优化
- 连接池配置合理
- 资源限制设置
-
监控配置
- 日志记录正常
- 监控指标收集
- 告警规则配置
-
备份和恢复
- 数据库定期备份
- 配置文件备份
- 恢复流程测试
故障排查指南
常见问题诊断流程
flowchart TD
Problem[问题发生] --> Identify{问题识别}
Identify -->|连接问题| ConnIssue[连接问题]
Identify -->|性能问题| PerfIssue[性能问题]
Identify -->|隧道问题| TunnelIssue[隧道问题]
ConnIssue --> CheckPort{检查端口}
CheckPort -->|端口被占用| PortSolution[更换端口或停止占用进程]
CheckPort -->|端口超范围| RangeSolution[调整端口范围配置]
CheckPort -->|防火墙| FirewallSolution[配置防火墙规则]
PerfIssue --> CheckResource{检查资源}
CheckResource -->|CPU高| CPUSolution[优化算法或增加服务器]
CheckResource -->|内存高| MemSolution[调整缓冲区或检查内存泄漏]
CheckResource -->|网络慢| NetSolution[检查网络质量]
TunnelIssue --> CheckTunnel{检查隧道}
CheckTunnel -->|连接断开| ReconnectSolution[自动重连机制]
CheckTunnel -->|认证失败| AuthSolution[检查服务器地址和端口]
CheckTunnel -->|协议错误| ProtocolSolution[检查版本兼容性]
style Problem fill:#ffebee
style ConnIssue fill:#fff3e0
style PerfIssue fill:#e3f2fd
style TunnelIssue fill:#f3e5f5
问题分类与解决方案
🔌 连接类问题
问题 1: 端口映射创建失败
# 诊断命令
netstat -tlnp | grep :10001
lsof -i :10001
# 解决方案
1. 检查端口是否被占用
2. 确认端口在配置范围内
3. 检查权限(1024以下端口需要root权限)
问题 2: 外部客户端无法连接
# 诊断命令
telnet server_ip 10001
nmap -p 10001 server_ip
# 解决方案
1. 检查防火墙设置
2. 确认服务器监听正确的接口
3. 验证端口映射是否正确创建
🚀 性能类问题
问题 3: 数据传输缓慢
graph LR
SlowTransfer[传输缓慢] --> CheckNetwork{网络检查}
CheckNetwork -->|延迟高| Latency[网络延迟问题]
CheckNetwork -->|带宽低| Bandwidth[带宽限制]
CheckNetwork -->|正常| ConfigCheck[配置检查]
ConfigCheck --> BufferSize[调整缓冲区大小]
ConfigCheck --> ConcurrencyLimit[检查并发限制]
Latency --> OptimizeRoute[优化网络路由]
Bandwidth --> UpgradeBandwidth[升级带宽]
style SlowTransfer fill:#ffebee
style Latency fill:#fff3e0
style Bandwidth fill:#e3f2fd
调优建议:
// 调整缓冲区大小
const BufferSize = 64 * 1024 // 64KB for high throughput
// 调整TCP参数
conn.(*net.TCPConn).SetNoDelay(true)
conn.(*net.TCPConn).SetKeepAlive(true)
🔗 隧道类问题
问题 4: 隧道连接不稳定
诊断步骤:
# 1. 检查隧道服务器状态
curl http://server:8080/health
# 2. 检查网络连通性
ping server_ip
traceroute server_ip
# 3. 检查客户端日志
./client -server server:9000 -debug
解决方案:
- 配置更短的心跳间隔
- 增加重连重试次数
- 使用更稳定的网络连接
日志分析
日志级别说明
graph LR
subgraph "日志级别"
Debug[DEBUG] --> Info[INFO]
Info --> Warn[WARN]
Warn --> Error[ERROR]
Error --> Fatal[FATAL]
end
subgraph "内容说明"
Debug --> DebugContent[详细调试信息]
Info --> InfoContent[一般运行信息]
Warn --> WarnContent[警告信息]
Error --> ErrorContent[错误信息]
Fatal --> FatalContent[致命错误]
end
style Debug fill:#e8f5e8
style Warn fill:#fff3e0
style Error fill:#ffebee
style Fatal fill:#ffcdd2
关键日志模式
# 隧道连接日志
grep "隧道客户端已连接" server.log
grep "隧道客户端已断开" server.log
# 端口映射日志
grep "端口转发启动" server.log
grep "端口转发已停止" server.log
# 错误日志
grep "ERROR\|FATAL" server.log
# 性能日志
grep "连接建立\|连接关闭" server.log | wc -l
监控设置
Prometheus指标示例
# prometheus.yml 配置示例
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'go-tunnel'
static_configs:
- targets: ['localhost:8080']
metrics_path: '/metrics'
scrape_interval: 5s
告警规则示例
groups:
- name: go-tunnel
rules:
- alert: TunnelDisconnected
expr: tunnel_connected == 0
for: 30s
labels:
severity: critical
annotations:
summary: "隧道连接断开"
- alert: HighConnectionCount
expr: active_connections > 1000
for: 1m
labels:
severity: warning
annotations:
summary: "连接数过高"
开发和贡献
开发环境设置
# 克隆项目
git clone <repository-url>
cd go-tunnel/src
# 安装开发依赖
go mod download
go install golang.org/x/tools/cmd/goimports@latest
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
# 代码格式化
goimports -w .
golangci-lint run
编译选项
# 开发编译
make dev
# 生产编译
make release
# 交叉编译
make cross-compile
# 具体平台编译
GOOS=linux GOARCH=amd64 go build -o server-linux ./server
GOOS=windows GOARCH=amd64 go build -o server.exe ./server
GOOS=darwin GOARCH=amd64 go build -o server-mac ./server
测试套件
# 运行所有测试
make test
# 运行单元测试
go test ./... -v
# 运行集成测试
go test ./test -v
# 运行基准测试
go test -bench=. ./...
# 测试覆盖率
go test -cover ./...
代码贡献指南
- 分支策略: 使用 Git Flow 工作流
- 提交规范: 遵循 Conventional Commits
- 代码审查: 所有PR需要代码审查
- 测试要求: 新功能需要对应测试
版本更新日志
v2.0.0 (2025-10-14) - 重大更新
🚀 新增特性
- 重新设计隧道协议: 采用自定义应用层协议
| 版本(1B) | 类型(1B) | 长度(4B) | 数据 | - 透明代理机制: 隧道对外部完全不可见,实现真正的透明转发
- 多路复用支持: 单个隧道连接支持多个并发TCP会话
- 连接生命周期管理: 实现连接请求/响应/数据/关闭的完整流程
- 心跳保活机制: 自动检测和维护隧道连接状态
🔧 技术改进
- 协议版本控制: 支持协议版本检查和兼容性处理
- 错误处理优化: 完善的错误边界和异常恢复机制
- 性能优化: 优化缓冲区管理和并发控制
- 测试覆盖: 全面的单元测试和集成测试
📋 协议消息类型
0x01- 连接请求 (ConnectRequest)0x02- 连接响应 (ConnectResponse)0x03- 数据传输 (Data)0x04- 关闭连接 (Close)0x05- 心跳保活 (KeepAlive)
🛠️ 重构组件
- 服务器端:
server/tunnel/tunnel.go- 完全重写 - 客户端:
client/tunnel/client.go- 完全重写 - 测试套件: 新增协议测试和性能测试
v1.0.0 (2024-01-01) - 初始版本
✨ 基础功能
- 端口转发功能
- 基础内网穿透
- HTTP API 管理
- SQLite 持久化存储
- 自动重连机制
技术规范
协议兼容性
| 版本 | 协议格式 | 兼容性 | 状态 |
|---|---|---|---|
| v2.0+ | 版本+类型+长度+数据 |
向后兼容 | 当前 |
| v1.x | 长度+连接ID+数据 |
已弃用 | 不推荐 |
性能基准
在标准测试环境下的性能指标:
| 指标 | 数值 | 说明 |
|---|---|---|
| 并发连接数 | 10,000+ | 单服务器实例 |
| 吞吐量 | 1GB/s | 千兆网络环境 |
| 延迟增加 | <5ms | 相比直连的额外延迟 |
| 内存使用 | <100MB | 1000个活跃连接 |
| CPU使用 | <30% | 单核,高负载场景 |
系统要求
最低要求
- 操作系统: Linux/macOS/Windows
- Go版本: 1.19+
- 内存: 128MB
- CPU: 单核
- 网络: 10Mbps
推荐配置
- 操作系统: Linux (Ubuntu 20.04+/CentOS 8+)
- Go版本: 1.21+
- 内存: 512MB+
- CPU: 双核+
- 网络: 100Mbps+
- 存储: SSD
许可证
MIT License - 详见 LICENSE 文件
社区和支持
- 文档: 本README和代码注释
- 问题反馈: GitHub Issues
- 功能请求: GitHub Discussions
- 安全问题: 请私密联系维护者
致谢
感谢所有为这个项目做出贡献的开发者和用户。
Go-Tunnel - 高性能、生产就绪的TCP端口转发和内网穿透解决方案