UDP客户端收到服务器消息时发送ICMP“端口不可达”消息。

5

已移动:https://superuser.com/questions/782549/udp-client-sending-icmp-port-unreachable-when-receiveing-messages-from-the-ser

我有一个使用luasocket的UDP客户端,基本上是这样做的(有一些抽象层,但这就是正在进行的操作):

s=socket.udp()
s:setsockname("*",0)
s:setpeername(socket.dns.toip("example.com"),64299)
s:settimeout(0)
s:send(...)
s:settimeout(10)
msg,err=s:receive()
s:settimeout(0)
print(msg,err)

虽然在服务器的调试输出中(通过ssh连接到远程主机),我看到一切都正常,但客户端却出现了“超时”错误。

当使用客户端Wireshark检查所有内容时,我看到了客户端发送的数据包以及来自服务器的响应数据包(正确的端口和一切),还有一个ICMP“端口不可达”数据包,由我的客户端主机发送给服务器作为对其(正确的)响应。

这是怎么回事?我尝试了所有方法,包括将我的iptables重置为“接受所有”,但我的客户端仍然发送“端口不可达”。

相关的数据包如下:

From            To                  Len Description
192.168.2.100   95.143.172.171  UDP 61  Source port: 45025  Destination port: 64299
  000e8f11e7000025229835a908004500002f4008400040112b6fc0a802645f8facabafe1fb2b001b28d794d2000ec8360100aa81a477616e74a3756964
95.143.172.171  192.168.2.100   UDP 60  Source port: 64299  Destination port: 45025
  0025229835a9000e8f11e70008004500002b000040003911727b5f8facabc0a80264fb2bafe100172e8d94d2000e0ea10100a681a3756964ff000000
192.168.2.100   95.143.172.171  ICMP 85 Destination unreachable (Port unreachable)
  000e8f11e7000025229835a9080045c00047061d00004001a492c0a802645f8facab0303cc6c000000004500002b000040003911727b5f8facabc0a80264fb2bafe100172e8d94d2000e0ea10100a681a3756964ff

防火墙,在这种情况下很重要(我认为并不重要,因为当此情况发生时,iptables不会增加任何输入数据包计数器):
$ sudo iptables -S
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -i eth0 -p udp -m udp --sport 64299 -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i eth0 -p tcp -m tcp --dport 10001:30000 -j ACCEPT
-A FORWARD -j REJECT --reject-with icmp-port-unreachable
-A OUTPUT -o lo -j ACCEPT

@alfasin,问题在于没有理由说明该端口不可达,因为我刚刚从该端口发送了请求数据包。 - nonchip
@alfasin 别闹了,我的问题很明确。那怎么解释他为什么会收到 ICMP UNREACH 呢? - user207421
我的问题是:客户端发送“请求”,服务器发送“响应”,但客户端看不到它(超时),而客户端的操作系统向服务器发送“icmp不可达”消息,因为服务器的响应已经到达了客户端的操作系统,但操作系统却忘记了客户端的存在。 - nonchip
@EJP,你说得对,这个问题很模糊。我的观点是这个问题不属于主题范围内。否则它是有效的。我不想回答,我已经为你的回答投了赞成票。 - usr
@usr 这就是我不理解的地方。虽然我同意 EJP 和你的观点,认为这个问题在这里是离题的,但它绝对不是我的防火墙问题(我甚至卸载了 iptables 模块进行测试),所以我担心 EJP 的答案在技术上是不正确的。 - nonchip
显示剩余7条评论
1个回答

1

您的客户端防火墙正在主动阻止入站UDP。


很抱歉,我不认为是这样的。至少如果我理解正确的话。因为:iptables -t filter -A INPUT -i eth0 -p UDP --sport 64299 -j ACCEPT - nonchip
我看到这是唯一可能的解释,但我不明白为什么会这样,因为我明确接受源端口。此外,我接受所有已建立/相关的状态,这应该也隐含地涵盖了这种情况(iptables 会记住无状态“连接”(如 UDP)的 IP/端口对)。 - nonchip
更奇怪的是:检查 iptables -vL ; ./client.lua ; iptables -vL,我发现在客户端运行之前和之后,这些规则都没有收到任何数据包;而 reject-with icmp-port-unreachable 计数器也没有改变。 - nonchip
这个问题现在涉及iptables,因此不属于主题范围。请尝试Superuser。 - user207421
这与你的代码无关。你的代码执行得很完美。读取超时和 ICMP 消息都表明外部因素在起作用。因此,这是离题的。 - user207421
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接