当前位置: 首页 > 面试题库 >

Java UDP打孔示例-通过防火墙连接

司知
2023-03-14
问题内容

可以说我有两台计算机。

他们通过彼此了解公共IP和私有IP ice4j

一个客户端正在侦听,另一个客户端正在发送一些字符串。

我希望通过UPD打孔看到这种情况:

Let A be the client requesting the connection

Let B be the client that is responding to the request

Let S be the ice4j STUN server that they contact to initiate the connection
--
A sends a connection request to S

S responds with B's IP and port info, and sends A's IP and port info to B

A sends a UDP packet to B, which B's router firewall drops but it still
punches a hole in A's own firewall where B can connect

B sends a UDP packet to A, that both punches a hole in their own firewall,
and reaches A through the hole that they punched in their own firewall

A and B can now communicate through their established connection without 
the help of S

能否再有一个伪示例说明如何通过对称NAT进行打孔?假设将有服务器S帮助猜测端口号并在客户端A和客户端B之间建立连接。

如果您还要考虑双重NAT,那将是很好的。

注意:

您可以使用STUN查找IP和端口,但是您必须编写自己的代码,以通过keepalive技术将IP:Port发送到您的服务器。

一旦一个客户端通过服务器上的唯一ID识别了另一个客户端,它将为另一个客户端提供IP地址:UDP的端口信息,以便对需要发送和接收的数据进行UDP打孔。

小更新:

有一个库正在显示Java的地平线上签出:https :
//github.com/htwg/UCE#readme


问题答案:

此示例使用C#编写,而不是Java编写,但是NAT遍历的概念与语言无关。

请参阅Michael Lidgren的网络库,其中内置了NAT遍历。

链接:http :
//code.google.com/p/lidgren-network-gen3/ 处理NAT遍历的特定C#文件:http :
//code.google.com/p/lidgren-network-
gen3/source/browse/主干/Lidgren.Network/NetNatIntroduction.cs

您发布的过程是正确的。在4种普通类型的NAT设备中,只有3种有效(我之所以说是通用的,因为NAT行为并未真正标准化):全锥NAT,受限锥NAT和端口受限锥NAT。NAT遍历不适用于对称NAT,对称NAT主要在公司网络中使用,以增强安全性。如果一方使用对称NAT而另一方不使用对称NAT,则仍然可以遍历NAT,但需要更多的猜测。从对称NAT到对称NAT的遍历非常困难-
您可以在此处阅读有关它的文章。

但是实际上,您描述的过程完全可以正常工作。我已经为我自己的远程屏幕共享程序(不幸的是,也使用C#)实现了它。只要确保已禁用Windows防火墙(如果使用Windows)和第三方防火墙即可。但是,是的,我可以很高兴地确认它会起作用。

澄清NAT遍历的过程

我正在写此更新,以为您和将来的读者阐明NAT遍历的过程。希望这可以是历史和过程的清晰摘要。

有些文献:http://think-like-a-computer.com/2011/09/16/types-of-nat/和http://en.wikipedia.org/wiki/Network_address_translation,HTTP://
en.wikipedia.org/wiki/IPv4,http://en.wikipedia.org/wiki/IPv4_address_exhaustion。

IPv4地址已经用完了,它可以唯一地命名大约43亿台计算机。聪明的人预见到了这个问题,除其他原因外,他们还通过为连接到自身的1个共享IP地址分配了计算机网络,发明了路由器来抵抗IPv4地址耗尽。

有局域网IP。然后是WAN IP。LAN IP是局域网IP,用于唯一标识局域网中的计算机,例如连接到家庭路由器的台式机,笔记本电脑,打印机和智能手机。WAN
IP可以唯一地标识广域网中局域网外部的计算机-通常指Internet。因此,这些路由器为一组计算机分配了1个WAN IP。每台计算机仍具有自己的LAN
IP。当您键入ipconfig命令提示符并获取时,将看到LAN IP IPv4 Address . . . . . . . . 192.168.1.101。当您连接cmyip.com并获取WAN IP时,便会看到128.120.196.204

就像购买无线电频谱一样,代理商和组织也购买并保留整个IP范围,以及端口号。再次提醒您,我们没有多余的IPv4地址可供使用。

这与NAT遍历有什么关系?好吧,由于发明了路由器,因此直接连接(端到端连接)在某种程度上……是不可能的,没有一些黑客。如果您的网络由两台计算机(计算机A和计算机B)共享的WAN
IP组成128.120.196.204,则连接连接到哪台计算机?我说的是外部计算机(例如google.com) 启动
与的连接128.120.196.204。答案是: 没有人知道 ,路由器也不 知道 ,这就是路由器断开连接的原因。如果计算机A 启动
与的连接,例如google.com,那就不同了。然后,路由器记住具有LAN IP的计算机A
192.168.1.101发起了与74.125.227.64(google.com)。随着计算机A的请求数据包离开路由器,路由器实际上
LAN IP 重新写入192.168.1.101路由器的WAN IP
128.120.196.204。因此,当google.com收到计算机A的请求数据包时,它会看到路由器重写的发件人IP,而不是计算机A的LAN
IP(google.com被128.120.196.204视为要回复的IP)。当google.com最终答复时,数据包到达路由器,路由器 记住
(它有一个状态表)它正在等待google.com的答复,并适当地将数据包转发到计算机A。

换句话说,如果你的路由器有没有问题 ,你 的路由器会记得转发回复包返回到您的计算机(通过上述整个过程) -启动连接。但是,当外部服务器启动 与您
的连接 ,路由器将无法知道该连接的目标计算机,因为计算机A和计算机B都共享…的WAN
IP,128.120.196.204除非有明确的规则指示路由器将所有最初转到目标端口的数据包转发到X现在转到计算机A的目标端口的所有数据包Y。这称为
端口转发
。不幸的是,如果您正在考虑将端口转发用于网络应用程序,则这是不切实际的,因为您的用户可能不了解如何启用它,并且如果他们认为这有安全隐患,可能不愿意启用它。
UPnP 只是指允许您以 编程方式启用端口转发的技术
。不幸的是,如果您正在考虑使用UPnP来转发您的网络应用程序,那么它也不切实际,因为UPnP并不总是可用,并且当启用时,默认情况下可能未打开。

那么解决方案是什么?解决方案是在您自己的计算机上代理全部流量(已将其预先配置为可全局访问),或者提出一种击败系统的方法。第一个解决方案(我相信)称为TURN,它以为服务器场提供可用带宽的价格神奇地解决了所有连接问题。第二种解决方案称为NAT遍历,这是我们接下来将要探讨的。

之前,我描述了外部html" target="_blank">服务器(例如google.com)发起与的连接的过程128.120.196.204。我说过,如果路由器没有特定的规则来了解将google的连接请求转发到哪台计算机,则路由器会简单地断开连接。这是一般情况,由于存在不同类型的NAT,因此不准确。(注意:路由器是可以放在地板上的实际物理设备。NAT(网络地址转换)是编程到路由器中的软件过程,可帮助保存IPv4地址(如树)。因此,根据
NAT路由器使用,连接方案有所不同。路由器甚至可以 结合 NAT进程。

具有标准化行为的NAT有四种类型:全锥NAT,受限锥NAT,端口受限锥NAT和对称NAT。除了这些类型之外,还可以存在其他类型的具有非标准化行为的NAT,但这很少见。

注意:我对NAT并不是很熟悉…似乎有很多查看路由器的方法,并且互联网上的信息在此主题上非常广泛。Wikipedia说,已不赞成按完全,受限和端口受限的锥体对NAT分类。有一种叫做静态和动态NAT的东西……只是一堆我无法调和的各种概念。不过,以下模型适用于我自己的应用程序。您可以通过阅读本文上下和以上的链接找到有关NAT的更多信息。我无法发布更多有关它们的信息,因为我对它们了解不多。

希望有一些网络专家来纠正/添加输入,以便我们所有人都可以了解有关此神秘过程的更多信息。

要回答 有关收集每个客户端的外部IP和端口的问题:

所有UDP数据包的标头都具有 一个
源IP和 一个 源端口的相同结构。
_UDP数据包头不包含“内部”源IP和“外部”源IP。
UDP数据包头仅包含一个源IP。如果要获得“内部”和“外部”源IP,则需要实际发送内部源IP作为有效负载的一部分。_但这听起来并不像您需要一个内部源IP和端口。听起来就像您的问题所述,您只需要一个外部IP和端口即可。这意味着您的解决方案只需读取源IP并像其字段一样关闭数据包的端口。

以下是两种情况(它们并没有真正解释其他内容):

局域网通讯

计算机A的LAN IP为192.168.1.101。计算机B的LAN
IP为192.168.1.102。计算机A从端口3000向计算机B的端口6000发送一个数据包。UDP数据包上的源IP为192.168.1.101。那将是唯一的IP。“外部”在这里没有上下文,因为网络纯粹是局域网。在此示例中,不存在广域网(如Internet)。但是,关于端口,因为我不确定NAT,所以不确定包上的端口号是否为3000。NAT设备
可能 将数据包的端口从3000改写为诸如49826之类的随机值。无论哪种方式,您都应该使用数据包上标明的任何端口进行答复-
这就是您应该用来答复的端口。因此,在此LAN通信示例中,您只需要发送一个IP-LAN IP,因为这很重要。您不必担心端口-
路由器会为您负责。收到数据包后,只需从数据包中读取就可以收集唯一的IP和端口。

广域网通讯

再次,计算机A的IP地址为192.168.1.101。计算机B的LAN
IP仍为192.168.1.102。计算机A和计算机B都将共享128.120.196.204的WAN IP。服务器S是服务器,是位于Amazon
EC2服务器上的全局可访问计算机,其WAN IP为1.1.1.1。服务器S可能具有LAN IP,但这无关紧要。计算机B也无关紧要。

计算机A从端口3000向服务器S发送一个数据包。在离开路由器的过程中,来自计算机A的数据包的源LAN IP被重新写入路由器的WAN
IP。路由器还将源端口300重写为32981。就外部IP和端口而言,服务器S看到什么?服务器S将128.120.196.204视为IP,而不是192.168.1.101,服务器S将32981视为端口,而不是3000。尽管这些不是原始IP,并且计算机A用来发送数据包的端口也正确,但这些都是正确的IP。和要回复的端口。收到数据包时,您只能知道WAN
IP和重写的端口。如果这就是您想要的(您只要求 外部 IP和端口),那么您就可以开始了。否则,如果您还想要发送者的内部IP, 标题 分开

码:

如上所述(下面 要回答 有关收集外部IP的问题),要收集每个客户端的外部IP和端口,只需从数据包中读取它们即可。发送的每个数据报 始终
具有发送方的源IP和源端口。您甚至不需要精美的自定义协议,因为始终包含这两个字段-根据定义,每个UDP数据包都必须具有这两个字段。

// Java language
// Buffer for receiving incoming data
byte[] inboundDatagramBuffer = new byte[1024];
DatagramPacket inboundDatagram = new DatagramPacket(inboundDatagramBuffer, inboundDatagramBuffer.length);
// Source IP address
InetAddress sourceAddress = inboundDatagram.getAddress();
// Source port
int sourcePort = inboundDatagram.getPort();
// Actually receive the datagram
socket.receive(inboundDatagram);

因为getAddress()getPort()可以根据目标端口或源端口的设置返回目标端口或源端口,所以在客户端(发送)机器上,调用setAddress()setPort()返回到服务器(接收)机器,在服务器(接收)机器上,调用setAddress()setPort()返回到客户端(发送)机器。必须有一种方法可以在中执行此操作receive()。请详细说明这是否是您的实际障碍(getAddress()并且getPort()不要返回您期望的源IP和端口)。这是假定服务器为“标准”
UDP服务器(不是STUN服务器)。

进一步更新:

我阅读了有关“ 如何使用STUN从一个客户端获取IP和端口并将其提供给另一个客户端
”的更新?STUN服务器并非旨在交换端点或执行NAT遍历。STUN服务器旨在告诉您您的公共IP,公共端口和NAT设备的类型(无论是全锥NAT,受限锥NAT还是端口受限锥NAT)。我将负责交换端点并执行实际NAT遍历的中间人服务器称为“介绍人”。在我的个人项目中,我实际上不需要使用STUN来执行NAT遍历。我的“介绍人”(介绍客户端A和B的中间人服务器)是侦听UDP数据报的标准服务器。当客户A和客户B都向介绍人注册时,介绍人会读取其公共IP以及端口和专用IP(如果它们位于LAN上)。从数据报头中读取公共IP,就像所有标准UDP数据报一样。专用IP被写入为数据报有效负载的一部分,而引入者只是将其读取为有效负载的一部分。因此,关于STUN的有用性,您无需依靠STUN来获取每个客户端的公共IP和公共端口-
任何连接的套接字都可以告诉您这一点。一世’

请详细说明障碍:如果您希望获得有关设计应用程序消息传递协议的最佳实践的建议,以及有关以有序和系统的方式(根据您在下面发表的评论)从接收到的消息中读取字段的建议,是否可以分享您的最新消息?方法?



 类似资料:
  • 问题内容: 我正在写这个问题并回答它,因为我花了几个小时使它今天开始工作,而我在这里找不到的答案对我有用。希望这对其他人有帮助。如果您有除我最终使用的解决方案以外的其他解决方案,请随时回答此问题。如果您的情况更好,我会接受您的情况。 问题:我正在尝试使用VisualVM和jstatd监视我的FreeBSD服务器上的一些自制Java应用程序(这也应适用于Linux服务器),但是即使在我之后,我也无法

  • 基本概念 netfilter Linux 内核包含一个强大的网络过滤子系统 netfilter。netfilter 子系统允许内核模块对遍历系统的每个网络数据包进行检查。这表示在任何传入、传出或转发的网络数据包到达用户空间中的组件之前,都可以通过编程方式检查、修改、丢弃或拒绝。netfilter 是 RHEL 7 计算机上构建防火墙的主要构建块。 尽管系统管理员理论上可以编写自己的内核模块以与 n

  • 我有一个服务器写在JavaServerSocket。 我有一个客户端,它位于一个公司防火墙之上,除了公共端口之外,它阻止了所有东西。 我已在SMTP端口(#25)上启动服务器。 有防火墙的用户连接到它,到目前为止一切正常。 然后服务器处理ServerSocket.accept()。据我所知,它在一个随机端口上创建一个套接字(每次端口号都不同)。因为防火墙而失败。 我的问题是-如何制作ServerS

  • iptables 命令 防火墙分为硬件防火墙和软件防火墙 防火墙策略一般分为两种:开放和屏蔽 iptables 是 Linux 上常用的防火墙软件 iptables 一共有四张表和五条链 iptables (选项)[表名] (选项)[链名规则] (选项)[动作] 表: Raw 负责连接跟踪 Mangle 负责包处理 Nat 负责地址转换 Filter 负责包过滤 链名规则: PREROUTING

  • 我正在尝试从我们的网络访问cloud Elasticsearch安装,这需要使用外部请求的代理。这是我用来传递Elasticsearch凭据和代理设置的代码片段: CredentialsProvider CredentialsProvider=new BasicCredentialsProvider();CredentialsProvider.SetCredentials(AuthScope.An

  • Contributed by Joseph J. Barbish. Converted to SGML and updated by Brad Davis. 31.1. 入门 防火墙的存在, 使得过滤出入系统的数据流成为可能。防火墙可以使用一组或多组 “规则 (rules)”,来检查出入您的网络连接的数据包, 并决定允许或阻止它们通过。这些规则通常可以检查数据包的某个或某些特征,这些特征包括, 但