Служба UDP должна отвечать с подключенного IP-адреса? - PullRequest
1 голос
/ 21 августа 2009

Pyzor использует UDP / IP в качестве протокола связи. Недавно мы переключили общедоступный сервер на новую машину и начали получать отчеты о многих тайм-аутах. Я обнаружил, что могу решить эту проблему, если я изменил IP-адрес, который был запрошен с eth0:1 на 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.206 - это eth0. 188.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 имеет IP-адрес eth0, а не тот, к которому был подключен.

Это просто правило UDP? Это проблема / ограничение с классом Python UDPServer? Это то, что я делаю неправильно? Можно ли как-нибудь разрешить эту работу, кроме простого подключения к eth0 IP (или прослушивания определенного IP, а не 0.0.0.0)?

Ответы [ 2 ]

3 голосов
/ 21 августа 2009

Я сталкивался с этим с сервером TFTP. У моего сервера было два IP-адреса, обращенных к одной сети. Поскольку UDP не имеет соединения, могут быть проблемы с IP-адресами, которые не устанавливаются должным образом в этой ситуации. Последовательность, которую я имел, была:

  1. Клиент отправляет начальный пакет на сервер по определенному IP-адресу
  2. Сервер считывает адрес источника клиента из входящего пакета и отправляет ответ.
    1. Однако в ответе «исходный адрес» сервера задается в соответствии с таблицами маршрутизации и ему присваивается другой IP-адрес.
    2. Невозможно контролировать «исходный» IP-адрес сервера, поскольку ОС не сообщает нам, через какой IP-адрес поступил запрос.
  3. Клиент получает ответ с «другого» IP-адреса и отклоняет его.

Решение в моем случае состояло в том, чтобы специально привязать TFTP-сервер к IP-адресу, который я хотел прослушать, а не привязывать ко всем интерфейсам.

Я нашел текст, который может иметь отношение к справочной странице Linux для 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.

См. этот ответ , который показывает, что в Linux есть возможность считывать локальный адрес для входящих пакетов UDP и устанавливать его для исходящих пакетов. Это возможно в C; Я не уверен насчет Python.

1 голос
/ 21 августа 2009

Это просто правило UDP?

номер

Это проблема / ограничение с Класс Python UDPServer?

Сомнительный.

Это что-то, что я делаю неправильно?

Ваша программа выглядит правильно.

Существует несколько причин, по которым дейтаграмма не попадает на сервер. UDP не имеет соединения, поэтому ваш клиент просто отправляет пинг в эфир, не зная, получит ли кто-нибудь его.

Посмотрите, разрешено ли вам связываться с этим адресом. Есть отличная маленькая программа под названием netcat, которая отлично работает для низкоуровневого доступа к сети. Он не всегда доступен в каждой системе, но его легко скачать и скомпилировать.

nc -l -s 188.40.77.236 -p 24440 -u

Если вы запускаете свою клиентскую программу, как и раньше, вы должны увидеть «Ping» на вашем терминале. (Вы можете набрать Pong и установить его обратно на свой клиент. С ним интересно играть.) Если вы получаете пинг, проблемы с сетью не являются проблемой, и что-то не так с программой или библиотеками сервера Python. Если вы не получаете пинг, вы не можете установить соединение. «Обратитесь за помощью к администратору сети.»

Вещи, которые нужно проверить, включают ...

  1. Проблемы с брандмауэром?
  2. Проблемы с настройкой сетевых интерфейсов с псевдонимами.
  3. Проблемы с правами пользователя.
...