evilpan / P2P-Over-MiddleBoxes-Demo

A simple demo of P2P communication over middle boxes such as NAT
437 stars 212 forks source link

服务端C外网运行,客户端A内网虚机机运行,客户端B远程控制家里机器运行。A向B发送消息成功,B向A发送消息不成功。 #3

Open andy-da opened 6 years ago

andy-da commented 6 years ago

打洞成功后,客户端A向B发消息成功,客户端B向A发消息不成功。 测试环境,服务端C在公网上,客户端A在机器1虚拟机下运行,客户端B远程控制机器2运行。

holepunch holepunch_ a b _b a

evilpan commented 6 years ago

看样子是59.63.3.220这个端点没有在cone NAT之后,企业ISP可能是symmetric NAT, 可以用tools下的udp_serverudp_client按照README验证一下.

andy-da commented 6 years ago

又试了一次,客户端A(58.63.3.220:3902)可以向客户端B(59.41.161.145:20707)发送消息,客户端B(59.41.161.145:20707/19459/19875)向客户端A发送消息不通,客户端B(59.41.161.145)的端口号分别显示为19459、19875、20707,显示了三个不同端口号?

用tools下的udp_server和udp_client按照README验证了一下。如图,两个端点都是Cone Nat?

test_nat b _a b _b a 1

andy-da commented 6 years ago

nat_type_restrict_nat 用另一程序测了一下,显示nat_type=Restrict NAT

evilpan commented 6 years ago

从上面的截图得到的结论是, 外部IP为58.63.3.220的NAT为Cone NAT, 外部IP为59.41.161.145的NAT为Symmetric NAT. NAT对UDP维护的映射时间一般在10秒到几分钟, 应用程序只是一个POC, 暂时还没做keepalive, 这也可能导致两次显示的源端口不一致的.

evilpan commented 6 years ago

@andy-da Hi andy, 我新添加了一个python脚本, 基于classic STUN协议来精确检测NAT类型, 见https://github.com/pannzh/P2P-Over-MiddleBoxes-Demo/tree/master/stun.

andy-da commented 6 years ago

INFO:root:running test I with stun.voipbuster.com:3478 INFO:root:local address is 0.0.0.0:46520 INFO:root:MAPPED_ADDRESS: 58.63.0.101:17130 INFO:root:running test II with stun.voipbuster.com:3478 INFO:root:running test I with 77.72.169.210:3479 INFO:root:MAPPED_ADDRESS: 58.63.0.101:17130 INFO:root:running test III with stun.voipbuster.com:3478 NAT_TYPE: (Address) Rristrict Cone NAT 测到外部IP 58.63.0.101是 Cone NAT类型

p2p_update_cannot_login @pannzh 代码更新后,client端怎样login到server端?

evilpan commented 6 years ago

外网测试要指定local address, 因为自动获取的是0.0.0.0所以不匹配就走到下面流程了; 新的客户端简化了操作流程, 启动时就指定server地址, login/logout/list 不需要带参数了

evilpan commented 6 years ago

如果不确定自己是否是在NAT之后, 可以指定网络接口的本地地址运行, 如:

stun/classic_stun_client.py 58.63.0.101

应该就能获得正确的结果了.

andy-da commented 6 years ago

p2p_punch

外网121.199.46.119机器上运行服务端 $./p2pchat/server 10088 内网机器启动客户端后,输入login,list不带参数,没有任何提示?

evilpan commented 6 years ago

client 启动参数是 server:port, 对于你的地址是

client 121.199.46.119:10088
andy-da commented 6 years ago
udp_holepunch_nat_success4

服务端C运行在公网:IP 121.199.46.119 客户端A运行在内网:IP 192.168.1.173 -> 外部IP 58.63.3.111 的NAT为Rristrict Cone NAT 客户端B运行在外网:IP 192.168.1.11 -> 外部IP 59.41.162.249的NAT为Symmetric NAT UDP打洞成功后,A、B可互发消息而不需要经过C。


TCP打洞比UDP打洞难实现吗?看你写的文章里提到相对于UDP成功率较低。 TCP打洞需要操作系统所支持的SO_REUSEADDR或者SO_REUSEPORT之类的socket选项将客户端和服务器绑定到同一个端口? 理解不深,具体还不知道怎样实现。

evilpan commented 6 years ago

TCP打洞和UDP类似,难点在于TCP建立连接要三次握手,但握手的过程通常是操作系统控制的,比如一个connect系统调用。要想三次握手能按顺序正确到达并且被对方收到,要比较精确地控制每个TCP包(SYN/ACK/SYNACK),新版的STUN协议(RFC5389), 以及ICE协议(RFC5245)有对TCP打洞的相关介绍,你可以参阅一下。