P2P网络中内网穿越方法总结(2019)
- 内网穿越的需求
- 问题分析
- 方案一
- 方案二
- 方案三
内网穿越的需求
今天去图书馆搜资料查了一下,这个问题很老,但是解决办法很久都没有更新过了,还得翻翻书。网上的帖子众说纷纭,看得人云里雾里,这里总结一下以后备查。
是关于一个局域网和外网之间连接的问题:
一分钟实现内网穿透:https://blog.csdn.net/zhangguo5/article/details/77848658
问题分析
首先问题的关键在于:
由于动态NAPT的映射关系是LAN侧数据包来触发的,如果WAN侧有主动进来的数据包,因为查询不到映射关系的存在,就会被丢弃掉。所以这时需要内网穿透。
方案一
理念是构建一个公网中的服务端,两个内网中的客户端都相当于向该服务器注册,然后发送三次握手,可互相发现,实现NAT穿透。
Python写的比较常用的实现TCP内网穿透的服务器是ShootBack:
ShootBack:https://github.com/aploium/shootback
方案二
一个比较简单的方式是:端口映射(Port Mapping或者叫Port Forwarding),也是最基本的一种方式。
它将NAPT网关WAN侧的指定端口映射到内网指定地址的指定端口上。 这样当网关收到一个从外网过来的封包,就会转发到上述指定的内网地址和端口,对于封包的发起者来说,就像是直接访问这个内网主机一样。
且当内网的地址和端口都希望是动态的时候就需要“动态端口映射”,也就是UPnP里面的IGD(Internet Gateway Device)控制协议。
这种方式下的情形就是: 把节点连接在某个UPnP分配的节点上,然后外部直接来连接这个端口。
现在了解到的python下分离并加强这种分配端口方法的的包就是miniUpnp,还有待于了解;
但这种方法存在的问题:
——使用UPNP穿透NAT的方法会使得机器不安全,极其容易卡死路由器和其他问题;
——最初是为各种设备,后来发展为一般都是为电驴等软件配置某一个外部端口的时候开启,而自己写的某种程序能否做到端口映射问题很大,且开源多基于C;
——这种方法受到不同网络状况和设备的影响很大;
——多用于家庭内的树莓派或者设备连接外部公司里电脑这种情况;
关于UPnP和NAPT的解释:
https://www.zhihu.com/question/52383627/answer/130588578
主要用到的是其中IGD这个协议。
方案三
STUN协议和TURN协议
STUN(Simple Traversal of UDP over NATs,NAT 的UDP简单穿越)是一种网络协议,它允许位于NAT(或多重NAT)后的客户端找出自己的公网地址,查出自己位于哪种类型的NAT之后以及NAT为某一 个本地端口所绑定的Internet端端口。这些信息被用来在两个同时处于NAT路由器之后的主机之间建立UDP通信。
如图,在N层NAT后面的client向Server询问自己的外网IP和端口号,然后直接用于连接,这样就可以直接使用外部端口和IP,避免使用私网IP和端口无法被访问的问题。
网上开源项目也很多:
显然pystun支持的是python2.7之前的版本,现在版本需要的是pynat。
pynat:https://github.com/arantonitis/pynat
这里附上书上的描述: