UDP服务是否必须从连接的IP地址进行响应?

时间:2009-08-20 23:21:32

标签: python sockets udp ip multihomed

Pyzor使用UDP / IP作为通信协议。我们最近将公共服务器切换到新机器,并开始收到许多超时的报告。我发现如果我将从eth0:1查询的IP更改为eth0,我就可以解决问题。

我可以用一个简单的例子重现这个问题:

这是服务器代码:

#! /usr/bin/env python

import SocketServer

class RequestHandler(SocketServer.DatagramRequestHandler):
    def handle(self):
        print self.packet
        self.wfile.write("Pong")

s = SocketServer.UDPServer(("0.0.0.0", 24440), RequestHandler)
s.serve_forever()

这是客户端代码(188.40.77.206eth0188.40.77.236是同一台服务器,但是eth0:1):

>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> s.sendto('ping', 0, ("188.40.77.206", 24440))
4
>>> s.recvfrom(1024)
('Pong', ('188.40.77.206', 24440))
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> s.sendto('ping', 0, ("188.40.77.236", 24440))
4
>>> s.recvfrom(1024)
[never gets anything]

服务器在两种情况下都获取“ping”数据包(因此在两种情况下都会发送“pong”数据包)。

奇怪的是,确实在某些地方工作(即我会得到两个IP的响应)。例如,它可以从188.40.37.137(相同的网络/数据中心,不同的服务器)工作,也可以从89.18.189.160(不同的数据中心)工作。在这些情况下,recvfrom响应确实具有eth0 IP,而不是连接到的IP。

这只是UDP的规则吗?这是Python UDPServer类的问题/限制吗?这是我做错了吗?除了简单地连接到eth0 IP(或者监听特定的IP而不是0.0.0.0)之外,我有什么方法可以完成这项工作吗?

2 个答案:

答案 0 :(得分:3)

我遇到了TFTP服务器。我的服务器有两个面向同一网络的IP地址。由于UDP是无连接的,因此在这种情况下可能会出现未按预期设置IP地址的问题。我的顺序是:

  1. 客户端将初始数据包发送到特定IP地址的服务器
  2. 服务器从传入数据包中读取客户端的源地址,并发送响应。
    1. 但是,在响应中,服务器的“源地址”是根据路由表设置的,并设置为其他 IP地址。
    2. 无法控制服务器的“源”IP地址,因为操作系统没有告诉我们请求通过哪个IP地址。
  3. 客户端从“其他”IP地址获取响应,并拒绝它。
  4. 我的解决方案是将TFTP服务器专门绑定到我想要侦听的IP地址,而不是绑定到所有接口。

    我发现了一些可能与Linux man page for tftpd(TFTP服务器)相关的文本。这是:

     Unfortunately, on multi-homed systems, it is impossible for tftpd to
     determine the address on which a packet was received. As a result, tftpd
     uses two different mechanisms to guess the best source address to use for
     replies. If the socket that inetd(8) passed to tftpd is bound to a par‐
     ticular address, tftpd uses that address for replies. Otherwise, tftpd
     uses ‘‘UDP connect’’ to let the kernel choose the reply address based on
     the destination of the replies and the routing tables. This means that
     most setups will work transparently, while in cases where the reply
     address must be fixed, the virtual hosting feature of inetd(8) can be
     used to ensure that replies go out from the correct address.  These con‐
     siderations are important, because most tftp clients will reject reply
     packets that appear to come from an unexpected address.
    

    请参阅this answer,其中显示在Linux上 可以读取传入UDP数据包的本地地址,并将其设置为传出数据包。它可能在C;我不确定Python。

答案 1 :(得分:1)

  

这只是UDP的规则吗?

没有

  

这是一个问题/限制   Python UDPServer类?

疑。

  

这是我做错了吗?

您的程序看起来不错。

数据报没有到达服务器的原因有很多。 UDP是无连接的,因此您的客户端只需将ping发送到以太网而不知道是否有人收到它。

查看是否允许绑定到该地址。有一个很棒的小程序叫做netcat,非常适合低级网络访问。它并不总是在每个系统上都可用,但它很容易下载和编译。

nc -l -s 188.40.77.236 -p 24440 -u

如果您像以前一样运行客户端程序,则应在终端上看到“Ping”。 (你可以输入Pong并将它设置回你的客户端。玩起来很有趣。)如果你得到ping,网络问题不是问题,而且Python服务器程序或库有问题。如果没有ping,则无法建立连接。 “请联系您的网络管理员以获取帮助。”

要检查的内容包括......

  1. 防火墙问题?
  2. 使用别名网络接口的配置问题。
  3. 用户权限问题。