UDP サービスは接続された IP アドレスから応答する必要がありますか?

StackOverflow https://stackoverflow.com/questions/1309370

質問

パイザー 通信プロトコルとして UDP/IP を使用します。最近、パブリック サーバーを新しいマシンに切り替えたところ、多数のタイムアウトに関するレポートが届くようになりました。クエリの対象となる IP を変更すると問題を解決できることがわかりました。 eth0:1eth0.

簡単な例でこの問題を再現できます。

これはサーバーコードです:

#! /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」パケットを取得します(したがって、どちらの場合も「pong」パケットを送信します)。

奇妙なことに、これは する いくつかの場所から作業します(つまり、両方の IP から応答が得られます)。たとえば、次のように動作します。 188.40.37.137 (同じネットワーク/データセンター、異なるサーバー) だけでなく、 89.18.189.160 (別のデータセンター)。それらの場合、 recvfrom 応答には eth0 接続されていた IP ではなく、IP。

これは単なる UDP のルールですか?これは問題/制限ですか? パイソン UDPServer クラス?それは私のやり方が間違っているのでしょうか?単に接続する以外にこの作業を行う方法はありますか? eth0 IP (または、IP ではなく特定の IP でリッスン) 0.0.0.0)?

役に立ちましたか?

解決

TFTPサーバーでこれに遭遇しました。私のサーバーには、同じネットワークに面した 2 つの IP アドレスがありました。UDP はコネクションレスであるため、その状況では IP アドレスが期待どおりに設定されないという問題が発生する可能性があります。私が持っていたシーケンスは次のとおりです。

  1. クライアントは最初のパケットを特定の IP アドレスのサーバーに送信します
  2. サーバーは受信パケットからクライアントの送信元アドレスを読み取り、応答を送信します。
    1. ただし、応答では、サーバーの「送信元アドレス」がルーティング テーブルに従って設定され、 他の IPアドレス。
    2. OS はリクエストがどの IP アドレスを経由して来たのかを教えてくれなかったため、サーバーの「ソース」IP アドレスを制御することはできませんでした。
  3. クライアントは「他の」IP アドレスから応答を受け取りますが、それを拒否します。

私の場合の解決策は、すべてのインターフェイスにバインドするのではなく、リッスンしたい IP アドレスに TFTP サーバーを具体的にバインドすることでした。

関連する可能性のあるテキストを見つけました 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 はコネクションレス型であるため、クライアントは誰かが受信するかどうかを知ることなく、エーテルに ping を送信するだけです。

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

nc -l -s 188.40.77.236 -p 24440 -u

前と同じようにクライアント プログラムを実行すると、端末に「Ping」と表示されるはずです。(Pong と入力して、クライアントに設定し直すことができます。遊んでみるとちょっと楽しいです。) ping が受信できた場合は、ネットワークの問題は問題ではなく、Python サーバー プログラムまたはライブラリに問題があると考えられます。ping が届かない場合は接続できません。「サポートが必要な場合は、ネットワーク管理者に問い合わせてください。」

確認すべき内容は次のとおりです。

  1. ファイアウォールの問題?
  2. エイリアス化されたネットワーク インターフェイスに関する構成の問題。
  3. ユーザー権限の問題。
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top