ツイスト:アウトバウンド接続のソースIPアドレス
-
06-07-2019 - |
質問
私は、Debian GNU / Linux上で動作するTwistedフレームワークを備えたPythonで書かれたサービスを実装する過程にあり、SIPサーバーの可用性をチェックしています。これには、OPTIONSメソッド(SIPプロトコル機能)を使用します。これは一般的な慣行のようです。正しく、RFCに準拠したヘッダーを構築するには、確立しようとしている接続のソースIPアドレスとソースポートを知る必要があります。 [どのように]これをTwistedで実行できますか?
これは私が試したものです:
protocol.DatagramProtocol および< code> startProtocol(self) self.transport.getHost()。host
と self.transport.getHost()。port
を使用しました。後者は実際に使用されるポートですが、前者は0.0.0.0のみを生成します。
この時点で、Twistedは[まだ?]どのインターフェイスを使用し、どのソースIPアドレスが使用されるかを知らないのではないでしょうか。 Twistedはこれに役立つ機能を提供しますか、それともOSとのインターフェース(ルーティング)を別の方法で行う必要がありますか?または、 self.transport.getHost()。host
を誤って使用しただけですか?
解決
完全を期すために、私は自分の質問に答えます:
ホストのソースIPアドレスを決定する前に、トランスポートでconnect()を使用していることを確認してください。次の抜粋は、プロトコル実装の関連部分を示しています。
class FooBarProtocol(protocol.DatagramProtocol):
def startProtocol(self):
self.transport.getHost().host # => 0.0.0.0
self.transport.connect(self.dstHost, self.dstPort)
self.transport.getHost().host # => 192.168.1.102
他のヒント
UDPを使用している場合、エンドポイントは次のいずれかによって決定されます。
- ソケットで
bind()
を呼び出し、明示的にアドレスを与える - パケットの送信
さらに詳細が必要な場合は、このレスポンスを確認 。
問題は、私がツイストに慣れていないことです。ソースをざっと読んでわかることから、 tidSelectReactor
代わりに。これは、 tndDNSDatagramProtocol
は内部で動作します。
写真から twisted
を取り出すと、次のスニペットが何が起こっているかを示しています:
>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
<socket._socketobject object at 0x10025d670>
>>> s.getsockname() # this is an unbound or unnamed socket
('0.0.0.0', 0)
>>> s.bind( ('0.0.0.0', 0) ) # 0.0.0.0 is INADDR_ANY, 0 means pick a port
>>> s.getsockname() # IP is still zero, but it has picked a port
('0.0.0.0', 56814)
複数のネットワークインターフェイスまたはIPv4とIPv6をサポートする必要がある場合、ホスト名の取得は少し複雑です。使用するインターフェースを構成可能にできる場合は、タプルの最初のメンバーとして socket.bind()
に渡し、設定します。
今では、ツイストが提供する抽象化の範囲内でこれを行うのが難しい部分です。残念なことに、私はそこに多くを助けることができません。基礎となるソケットにアクセスする方法の例を探すか、ソケット情報をフレームワークに渡す方法を見つけることをお勧めします。
がんばって。
Twistedの一部であるSIP実装を使用して、実行したいことが可能かどうかを確認しましたか?
いずれの場合も、TwistedでUDPのソースアドレスとポートを設定する方法は、Twistedなしで設定する方法と非常に似ています。 Twistedでは、 reactor.listenUDP(port、protocol、interface)
はUDPソケットを特定のポートとインターフェイスにバインドし、受信したデータグラムをプロトコルに処理します。プロトコル内で、 self.transport.write(msg、addr)
は、プロトコルがソースアドレスとしてバインドされているアドレスを使用して、データグラムを addr
に送信します。
もう一度質問を読んで、不足している部分は interface
を reactor.listenUDP(...)
に渡すことだけだったと思います。