Files
stun-NAT/README.md
2026-07-16 15:07:12 +08:00

98 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# STUNMap Console
独立的 NAT1 STUN 内网穿透管理系统,按 Lucky 的 STUN 模块工作方式实现:在一台设备上维持 TCP 或 UDP 的 NAT 映射,获得动态公网端口,再将流量转发到指定内网服务,或交由路由器直转。
它不是双节点 P2P 打洞系统,也不提供中继服务。映射是否可用取决于运营商和每一层 NAT 是否为 NAT1(全锥形)。公网端口不可指定,变化周期也无法保证。
## 功能
- Web 管理页面、HTTP Basic Auth 和规则 REST API。
- 多条 IPv4 TCP / UDP 穿透规则。
- 通道监听端口支持固定值或 `0` 随机分配。
- TCP 使用同源端口保活连接和 STUN TCP 探测;UDP 持续保活并周期性探测。
- Lucky 内置转发模式:TCP/UDP 流量转发到 `目标地址:目标端口`。
- bind 直转模式:只建立 NAT 映射;由路由器端口转发直接指向目标设备,可保留真实访问者 IP。
- NAT-PMP 与 UPnP IGD 自动上级路由映射。
- Linux `iptables` 自动放行通道端口(每条规则可选)。
- 每条规则保存动态公网地址、端口、IP4P 地址、本地端口、运行状态和日志。
- 支持将状态文件用于 DDNS:`data/state/<规则 ID>.json`。
- 默认每 10 秒进行一次 STUN/保活心跳;连续缺失心跳会自动重建映射。
- 可选独立公网探针:TCP 验证通道握手,UDP 验证映射引擎健康回显;两者均不依赖目标服务是否启动。
- 映射成功或公网端点变化后,可调用指定 GET 或 POST Webhook;保活心跳不会重复触发。
映射核心使用 [NATMap](https://github.com/heiher/natmap) 的 MIT 许可实现,管理服务、规则存储、路由映射适配和界面为本项目独立编写。
## 部署
此类程序必须运行在需要暴露服务的主路由或内网设备上,Docker 必须使用宿主机网络;容器 NAT 网络会破坏端口映射。
`network_mode: host` 面向 Linux 主机/路由器。Docker Desktop(macOS/Windows)会将 host 网络指向其 Linux VM,管理端口和 NAT 映射均不等同于桌面宿主机;可用于构建验证,但不能替代在目标 Linux 路由设备上的部署。
```sh
export STUNMAP_ADMIN_USER=admin
export STUNMAP_ADMIN_PASSWORD='use-a-long-random-password'
docker compose up -d --build
```
访问 `http://设备地址:16888`,使用上面的账号密码登录。
首次建议创建一条 TCP 内置转发规则:
| 字段 | 示例 |
| --- | --- |
| 穿透类型 | `IPv4 TCP` |
| 通道监听端口 | `0`(随机)或未被占用的高端口 |
| STUN 服务器 | `turn.cloudflare.com:3478` |
| TCP 保活服务器 | `www.cloudflare.com:80` |
| 转发模式 | `Lucky 内置转发` |
| 目标地址 / 端口 | `192.168.1.20` / `443` |
运行后页面会显示 `公网映射 IP:端口`。该端口可能变化,应通过状态文件或后续 DDNS 集成同步域名记录。
## 公网可达性探针
STUN 成功证明映射已建立,但不能单独证明外部入站数据包当前仍可到达。需要严格验证时,将探针部署在与家庭网络不同的公网 VPS:
```sh
export STUNMAP_PROBE_TOKEN='use-a-long-random-token'
docker compose -f docker-compose.probe.yml up -d --build
```
在穿透规则的“定制模式”填写:
```text
公网探针地址: http://<VPS IPv4>:16900/probe
公网探针令牌: 与 STUNMAP_PROBE_TOKEN 相同
公网探针间隔: 10
```
探针不会访问目标内网服务。TCP 只验证公网端口的三次握手;UDP 发送 `SMHP:` 健康报文,映射引擎在转发前原样回显。因此即使 `targetHost:targetPort` 尚未启动,健康结果仍可正确反映 NAT 通道状态。探针连续两次失败时,规则会立即重建映射。
## 映射 Webhook
在规则“定制模式”设置 Webhook 地址和方法。首次获取映射、或 STUN 地址/端口变化时会触发一次;每次正常心跳不会重复调用。Webhook 地址和 POST JSON 模板均可使用变量,写法支持 `{{STUN_PUBLIC_IP}}`、`${STUN_PUBLIC_IP}` 或 `{STUN_PUBLIC_IP}`。
- `POST`:可填写 JSON 模板;为空时发送默认 JSON,包含 `event`、规则信息、STUN 映射、本地通道和路由器映射状态。示例:`{"ip":"{{STUN_PUBLIC_IP}}","port":{{STUN_PUBLIC_PORT}},"address":"{{STUN_PUBLIC_ADDR}}"}`。
- `GET`:URL 中可直接使用变量,并自动补充 `event`、`rule_id`、`rule_name`、`protocol`、`public_address`、`public_port`、`private_address`、`private_port`、`ip4p` 查询参数;URL 中已明确提供的同名参数不会被覆盖。
变量列表:`STUN_PUBLIC_IP`、`STUN_PUBLIC_PORT`、`STUN_PUBLIC_ADDR`、`STUN_PRIVATE_IP`、`STUN_PRIVATE_PORT`、`STUN_PRIVATE_ADDR`、`STUN_IP4P`、`STUN_PROTOCOL`、`STUN_RULE_ID`、`STUN_RULE_NAME`、`STUN_ROUTER_IP`、`STUN_ROUTER_PORT`。JSON 模板中字符串变量应放在双引号内;端口变量可直接作为数值填写。
## 环境要求
1. 光猫拨号时,光猫 DMZ 应指向主路由。
2. 优先在主路由运行。若运行在局域网设备,可启用 NAT-PMP 或 UPnP,或手动将通道监听端口转发到该设备。
3. 放行设备防火墙上的通道监听端口。
4. UDP 规则不支持 bind 直转,必须使用内置转发。
5. TCP bind 直转须在路由器上将通道监听端口转发到目标设备/端口。
## 本地开发与验证
无需安装 npm 依赖:
```sh
STUNMAP_ADMIN_PASSWORD=dev-password npm test
STUNMAP_ADMIN_PASSWORD=dev-password NATMAP_BIN=/path/to/natmap npm start
```
测试覆盖认证、规则校验、创建和删除。真实 NAT 映射测试必须在 NAT1 网络中进行,不能以本机回环结果代替。