mirror of
https://github.com/MikeWang000000/n4.git
synced 2024-08-16 14:27:54 +00:00
147 lines
5.0 KiB
Markdown
147 lines
5.0 KiB
Markdown
# N4
|
||
|
||
N4 是针对双方均为 “端口递增型 NAT” 的一种打洞测试工具。
|
||
|
||
> “端口递增型 NAT” 不限制 NAT 种类。
|
||
> 也就是说,即使双方均为对称型 NAT(NAT4 - NAT4),只要满足端口递增,也可使用此工具成功打通。
|
||
|
||
|
||
## 快速开始
|
||
公网服务器运行:
|
||
```bash
|
||
python3 n4.py -s
|
||
```
|
||
|
||
需要打洞的两个 NAT4 客户端运行:
|
||
```bash
|
||
python3 n4.py -c -h 服务器IP
|
||
```
|
||
|
||
客户端日志显示:
|
||
|
||
```
|
||
[2024-06-01 12:38:56,438] INFO [n4.py:375] ==================
|
||
[2024-06-01 12:38:56,439] INFO [n4.py:376] Source port: 30000-30025
|
||
[2024-06-01 12:38:56,459] INFO [n4.py:287] <= Hello
|
||
[2024-06-01 12:38:56,471] INFO [n4.py:293] => Ready
|
||
[2024-06-01 12:38:56,472] INFO [n4.py:302] <= Exchange
|
||
[2024-06-01 12:38:56,486] INFO [n4.py:312] => Peer: 203.0.113.12:5793
|
||
[2024-06-01 12:38:56,486] INFO [n4.py:313] [ Target: 203.0.113.12:5813 ]
|
||
[2024-06-01 12:38:56,487] INFO [n4.py:321] <= Punch
|
||
[2024-06-01 12:39:06,498] INFO [n4.py:386] [ LOSE ]
|
||
[2024-06-01 12:39:06,500] INFO [n4.py:375] ==================
|
||
[2024-06-01 12:39:06,500] INFO [n4.py:376] Source port: 30025-30050
|
||
[2024-06-01 12:39:06,514] INFO [n4.py:287] <= Hello
|
||
[2024-06-01 12:39:06,526] INFO [n4.py:293] => Ready
|
||
[2024-06-01 12:39:06,527] INFO [n4.py:302] <= Exchange
|
||
[2024-06-01 12:39:06,541] INFO [n4.py:312] => Peer: 203.0.113.12:5434
|
||
[2024-06-01 12:39:06,541] INFO [n4.py:313] [ Target: 203.0.113.12:5454 ]
|
||
[2024-06-01 12:39:06,542] INFO [n4.py:321] <= Punch
|
||
[2024-06-01 12:39:06,556] INFO [n4.py:334] => Punch from peer
|
||
[2024-06-01 12:39:08,559] INFO [n4.py:342] <= Punch
|
||
[2024-06-01 12:39:08,560] INFO [n4.py:379] ------
|
||
[2024-06-01 12:39:08,560] INFO [n4.py:380] Local port: 30040
|
||
[2024-06-01 12:39:08,560] INFO [n4.py:381] Peer address: 203.0.113.12:5454
|
||
[2024-06-01 12:39:08,560] INFO [n4.py:382] ------
|
||
[2024-06-01 12:39:08,560] INFO [n4.py:383] [ WIN ]
|
||
[2024-06-01 12:39:08,560] INFO [n4.py:385] > nc -u -p 30040 203.0.113.12 5454
|
||
```
|
||
|
||
日志出现 `[ WIN ]` 字样,表示两者打通。
|
||
|
||
双方运行日志中提示的 `nc` 命令,即可互相进行 P2P 通信。
|
||
|
||
|
||
## 打洞过程
|
||
|
||
服务端监听 `TCP/1721` 和 `UDP/1721`。
|
||
|
||
- TCP 端口用于与客户端通信;
|
||
- UDP 端口仅用于获取客户端公网上的IP、端口信息,只接收不发送。
|
||
|
||
打洞过程共有 5 步:
|
||
```
|
||
1. Hello client --TCP-> server
|
||
2. Ready client <-TCP-- server
|
||
3. Exchange client --UDP-> server
|
||
4. Peerinfo client <-TCP-- server
|
||
5. Punch client <-UDP-> client
|
||
```
|
||
|
||
解释说明:
|
||
|
||
1. 客户端向服务端发送 Hello 包;
|
||
2. 服务端收到两个客户端的 Hello 包后,同时向两方发送 Ready 包;
|
||
3. 客户端收到 Ready 包,使用 UDP 向服务器发送 Exchange 包,表示交换两客户端 UDP 公网信息;
|
||
4. 服务端收到一客户端的 Exchange 包,向另一客户端发送 Peerinfo 包,携带前者 UDP 公网信息;
|
||
5. 客户端收到 Peerinfo 包,根据对方地址 `IP:PORT`,
|
||
预测对方将来的地址会有 `IP:PORT + peer_port_offset`。
|
||
客户端从自身端口 `src_port_start` ~ `src_port_start + src_port_count` 范围,
|
||
使用 UDP 逐一向 `IP:PORT + peer_port_offset` 固定地址发送 Punch 包。
|
||
|
||
如果客户端收到 Punch 包,代表打通。否则,增加源端口值,再次尝试。
|
||
|
||
|
||
## 示例说明
|
||
|
||
下面是一个示例,假设有以下设定值。
|
||
|
||
```
|
||
src_port_start = 30000
|
||
src_port_count = 8
|
||
peer_port_offset = 5
|
||
```
|
||
|
||
括号内为 NAT 转换后的地址。该地址只对目标可见,对来源不可见。
|
||
|
||
客户端A:
|
||
|
||
```
|
||
---(Exchange)---
|
||
192.168.1.101:30000 --> (198.51.100.3:1801) --> 192.0.2.2:1721
|
||
----(Punch)-----
|
||
192.168.1.101:30000 --> (198.51.100.3:1803) --> 203.0.113.12:3028
|
||
192.168.1.101:30001 --> (198.51.100.3:1804) --> 203.0.113.12:3028
|
||
192.168.1.101:30002 --> (198.51.100.3:1807) --> 203.0.113.12:3028
|
||
192.168.1.101:30003 --> (198.51.100.3:1806) --> 203.0.113.12:3028 [*]
|
||
192.168.1.101:30004 --> (198.51.100.3:1810) --> 203.0.113.12:3028
|
||
192.168.1.101:30005 --> (198.51.100.3:1812) --> 203.0.113.12:3028
|
||
192.168.1.101:30006 --> (198.51.100.3:1817) --> 203.0.113.12:3028
|
||
192.168.1.101:30007 --> (198.51.100.3:1814) --> 203.0.113.12:3028
|
||
```
|
||
|
||
客户端B:
|
||
|
||
```
|
||
---(Exchange)---
|
||
192.168.0.112:30000 --> (203.0.113.19:3023) --> 192.0.2.2:1721
|
||
----(Punch)-----
|
||
192.168.0.112:30000 --> (203.0.113.12:3025) --> 198.51.100.3:1806
|
||
192.168.0.112:30001 --> (203.0.113.12:3029) --> 198.51.100.3:1806
|
||
192.168.0.112:30002 --> (203.0.113.12:2030) --> 198.51.100.3:1806
|
||
192.168.0.112:30003 --> (203.0.113.12:3031) --> 198.51.100.3:1806
|
||
192.168.0.112:30004 --> (203.0.113.12:3028) --> 198.51.100.3:1806 [*]
|
||
192.168.0.112:30005 --> (203.0.113.12:3032) --> 198.51.100.3:1806
|
||
192.168.0.112:30006 --> (203.0.113.12:3033) --> 198.51.100.3:1806
|
||
192.168.0.112:30007 --> (203.0.113.12:3034) --> 198.51.100.3:1806
|
||
```
|
||
|
||
在以上打洞组合中,`[*]` 标记的一对尝试,成功打通。
|
||
|
||
客户端 A 运行:
|
||
```
|
||
nc -u -l 30003
|
||
```
|
||
|
||
客户端 B 运行:
|
||
```
|
||
nc -u -p 30004 198.51.100.3 1806
|
||
```
|
||
|
||
两者即可 P2P 通信。
|
||
|
||
|
||
## License
|
||
|
||
GNU General Public License v3.0
|