2009-08-20 5 views
1

Pyzor은 UDP/IP를 통신 프로토콜로 사용합니다. 우리는 최근 공개 서버를 새로운 시스템으로 전환하고 많은 시간 제한에 대한 보고서를 받기 시작했습니다. 질문이있는 IP를 eth0:1에서 eth0으로 변경하면 문제를 해결할 수 있음을 발견했습니다.UDP 서비스가 연결된 IP 주소에서 응답해야합니까?

나는 간단한 예제와 함께이 문제를 재현 할 수

:.

#! /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.206188.40.77.236가 같은 서버입니다 eth0이지만, 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] 

서버는 두 경우 모두에서 "핑"패킷을 가져옵니다 (따라서 "폰 g "패킷).

이상하게도이 이 몇 군데에서 작동합니다 (두 IP 모두에서 응답을 받겠습니다). 예를 들어 188.40.37.137 (동일한 네트워크/데이터 센터, 다른 서버)에서 작동하지만 89.18.189.160 (다른 데이터 센터)에서도 작동합니다. 이 경우 recvfrom 응답에는 연결된 IP가 아닌 eth0 IP가 있습니다.

이것은 UDP의 규칙일까요? 이것은 PythonUDPServer 클래스의 문제/제한 사항입니까? 내가 잘못하고있는 것입니까? 단순히 eth0 IP에 연결하거나 (0.0.0.0이 아닌 특정 IP로 수신 대기)이 작업을 수행 할 수있는 방법이 있습니까?

답변

3

TFTP 서버로이 문제가 발생했습니다. 내 서버에는 두 개의 IP 주소가 동일한 네트워크를 마주하고 있습니다. UDP는 비 연결식이므로 IP 주소가 예상대로 설정되지 않는 문제가있을 수 있습니다. 내가 가진 순서였다 :

  1. 클라이언트는
  2. 서버가 들어오는 패킷에서 클라이언트의 소스 주소를 읽고 특정 IP 주소에서 서버에 초기 패킷을 전송하고 응답을 보냅니다.
    1. 그러나 응답에서 서버의 "원본 주소"는 라우팅 테이블에 따라 설정되고 기타 IP 주소로 설정됩니다.
    2. OS가 요청한 IP 주소를 알려주지 않았기 때문에 서버의 "원본"IP 주소를 제어 할 수 없었습니다.
  3. 클라이언트가 "다른"IP 주소에서 응답을 받고 거부합니다.

내 경우의 솔루션은 모든 인터페이스에 바인딩하는 대신 듣고 싶었던 IP 주소에 TFTP 서버를 구체적으로 바인딩하는 것이 었습니다.

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. 

리눅스에이 들어오는 UDP 패킷에 대한 로컬 주소를 읽어 나가는 패킷을 설정 가능하다는 것을 보여줍니다 this answer를 참조하십시오. C 언어로 가능합니다. 하지만 파이썬에 대해서는 잘 모르겠습니다.

+0

정확히 여기서 무슨 일이 일어나는지 들립니다. 위의 Python과 동일한 작업을 수행 한 C 클라이언트를 작성했으며 여전히 동일한 결과를 얻었으므로 "다른 IP의 응답 거부"가 C 라이브러리 레벨에서 발생해야합니다.). 특정 주소에도 바인딩해야합니다. 도와 주셔서 감사합니다! –

1

이것은 UDP의 규칙일까요? 이것은 파이썬 UDPServer 클래스에 문제/제한

번호

인가?

의심의 여지가 있습니다.

내가 잘못하고있는 것입니까?

프로그램이 올바르게 보입니다.

데이터 그램이 서버에 도착하지 않는 데는 여러 가지 이유가 있습니다. UDP는 비 연결이므로 클라이언트는 누구나 수신 여부를 알지 못하고 그냥 핑을 에테르로 보냅니다.

해당 주소에 바인딩 할 수 있는지 확인하십시오. 낮은 수준의 네트워크 액세스를 위해 잘 작동하는 netcat이라는 훌륭한 프로그램이 있습니다. 항상 모든 시스템에서 사용할 수있는 것은 아니지만 다운로드하고 컴파일하는 것이 쉽습니다.

nc -l -s 188.40.77.236 -p 24440 -u 

클라이언트 프로그램을 이전과 같이 실행하면 터미널에 "Ping"이 인쇄되어 있어야합니다. (Pong을 타이핑하여 클라이언트에게 되돌려 줄 수있다.) 핑 (ping)을 받으면 네트워킹 문제는 문제가되지 않으며 파이썬 서버 프로그램이나 라이브러리에 문제가있다. 핑을 얻지 못하면 연결을 할 수 없습니다. "네트워크 관리자에게 도움을 요청하십시오." 포함 할 것입니다 확인

것들 ...

  1. 방화벽 문제?
  2. 앨리어싱 된 네트워크 인터페이스의 구성 문제.
  3. 사용자 권한 문제입니다.
+0

서버가 'ping'을 가져 오기 때문에 문제가 주소에 바인딩되지 않지만 클라이언트가 'pong'을 얻지 못합니다. 해당 IP에 연결된 netcat을 실행하면 작동하지만 (SocketServer도 마찬가지 임). 0.0.0.0 **에 바인딩 된 netcat 실행은 ** 작동하지 않습니다. –

+0

나는 클라이언트의 패킷을받는 서버가 아니라 응답이 문제라는 것을 명확하게하기 위해 질문을 편집했다. –