14

我在没有基础服务器的情况下对 p2p 通信进行了一些研究,结果遇到了 STUN。根据我的阅读,STUN 是一种 NAT“打孔”方式,不需要端口转发来连接对等方。这是正确的,打孔到底是什么意思?如果不需要端口转发,这一切似乎都非常脆弱,因为它会通过防火墙,而且我不完全理解 STUN 的作用。STUN 可以在 Java 或其他语言的 p2p 程序中使用,例如聊天客户端,它通过 TCP/UDP 端口向对等方发送消息,而无需基础服务器或不需要用户进行端口转发?

4

1 回答 1

62

考虑两台机器想要相互通信的任务。如果两台机器直接连接到公共互联网(而不是在路由器后面),那么这两台机器只需将数据包来回发送到对方的公共 IP。通常,机器位于一个或多个路由器后面。为了简化问题,我们假设只有一层路由器。

NAT 遍历解决了路由器将数据包的传出端口号转换为其他内容的问题(例如,您从端口 X 发送请求,路由器将数据包转换为好像它从端口 Y 离开一样)。如果路由器是端口转发,那么路由器实际上不会进行任何转换(端口 X->X)。然而,大多数家庭/公司/等路由器都没有端口转发,因此 NAT 穿越开始发挥作用。请参阅NAT 遍历和不同类型的NAT

考虑一个路由器的防火墙,它执行上述文章中的任何非端口转发转换(例如全锥)。如果路由器接收到一些数据包到端口 X,但路由器没有从端口 Y 发送任何数据包,它会丢弃数据包(毕竟,数据包是给谁的?路由器不知道!)。只有当某个私有机器发送一个数据包并且路由器进行转换以将端口 X 从该私有机器映射到外部端口 Y 时,外部数据包到端口 Y 才会被转发到私有机器。

STUN 穿越

为了让两个客户端 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 必须以某种方式发现映射. 一些 Wikipedia 文章,该图仅显示具有此漏洞的完整锥形 NAT,但不要相信我的话。从使用打孔的应用程序(Skype、xbox live 等)的数量来看,除了路由器防火墙措施外,网络似乎还依赖于应用程序和系统级防火墙保护。

下面的福特文章简要提到了安全性:“与它的名字所暗示的相反,打孔不会损害专用网络的安全性。” 网络似乎比路由器防火墙更依赖系统级防火墙。

对称 NAT 和 TURN 遍历

STUN 并不总是有效:一些路由器“表现不佳”。机器 A 可能从端口 X 发送两个数据包,一个到 stackoverflow.com,一个到 facebook.com。路由器映射来自端口 Y 的 stackoverflow.com 数据包和来自端口 Z 的 facebook.com 数据包(即使机器 A 从内部端口 X 发送两个数据包)。这是一个对称 NAT。这些 NAT 是有问题的,因为上面的 STUN/Skype 连接不起作用。将 stackoverflow.com 替换为 STUN,将 facebook.com 替换为机器 B(您尝试使用 Skype 的人)。不幸的是,STUN 可以找出 A 发送到 STUN 的数据包的 NAT 映射,但发送到 B 的数据包使用完全不同的映射。通常,(如果您无法跟踪出站路由器数据包)确定对称 NAT 的端口映射是不可能的。因此,客户端需要一个中央路由服务器进行通信,但这违背了 p2p 的全部意义。看

我们可以在 Java 聊天程序中使用它吗?

任何支持网络库的语言(Java、C 等),您可以从任意端口发送数据包,都可以使用 STUN 来遍历 NAT(只要它不是对称 NAT 等)。一般来说,一个人总是需要一个中央服务器(在这种情况下是两个:STUN 和一个登录服务器)。登录服务器的使用如 Skype 示例中所述;一旦两个客户端知道他们的端口映射,他们必须在 p2p 通信开始之前以某种方式相互通信(参见chicken or egg)。但是一旦 A 和 B 知道对方的公共 IP 和 NAT 映射,他们就可以直接通信。

警告

虽然我不可能列出所有 NAT 穿越警告,但一个重要的概念是保持活动:一旦路由器进行了端口映射,它会持续多久?假设我连接到一个 STUN 服务器,然后等待 10 分钟让 B 在我告诉它映射后向我发送一个数据包。路由器可能会丢弃映射(路由器必须定期清除旧映射,以便为新映射腾出空间,并尽量减少安全性)。我找不到我的参考资料,我认为它因 TCP 与 UDP 数据包而异,但我熟悉的应用程序每隔约 60 秒或更短时间发送一个保持活动数据包,以确保路由器不会丢弃映射。一旦路由器丢弃映射并且机器尝试发送数据包,数据包就会被丢弃(导致我数小时的困惑......)。

文章

上一篇文章很好地介绍了流派中关于路由器和 NAT 穿越的许多想法。我前段时间在实现一些 TURN 服务器/客户端程序时阅读了它,作者真的知道他们在说什么!

于 2012-11-24T09:27:31.760 回答