これを使って、socket(PF_INET, SOCK_DGRAM, 0)
ソケットの元の宛先IPアドレスを取得できます。
元の宛先ポートを取得するにはどうすればよいですか?
リダイレクトメカニズムに依存します。REDIRECT(内部的にはNAT)を使用している場合は、NATが適用される前に、SO_ORIGINAL_DSTまたはlibnetfilter_conntrackを使用して接続の元の宛先を照会する必要があります。ただし、同じリスナーソケットで複数の接続を提供できるため、このルックアップはすべてのパケットに対して実行する必要があります。
conntrackコマンドラインツールを使用して、libnetfilter_conntrackとそれが提供するサービスを試すことができます。
別の方法は、リダイレクトにTPROXYを使用することです。これは、このような場合に使用することを目的としていました。そこで、recvmsg()を使用した補助メッセージを使用して、パケットの元の宛先を取得できます。探すべき鍵はIP_RECVORIGDSTsetsockoptです。
TPROXYの詳細については、カーネルのドキュメントディレクトリのtproxy.txtというファイルを参照してください。使用するのは少し難しいですが、パケットフィルタリングサブシステムではなく、スタックによって実装されるため、より確実に機能します。
編集: TProxyを使用してUDP宛先アドレスを照会する方法を追加します。
編集済み: SO_ORIGINAL_DSTとudp
SO_ORIGINAL_DSTはudpソケットで機能するはずですが、カーネルでは接続エンドポイントを指定できません。SO_ORIGINAL_DSTを呼び出すソケットを使用して、このアドレス情報を取得します。
これは、UDPソケットが(リダイレクト先のアドレス/ポートに)適切にバインドされ、(問題のクライアントに)接続されている場合にのみ機能することを意味します。リスナーソケットはおそらく0.0.0.0にバインドされており、単一のクライアントだけでなく複数のクライアントにもサービスを提供しています。
ただし、宛先アドレスを照会するために実際のリスナーソケットを使用する必要はありません。UDPは接続の確立時にデータグラムを送信しないため、新しいUDPソケットを作成し、リダイレクトアドレスにバインドして、クライアント(とにかく最初のパケットをリスナーに送信してから知っているアドレス)に接続できます。次に、このソケットを使用してSO_ORIGINAL_DSTを実行できますが、原因は次のとおりです。
TProxyベースの方法の方が明らかに優れています。
解析してみてください/proc/net/nf_conntrack