Wie bekomme ich den ursprünglichen Zielport der umgeleiteten UDP-Nachricht?

8

dieses Ding kann ich Original erhalten Ziel-IP-Adresse von socket(PF_INET, SOCK_DGRAM, 0) socket.

Wie bekomme ich den ursprünglichen Zielport?

    
Vi. 11.04.2011, 00:02
quelle

2 Antworten

6

Hängt vom Umleitungsmechanismus ab. Wenn Sie REDIRECT (NAT unter der Haube) verwenden, müssen Sie SO_ORIGINAL_DST oder libnetfilter_conntrack verwenden, um das ursprüngliche Ziel der Verbindung abzufragen, bevor NAT angewendet wurde. Da Sie jedoch mehrere Verbindungen mit demselben Listener-Socket bedienen können, muss diese Suche für jedes Paket durchgeführt werden.

Sie können mit libnetfilter_conntrack und den angebotenen Diensten mit dem conntrack Kommandozeilen-Tool experimentieren.

Eine Alternative ist die Verwendung von TPROXY für die Umleitung, die in solchen Fällen verwendet werden sollte. Dort können Sie das ursprüngliche Ziel des Pakets mithilfe einer ancillirary-Nachricht mit recvmsg () abrufen. Der Schlüssel zum Suchen ist IP_RECVORIGDST setsockopt.

Weitere Informationen zu TPROXY finden Sie im Dokumentationsverzeichnis des Kernels in einer Datei namens tproxy.txt. Es ist ein bisschen schwierig zu verwenden, aber arbeitet zuverlässiger, da es durch den Stapel implementiert wird, anstatt das Paketfilter-Subsystem.

Bearbeitet: um hinzuzufügen, wie UDP-Zieladressen mit TProxy abgefragt werden.

  1. öffne einen UDP-Socket, bind ihn an 0.0.0.0 oder an eine spezifischere IP
  2. Sie aktivieren IP_RECVORIGDST über setsockopt (fd, SOL_IP, IP_RECVORIGDSTADDR, ...)
  3. Sie verwenden recvmsg () anstelle von recvfrom () / recv (), um Frames
  4. zu empfangen
  5. recvmsg () gibt das Paket und eine Reihe von zusätzlichen Nachrichten zurück,
  6. iteriere die Zusatznachrichten und suche den CMSG-Block mit der Ebene SOL_IP, Index IP_ORIGDSTADDR
  7. Dieser CMSG-Block enthält eine Struktur sockaddr_in mit der IP- und der Port-Information.

Bearbeitet: SO_ORIGINAL_DST vs. udp

SO_ORIGINAL_DST sollte mit Udp-Sockets arbeiten, aber der Kernel lässt Sie die Verbindungsendpunkte nicht angeben, es verwendet den Socket, den Sie SO_ORIGINAL_DST aufrufen, um diese Adressinformationen zu erhalten.

Dies bedeutet, dass es nur funktioniert, wenn der UDP-Socket ordnungsgemäß gebunden (an die umgeleitete Adresse / Port) und verbunden (mit dem fraglichen Client) ist. Ihr Listener-Socket ist wahrscheinlich an 0.0.0.0 gebunden und bedient nicht nur einzelne, sondern mehrere Clients.

Sie müssen jedoch nicht Ihren tatsächlichen Listener-Socket verwenden, um die Zieladresse abzufragen. Da UDP bei der Verbindungsherstellung keine Datagramme überträgt, können Sie einen neuen UDP-Socket erstellen, ihn an die Weiterleitungsadresse binden und mit dem Client verbinden (dessen Adresse Sie kennen, da er das erste Paket sowieso an Ihren Listener gesendet hat). Dann könnten Sie diesen Socket benutzen, um SO_ORIGINAL_DST zu starten, aber es gibt Schuldige:

  1. Sobald Sie einen solchen Socket öffnen, wird der Kernel das bevorzugen, wenn der Client nach dem ersten zusätzliche Pakete sendet, nicht Ihren Listener-Socket
  2. Das ist von Natur aus rassig, denn wenn Ihre Anwendung die Möglichkeit hat, SO_ORIGINAL_DST aufzurufen, hat der Conntrack-Eintrag möglicherweise ein Zeitlimit.
  3. es ist langsam und viel Overhead

Die TProxy-basierte Methode ist eindeutig besser.

    
bazsi77 28.04.2011, 06:39
quelle
1

Versuchen Sie, /proc/net/nf_conntrack

zu analysieren     
pepoluan 11.04.2011 06:26
quelle

Tags und Links