我在没有基本服务器的情况下对p2p通信做了一些研究,并且通过了STUN。从我读过的内容来看,STUN是NAT“打孔”的一种方式,它不需要将对等端口转发连接到。这是正确的,打孔究竟是什么意思?如果它不需要端口转发,它似乎非常脆弱,因为它越过防火墙,我不完全理解STUN的作用。 STUN可以用在Java中的p2p程序或其他语言中,例如聊天客户端,它通过TCP / UDP端口向没有基本服务器的对等端发送消息,或者不要求用户端口转发?
答案 0 :(得分:58)
考虑两台希望相互通信的机器的任务。如果两台机器直接连接到公共互联网(不在路由器后面),那么这两台机器只是相互发送数据包到彼此的公共IP。通常,机器位于一个或多个路由器后面。为简化问题,我们假设只有一级路由器。
NAT遍历解决了路由器将传出端口数量的数据包转换为其他内容的问题(例如,您从端口X发送请求,路由器将数据包转换为从端口Y离开的行为)。如果路由器是端口转发,则路由器实际上不进行任何转换(端口X-> X)。然而,大多数家庭/企业/等路由器不是端口转发,因此NAT遍历发挥作用。请参阅NAT traversal和不同类型的NATs。
考虑路由器的防火墙,该防火墙执行上述文章中的任何非端口转发翻译(例如,完整的锥形)。如果路由器收到一些数据包到端口X,但是路由器没有从端口Y发送任何数据包,它会丢弃数据包(毕竟,数据包意味着谁?路由器不知道!)。只有当某个私有机器发送数据包并且路由器进行转换以将端口X从该专用机器映射到外部端口Y时,外部数据包TO端口Y才会转发到私有机器。
为了让两个客户端A和B都在Internet上的防火墙之后进行直接通信,他们必须知道路由器映射。一般的解决方案是使用STUN服务器来确定它们的端口映射。机器A将端口X的数据包发送到STUN。路由器将端口转换为Y,并且STUN服务器看到这个并响应回A告诉他外部端口是什么。 B做同样的事情。然后,A和B交换他们翻译的端口(通过使用其他一些中央服务器......为简化示例,Skype可能有一个中央登录服务器,A和B告诉Skype服务器他们的端口翻译,Skype分别告诉A和B关于端口映射)。然后,B使用端口Y而不是X向A的公共IP发送数据包。机器A"打孔"它的防火墙,允许它从外部端口Y接收数据包。
你提到安全性:打孔是否会打开网络以防止安全?潜在的......我还没有研究过这个主题,但考虑一个完整的锥形NAT。一旦映射完成,任何外部机器都可以向机器A的路由器发送数据包,A将获取数据包,即使A从未向某些恶意机器Z发送数据包。当然,机器Z必须以某种方式发现映射。一些维基百科的文章,该图仅显示了具有此漏洞的完整锥形NAT,但我不理解它。根据使用打孔的应用程序数量来判断(Skype,xbox live,...),除了路由器防火墙措施之外,网络还会依赖应用程序和系统级防火墙保护。
下面的福特文章简要提到了安全性:"与其名称所暗示的相反,打孔不会损害专用网络的安全性。"似乎网络比路由器防火墙更依赖于系统级防火墙。
任何具有网络库支持的语言(Java,C等),您可以从任意端口发送数据包,可以使用STUN遍历NAT(只要它不是对称NAT等)。通常,一个始终需要一个中央服务器(在本例中为两个:STUN和登录服务器)。使用登录服务器,如Skype示例中所述;一旦两个客户端知道他们的端口映射,他们必须在 p2p通信开始之前以某种方式相互通信(参见chicken or the egg)。但是,一旦A和B知道对方的公共IP和NAT映射,他们就可以直接进行通信。
虽然我无法列出所有NAT遍历警告,但一个重要概念仍然存在:一旦路由器进行了端口映射,它会持续多长时间?假设我连接到STUN服务器,然后等待10分钟让B向我发送一个数据包,一旦我告诉它映射。路由器可能已经放弃了映射(路由器必须定期清除旧映射以便为新映射腾出空间,并且最小化安全性尝试)。我无法找到我的参考,我认为它会因TCP和UDP数据包而异,但我熟悉的应用程序每隔约60秒或更短时间发送一个保活包,以确保路由器不会掉线映射。一旦路由器丢弃了映射并且机器试图发送数据包,数据包将被丢弃(导致数小时的混乱......)。
上一篇文章是对genreal中路由器和NAT遍历的许多想法的一个很好的介绍。我刚刚读到它时实现了一些TURN服务器/客户端程序,作者真的知道他们在谈论什么!