299 lines
10 KiB
Markdown
299 lines
10 KiB
Markdown
# INP2P
|
||
|
||
自研 P2P 隧道组网系统。两个二进制,零依赖部署。
|
||
|
||
```
|
||
inp2ps — 信令服务器(STUN + WebSocket + REST API)
|
||
inp2pc — 客户端(NAT 探测 + 打洞 + 中继 + 端口转发)
|
||
```
|
||
|
||
## 为什么造这个
|
||
|
||
试过 OpenP2P、FRP、ZeroTier,各有各的问题。OpenP2P 最接近需求,但踩了一堆坑:
|
||
|
||
- `MsgReportBasic` 不回响应 → 客户端反复断连
|
||
- Push 消息白名单太窄 → 操作被拒绝
|
||
- TOTP relay 认证链过于复杂 → Access Denied
|
||
- `peerNatType=314` 跳过所有打洞 → 只走 relay
|
||
- 中继节点选择单一,没有分层概念
|
||
|
||
INP2P 从协议层重新设计,解决以上所有问题。
|
||
|
||
## 特性
|
||
|
||
- **连接优先级**:UDP 直连 → UDP 打洞 → TCP 直连 → TCP 打洞 → 私有中继 → 超级中继 → 服务器中继
|
||
- **流多路复用**:一条 P2P 连接承载多个隧道,7 字节帧头(StreamID + Flags + Length)
|
||
- **分层中继**:任意客户端可选开启 `--relay` / `--super`,自动参与中继
|
||
- **TOTP 认证**:CRC64 token + 时间窗口验证,跨用户场景用 HMAC-SHA256 一次性令牌
|
||
- **NAT 探测**:内置 STUN 服务端(UDP×2 + TCP×2),客户端自动探测 NAT 类型
|
||
- **断线重连**:5 秒退避自动重连,节点上线广播触发隧道重建
|
||
- **静态编译**:零 CGO 依赖,单二进制部署
|
||
|
||
## 快速开始
|
||
|
||
### 编译
|
||
|
||
```bash
|
||
git clone https://gitea.king.nyc.mn/openclaw/inp2p.git
|
||
cd inp2p
|
||
```
|
||
|
||
生产部署(静态编译,避免 glibc 版本问题):
|
||
|
||
```bash
|
||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w -extldflags=-static" -o bin/inp2ps ./cmd/inp2ps/
|
||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w -extldflags=-static" -o bin/inp2pc ./cmd/inp2pc/
|
||
```
|
||
|
||
### 启动服务器
|
||
|
||
```bash
|
||
# 生成 token
|
||
# token 是 CRC64(user + password) 的结果,客户端和服务端必须一致
|
||
./bin/inp2ps -token 12345678 \
|
||
-ws-port 27183 \
|
||
-stun-udp1 27182 -stun-udp2 27183 \
|
||
-stun-tcp1 27180 -stun-tcp2 27181
|
||
```
|
||
|
||
健康检查:
|
||
|
||
```bash
|
||
curl http://localhost:27183/api/v1/health
|
||
# {"status":"ok","version":"0.1.0","nodes":0}
|
||
```
|
||
|
||
### 启动客户端
|
||
|
||
节点 A(开启中继能力):
|
||
|
||
```bash
|
||
./bin/inp2pc \
|
||
-serverhost your-server.com \
|
||
-serverport 27183 \
|
||
-node nodeA \
|
||
-token 12345678 \
|
||
-relay \
|
||
-config config.json \
|
||
-newconfig
|
||
```
|
||
|
||
节点 B:
|
||
|
||
```bash
|
||
./bin/inp2pc \
|
||
-serverhost your-server.com \
|
||
-serverport 27183 \
|
||
-node nodeB \
|
||
-token 12345678 \
|
||
-config config.json \
|
||
-newconfig
|
||
```
|
||
|
||
### 参数说明
|
||
|
||
#### inp2ps
|
||
|
||
| 参数 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `-token` | 必填 | 认证 token(uint64) |
|
||
| `-ws-port` | 27183 | WebSocket 信令端口 |
|
||
| `-stun-udp1` | 27182 | UDP STUN 端口 1 |
|
||
| `-stun-udp2` | 27183 | UDP STUN 端口 2 |
|
||
| `-stun-tcp1` | 27180 | TCP STUN 端口 1 |
|
||
| `-stun-tcp2` | 27181 | TCP STUN 端口 2 |
|
||
|
||
#### inp2pc
|
||
|
||
| 参数 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `-serverhost` | 必填 | 服务器地址 |
|
||
| `-serverport` | 27183 | 服务器端口 |
|
||
| `-node` | 必填 | 节点名称(唯一标识) |
|
||
| `-token` | 必填 | 认证 token(与服务器一致) |
|
||
| `-insecure` | false | 跳过 TLS 验证(用 ws:// 代替 wss://) |
|
||
| `-relay` | false | 启用中继节点功能 |
|
||
| `-super` | false | 启用超级中继(对所有用户开放) |
|
||
| `-relay-port` | 27185 | 中继监听端口 |
|
||
| `-bw` | 10 | 共享带宽上限(Mbps) |
|
||
| `-config` | config.json | 配置文件路径 |
|
||
| `-newconfig` | false | 忽略已有配置,使用命令行参数 |
|
||
| `-stun-udp1/2` | 同服务器 | STUN 端口(通常与服务器一致) |
|
||
| `-stun-tcp1/2` | 同服务器 | STUN 端口(通常与服务器一致) |
|
||
|
||
## 架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────────┐
|
||
│ inp2ps │
|
||
│ │
|
||
│ ┌─────────┐ ┌──────┐ ┌───────────────┐ │
|
||
│ │ STUN │ │ WSS │ │ Coordinator │ │
|
||
│ │ UDP × 2 │ │Server│ │ (punch sync) │ │
|
||
│ │ TCP × 2 │ │ │ │ │ │
|
||
│ └─────────┘ └──────┘ └───────────────┘ │
|
||
│ │ │
|
||
│ ┌───────┴───────┐ │
|
||
│ │ Node Manager │ │
|
||
│ │ (online/hb) │ │
|
||
│ └───────────────┘ │
|
||
└─────────────────────────────────────────────┘
|
||
▲ WSS ▲ WSS
|
||
│ │
|
||
┌─────────┴──┐ ┌─────┴────────┐
|
||
│ inp2pc │◄──P2P──►│ inp2pc │
|
||
│ nodeA │ punch │ nodeB │
|
||
│ │ /relay │ │
|
||
│ ┌────────┐ │ │ ┌──────────┐ │
|
||
│ │ Tunnel │ │ │ │ Tunnel │ │
|
||
│ │ Mux │ │ │ │ Mux │ │
|
||
│ └────────┘ │ │ └──────────┘ │
|
||
└────────────┘ └──────────────┘
|
||
```
|
||
|
||
### 连接建立流程
|
||
|
||
```
|
||
nodeA inp2ps nodeB
|
||
│ │ │
|
||
│── ConnectReq ─────────►│ │
|
||
│ │── PunchStart ─────────►│
|
||
│◄── PunchStart ─────────│ │
|
||
│ │ │
|
||
│◄═══════ UDP/TCP Punch ═══════════════════════►│
|
||
│ │ │
|
||
│ (if punch fails, fallback to relay) │
|
||
│ │ │
|
||
│── RelayNodeReq ───────►│ │
|
||
│◄── RelayNodeRsp ───────│── PushRelayOffer ────►│
|
||
│ │ │
|
||
│──── RelayHandshake ──►[R]◄── RelayHandshake ───│
|
||
│ [R] bridges A ↔ B │
|
||
│◄═══════════ Mux Stream ═══════════════════════►│
|
||
```
|
||
|
||
### 多路复用帧格式
|
||
|
||
```
|
||
0 4 5 7
|
||
├───────┼────┼───────┤
|
||
│Stream │Flag│Length │ Data...
|
||
│ ID │ s │ │
|
||
└───────┴────┴───────┘
|
||
4B 1B 2B 0~65535B
|
||
|
||
Flags: SYN=0x01 FIN=0x02 DATA=0x04 PING=0x08 PONG=0x10 RST=0x20
|
||
StreamID: 客户端奇数(1,3,5...) 服务端偶数(2,4,6...)
|
||
```
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
inp2p/
|
||
├── cmd/
|
||
│ ├── inp2ps/main.go # 服务器入口
|
||
│ └── inp2pc/main.go # 客户端入口
|
||
├── internal/
|
||
│ ├── server/
|
||
│ │ ├── server.go # WSS 主循环、登录、心跳、节点管理
|
||
│ │ └── coordinator.go # 打洞协调、App 推送
|
||
│ └── client/
|
||
│ └── client.go # NAT 探测、登录、打洞、中继、重连
|
||
├── pkg/
|
||
│ ├── protocol/ # 消息定义、编解码、NAT 类型枚举
|
||
│ ├── config/ # 配置结构体、默认值、环境变量
|
||
│ ├── auth/ # CRC64 token、TOTP、HMAC-SHA256 令牌
|
||
│ ├── nat/ # UDP/TCP STUN 客户端和服务端
|
||
│ ├── signal/ # WebSocket 封装、handler、同步请求
|
||
│ ├── punch/ # UDP/TCP 打洞 + 优先级链
|
||
│ ├── mux/ # 流多路复用(7B 帧头)
|
||
│ ├── tunnel/ # 基于 mux 的端口转发
|
||
│ └── relay/ # 中继管理、TOTP 握手、会话桥接
|
||
├── go.mod
|
||
├── go.sum
|
||
├── TASKS.md # 任务拆分与进度
|
||
└── .gitignore
|
||
```
|
||
|
||
## 测试
|
||
|
||
```bash
|
||
go test ./... -v
|
||
```
|
||
|
||
```
|
||
internal/client PASS 8.3s — NAT + WSS + Login + Report 完整链路
|
||
internal/server PASS 0.8s — 双客户端登录 + Relay 节点发现
|
||
pkg/mux PASS 0.2s — 7 测试:并发/大载荷/FIN/session
|
||
pkg/tunnel PASS 0.16s — 端到端转发 + 5 并发 + 统计
|
||
pkg/relay PASS 0.3s — 双向桥接 + 1MB 中继 + 认证拒绝
|
||
```
|
||
|
||
## 防火墙
|
||
|
||
服务器需要开放以下端口:
|
||
|
||
| 端口 | 协议 | 用途 |
|
||
|------|------|------|
|
||
| 27183 | TCP | WebSocket 信令 |
|
||
| 27182, 27183 | UDP | STUN NAT 探测 |
|
||
| 27180, 27181 | TCP | STUN TCP 回退 |
|
||
|
||
客户端(如果开启 `--relay`):
|
||
|
||
| 端口 | 协议 | 用途 |
|
||
|------|------|------|
|
||
| 27185 | TCP | 中继服务 |
|
||
|
||
## Systemd 部署示例
|
||
|
||
### 服务器
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=INP2P Signaling Server
|
||
After=network.target
|
||
|
||
[Service]
|
||
ExecStart=/usr/local/bin/inp2ps -token YOUR_TOKEN
|
||
Restart=always
|
||
RestartSec=5
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
### 客户端
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=INP2P Client
|
||
After=network.target
|
||
|
||
[Service]
|
||
WorkingDirectory=/usr/local/inp2p
|
||
ExecStart=/usr/local/bin/inp2pc -serverhost your-server.com -node mynode -token YOUR_TOKEN -insecure
|
||
Restart=always
|
||
RestartSec=5
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
## Roadmap
|
||
|
||
- [x] 信令连接 + 认证
|
||
- [x] NAT 探测(UDP/TCP STUN)
|
||
- [x] UDP/TCP 打洞 + 双端协调
|
||
- [x] 流多路复用隧道
|
||
- [x] 中继握手 + TOTP 认证
|
||
- [x] SDWAN 虚拟组网(TUN 网卡 + 虚拟 IP + raw binary 数据面)
|
||
- [ ] Web 控制台
|
||
- [ ] UDP 端口转发
|
||
- [ ] 自动升级
|
||
- [ ] Docker 镜像
|
||
|
||
## License
|
||
|
||
MIT
|