2009-08-20 14 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.206eth0ある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」パケットを取得します(したがって、「pon」 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サーバーで見つけました。私のサーバーは同じネットワークに面した2つのIPアドレスを持っていました。 UDPはコネクションレスなので、IPアドレスが期待どおりに設定されていないという問題があります。私が持っていたシーケンスは:

  1. クライアントが
  2. Serverは、着信パケットからクライアントの送信元アドレスを読み取って、特定のIPアドレスでサーバーへの最初のパケットを送信し、応答を送信します。
    1. しかし、応じて、サーバの「送信元アドレスは、」ルーティングテーブルに従って設定され、それが IPアドレスに設定されます。
    2. OSが要求を受け取ったIPアドレスをOSから教えてくれなかったため、サーバーの「送信元」IPアドレスを制御することができませんでした。
  3. クライアントは "other" 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. 

は、Linux上での着信UDPパケットのためのローカルアドレスを読み込み、発信パケットのためにそれを設定する可能であることを示しているthis answerを参照してください。これはC言語で可能です。私はPythonについてはわかりません。

+0

これは、ここで起こっていることとまったく同じように思えます。私は上記のPythonと同じことをしたCクライアントを書いていましたが、私はまだ同じ結果を得ていますので、 "他のIPからの応答を拒否"しなければなりません(実際には、 )。 特定のアドレスにもバインドする必要があるようです。助けてくれてありがとう! –

1

これは単なるUDPのルールですか?これは PythonのUDPServerクラスでの問題/制限

ですか?

ダウトフル。

私は間違って何かしていますか?

プログラムが正しいように見えます。

データグラムがサーバーに届かない理由はいくつもあります。 UDPはコネクションレスなので、クライアントは受信したかどうかを知らずに単にpingをetherに送ります。

あなたがそのアドレスにバインドできるかどうかを確認してください。低レベルのネットワークアクセスにはうってつけのnetcatという素晴らしい小さなプログラムがあります。すべてのシステムで常に利用できるわけではありませんが、ダウンロードしてコンパイルするのは簡単です。

nc -l -s 188.40.77.236 -p 24440 -u 

クライアントプログラムを以前と同じように実行すると、端末に「Ping」が表示されます。 (あなたはPongと入力してクライアントに戻すことができます。遊びにはちょっと面白いです。)pingを受け取ったら、ネットワーキングの問題は問題ではなく、Pythonのサーバープログラムやライブラリに問題があります。 pingが表示されない場合は、接続できません。 「ネットワーク管理者に連絡してください。」チェックする

物事は...

  1. ファイアウォールの問題が含まれますか?
  2. エイリアスネットワークインターフェイスの設定に関する問題。
  3. ユーザー権限の問題です。
+0

サーバが「ping」を取得するため、問題はアドレスにバインドされませんが、クライアントは「pong」を取得しません。 そのIPにバインドされたnetcatを実行すると(ただし、SocketServerも同様です)。 0.0.0.0 **にバインドされたnetcatを実行しても**動作しません。 –

+0

質問を編集して、問題がクライアントのパケットを受信するのではなく、応答であることを明確にしました。 –

関連する問題