使用服务器绕过路由器发起连接
Posted
技术标签:
【中文标题】使用服务器绕过路由器发起连接【英文标题】:Bypass router using server to initiate connection 【发布时间】:2011-08-06 23:35:43 【问题描述】:我想用 Java 创建一个简单的聊天程序,它可以在 p2p 基础上运行。使用公共服务器仅启动连接。但我什至不确定这是否可能。
如果至少有一台 PC 转发了正确的端口,我成功地用 Java 实现了聊天解决方案。我还设法使用外部服务器,而不是必须在客户端转发端口。
所以我什至有可能以某种方式使用公共服务器来启动连接,而不是在客户端之间正确发送数据,从而减轻服务器的负载?
我不太熟悉路由器的工作原理,但我希望当您从内部 IP 调用公共服务器时,路由器会记住来自该公共 IP 的呼叫和传入响应,而不是发送到您的 PC。所以我想,也许如果第一个客户端连接到服务器,服务器比将信息传递给第二个客户端,也许他们可以以某种方式直接通信?如果router中的规则是服务器建立的?
我希望我解释清楚了。如果没有,请原谅我。我什至不知道这到底是怎么做到的,我只是想知道我的概念是否正确,我必须更加努力地学习,才有可能实现它。谢谢。
【问题讨论】:
你只是在使用 tcp 进行通信,对吧? 【参考方案1】:我认为TeleHash 是一个可以做这种事情的新项目。我是最近才知道的,所以不太了解。
我制作了这个答案社区 wiki,以便其他人可以更新它以解释 TeleHash 如何用于此目的。
【讨论】:
Telehash 正在积极开发中(2013-2014)。我正在研究 Go 的实现。 Telehash 支持 NAT 穿越、前向保密、基于身份的路由等等。【参考方案2】:这是一个浩瀚的主题,搜索hole punching(对于TCP:http://en.wikipedia.org/wiki/TCP_hole_punching)
【讨论】:
【参考方案3】:编辑:在 cmets(并阅读链接页面)之后,我应该撤回我的建议。我没有删除它,为了漂亮的图形,但改变了最后一部分。
如果我理解正确,您在 NAT 防火墙后面都有两个客户端,它允许传出连接,但如果没有特别配置,则不会转发传入连接(因为他们不知道它是哪个本地主机注定)。
原则上,一个 TCP 连接在其整个存在期间总是连接相同的两个 IP 地址和这些地址的端口号(例如,我们有四个保持不变的数字)。在 NAT 的情况下,您实际上有两个连接,但是从客户端计算机 A(也从服务器 S)看不到这:
Client A -------(LAN)------ NAT B ------ (Internet) -------- Server S
IP A IP B1 | IP B2 IP S
Port a | Port b Port s
TCP 数据包在 LAN 部分具有 [A:a / S:s](或 [S:s / A:a])地址和 [B2:b / S:s](或 [S:s / B2:b]) 互联网部分的地址。连接由这个 [IP:port / IP:port] 四元组标识,因此如果您尝试更改四个数字中的一个,这必须是一个新连接(否则数据包将被丢弃)。
因此,如果您首先与您的服务器通话,您将无法继续与同一连接上的其他客户端通话,除非服务器正在转发内容。
其实 UDP 包也是如此,不同的是没有连接,NAT 必须很聪明,猜出哪个包是对哪个包的回答,然后将其转发到右边方向。
正如 cmets 和其他答案所指出的,这是 NAT 可以被欺骗的地方:我们首先向另一个客户端发送一个 UDP 数据包,该数据包将被那里的 NAT 丢弃。但是随后另一个客户端发送了一个应答包,该应答包不是对传出包的真正应答(因为由于其他客户端的 NAT,这个包从未收到过),但 IP 地址和端口号匹配,它仍然会被允许通过。如果 NAT 也转换端口号,这可能会变得更加复杂。
对于 TCP,它可以类似地工作,如果两个 NAT 都没有真正保持打开的连接,而是在之前发送 SYN 时只是转发(更改)数据包。它更复杂,因为这里的 TCP 序列号也必须匹配。
【讨论】:
@Paulo,首先请使用packet
,而不是package
...当您尝试用包解释这一点时,您会立即失去可信度,但这不是我投反对票的原因。我投了反对票,因为他不需要创建新协议。 UDP(假设有问题的端口允许通过任何防火墙)很好。想想看,skype(一个peer2peer应用)get udp through a firewall是怎么做到的?
@Mike:感谢您的评论,我今天学到了一些新东西。关于 Skype,我从未真正考虑过它的点对点性质。 (我曾经读过一些关于它使用其他非防火墙客户端作为网关的内容。)
@mabn:谢谢,你是对的。我改变了我的答案,所以现在不是这个错误。 (阅读您的链接后,我什至会自己投反对票,但我不被允许。)
@Paulo,我非常尊重您对我们 cmets 的回复...谢谢。以上是关于使用服务器绕过路由器发起连接的主要内容,如果未能解决你的问题,请参考以下文章