无法在NAT路由器后接收UDP数据包

3
我曾阅读有关端口转换的内容,现在我想测试一下。
我有一台位于NAT路由器后面的本地机器和一台具有外部IP地址的服务器。
以下是我如何将来自我的机器上5000号端口的数据包发送到服务器上的4000号端口。
import socket
import sys

UDP_IP = #external server IP address
UDP_PORT = 4000
MESSAGE = "Hi!"

sock = socket.socket(socket.AF_INET, # Internet
                     socket.SOCK_DGRAM) # UDP
sock.bind(('0.0.0.0', 5000))
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))

紧接着,我开始在本地机器上听第5000个。

import socket
import sys

UDP_IP = #my ip address in the local network
UDP_PORT = 5000

sock = socket.socket(socket.AF_INET, # Internet
                     socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))

while True:
    data, addr = sock.recvfrom(1024)
    print "received message:", data

在服务器端,当我看到来自(someIP, somePort)的UDP时,我会向相同的someIPsomePort发送响应(使用其他端口和地址的相同脚本)。但是我从未在我的本地机器上收到这个响应。为什么?
此外,当服务器在本地网络中时,此代码可以正确工作。

1
为什么不直接使用同一个套接字? - David Schwartz
2个回答

1
问题在于您位于NAT之后,您发送到服务器(该服务器位于NAT之外)的数据包将具有NAT服务器的源IP。外部服务器发送的回复将具有NAT的目标IP。当回复到达NAT时,它不知道如何处理该数据包,因为没有可用的地址/端口映射。
您应该在NAT上创建一个映射,如下所示:
NAT地址:5000 <---> 本地地址:5000

在这种情况下,NAT会知道如果它接收到端口5000的数据包,它必须将该数据包发送到您的本地计算机。


4
为什么出站数据报不会创建临时的地址/端口映射?这不是NAT伪装总是工作的方式吗? - David Schwartz

1
我曾经遇到过类似的情况(客户端在NAT后无法通过UDP接收服务器响应),解决方法是从服务器的同一端口发送响应,以响应请求。不同类型的NAT工作方式不同,在我的情况下,路由器必须建立一个严格的映射client:CLIENT_PORT <---> server:SERVER_PORT,所以来自同一服务器的不同端口的“响应”被拒绝了。也许你的情况也是这样。

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