Должна ли служба UDP отвечать с подключенного IP-адреса?
-
19-09-2019 - |
Вопрос
Пызор использует 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
ответ имеет eth0
IP, а не тот, к которому подключался.
Это просто правило UDP?Это проблема/ограничение с Питон UDPServer
сорт?Это что-то я делаю неправильно?Есть ли какой-нибудь способ выполнить эту работу, кроме простого подключения к eth0
IP (или прослушивание конкретного IP, а не 0.0.0.0
)?
Решение
Я столкнулся с этим с TFTP-сервером.У моего сервера было два IP-адреса, обращенных к одной и той же сети.Поскольку UDP не поддерживает соединение, в этой ситуации могут возникнуть проблемы с IP-адресами, установленными не так, как ожидалось.Последовательность у меня была такая:
- Клиент отправляет первоначальный пакет на сервер по определенному IP-адресу.
- Сервер считывает исходный адрес клиента из входящего пакета и отправляет ответ.
- Однако в ответе «исходный адрес» сервера устанавливается в соответствии с таблицами маршрутизации и ему присваивается значение другой Айпи адрес.
- Невозможно было контролировать «исходный» IP-адрес сервера, поскольку ОС не сообщала нам, через какой IP-адрес пришел запрос.
- Клиент получает ответ от «другого» 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.
Другие советы
Это просто правило UDP?
Нет.
Это проблема/ограничение с классом Python Udpserver?
Сомнительно.
Это что-то я делаю неправильно?
Ваша программа выглядит правильно.
Существует множество причин, по которым дейтаграмма не доходит до сервера.UDP не поддерживает соединение, поэтому ваш клиент просто отправляет пинг в эфир, не зная, получил ли его кто-нибудь.
Посмотрите, разрешено ли вам привязываться к этому адресу.Есть замечательная маленькая программа под названием netcat, которая отлично подходит для низкоуровневого доступа к сети.Он не всегда доступен в каждой системе, но его легко загрузить и скомпилировать.
nc -l -s 188.40.77.236 -p 24440 -u
Если вы запустите клиентскую программу, как и раньше, вы должны увидеть на своем терминале надпись «Ping».(Вы можете ввести Pong и вернуть его своему клиенту.С этим весело играть.) Если вы получаете пинг, значит, проблемы с сетью не являются проблемой, а что-то не так с серверной программой или библиотеками Python.Если вы не получите пинг, вы не сможете установить соединение.«Обратитесь за помощью к своему сетевому администратору».
Вещи, которые следует проверить, включают в себя...
- Проблемы с брандмауэром?
- Проблемы конфигурации с псевдонимами сетевых интерфейсов.
- Проблемы с разрешениями пользователей.