it-swarm.com.de

Was bedeutet SO_REUSEADDR (Option setsockopt) - Linux?

Von der Manpage:

SO_REUSEADDR Gibt an, dass die Regeln zur Überprüfung der für bind () angegebenen Adressen die Wiederverwendung lokaler Adressen zulassen sollen, sofern dies vom Protokoll unterstützt wird. Diese Option nimmt einen int-Wert an. Dies ist eine boolesche Option

Wann soll ich es benutzen? Warum gibt es "Wiederverwendung von lokalen Adressen"?

55
Ray Templeton

Das primäre Entwurfsziel von TCP besteht darin, eine zuverlässige Datenkommunikation angesichts von Paketverlust, Paketumordnung und - hier - Paketduplizierung zu ermöglichen.

Es ist ziemlich offensichtlich, wie ein TCP/IP-Netzwerkstapel mit all dem umgeht, während die Verbindung hergestellt ist, aber es gibt einen Edge-Fall, der unmittelbar nach dem Schließen der Verbindung auftritt. Was passiert, wenn ein Paket, das direkt am Ende der Konversation gesendet wird, dupliziert und verzögert wird, sodass die 4-Wege-Abschaltung Pakete vor dem verzögerten Paket zum Empfänger gelangen? Der Stapel schließt pflichtgemäß seine Verbindung. Später wird das verzögerte Duplikatpaket angezeigt. Was soll der Stack tun?

Was tun, wenn ein Programm mit offenen Sockets für eine bestimmte IP-Adresse + TCP - Portkombination seine Sockets schließt und kurze Zeit später ein Programm auf dieselbe IP-Adresse warten möchte? und TCP Portnummer? (Typischer Fall: Ein Programm wird abgebrochen und schnell neu gestartet.)

Es gibt ein paar Möglichkeiten:

  1. Lassen Sie die Wiederverwendung dieser IP/Port-Kombination mindestens zweimal so lange zu, wie ein Paket im Flug sein kann. In TCP wird dies normalerweise als 2 × MSL delay bezeichnet. Sie sehen manchmal auch 2 × RTT , was ungefähr gleichwertig ist.

    Dies ist das Standardverhalten aller gängigen TCP/IP-Stacks. 2 × MSL liegt normalerweise zwischen 30 und 120 Sekunden und wird in der Ausgabe von netstat als TIME_WAIT Punkt angezeigt. Nach dieser Zeit geht der Stack davon aus, dass Rogue-Pakete verworfen wurdenunterwegsaufgrund abgelaufener TTLs , sodass der Socket den TIME_WAIT verlässt state, so dass die IP/Port-Kombination wieder verwendet werden kann.

  2. Lassen Sie das neue Programm erneut an diese IP/Port-Kombination binden. In Stacks mit BSD-Sockets interfaces - im Wesentlichen alle Unixe und Unix-ähnlichen Systeme sowie Windows über Winsock - müssen Sie nach diesem Verhalten fragen, indem Sie den SO_REUSEADDR setzen. Option über setsockopt() bevor Sie bind() aufrufen.

SO_REUSEADDR wird am häufigsten in Netzwerkserverprogrammen festgelegt, da ein allgemeines Verwendungsmuster darin besteht, eine Konfigurationsänderung vorzunehmen und dieses Programm anschließend neu zu starten, damit die Änderung wirksam wird. Ohne SO_REUSEADDR schlägt der Aufruf bind() in der neuen Instanz des neu gestarteten Programms fehl, wenn Verbindungen zur vorherigen Instanz geöffnet waren, als Sie sie beendet haben. Diese Verbindungen halten den TCP - Port 30 bis 120 Sekunden lang im Status TIME_WAIT, sodass Sie in den obigen Fall 1 fallen.

Das Risiko beim Festlegen von SO_REUSEADDR besteht darin, dass dadurch eine Mehrdeutigkeit entsteht: Die Metadaten in den Kopfzeilen eines TCP -Pakets sind nicht eindeutig genug, sodass der Stack zuverlässig erkennen kann, ob das Paket veraltet ist, und daher verworfen und nicht an das übermittelt werden sollte neue Hörerbuchse, weil sie eindeutig für einen jetzt toten Hörer gedacht war.

Wenn Sie nicht sehen, dass dies zutrifft, muss der TCP/IP-Stack des empfangenden Rechners nur mit Verbindungen pro Verbindung arbeiten, um diese Entscheidung zu treffen:

  1. Lokale IP: Nicht eindeutig per-conn. Tatsächlich besagt unsere Problemdefinition hier, dass wir die lokale IP absichtlich wiederverwenden.

  2. Lokaler TCP Port: Dito.

  3. Remote-IP: Der Computer, der die Mehrdeutigkeit verursacht, kann erneut eine Verbindung herstellen, sodass das richtige Ziel des Pakets nicht eindeutig identifiziert werden kann.

  4. Remote-Port: In gut erzogenen Netzwerkstapeln wird der Remote-Port einer ausgehenden Verbindung nicht schnell wiederverwendet, sondern nur 16 Bit. Wir haben 30-120 Sekunden Zeit, um den Stack zu zwingen, einige Zehntausende von Auswahlen zu durchlaufen und den Port wieder zu verwenden. Computer konnten in den 1960er Jahren so schnell funktionieren.

    Wenn Ihre Antwort darauf lautet, dass der Remote-Stack TIME_WAIT auf seiner Seite ausführen sollte, um ephemeren TCP Port wiederzuverwenden, geht diese Lösung davon aus, dass der Remote-Host harmlos ist. Einem böswilligen Akteur steht es frei, diesen Remote-Port wiederzuverwenden.

    Ich nehme an, der Listener-Stack könnte festlegen, dass nur Verbindungen mit dem 4-Tupel TCP strengstens untersagt werden, damit ein bestimmter Remote-Host während des Status TIME_WAIT keine erneute Verbindung mit demselben Remote-Ephemeral-Port herstellen kann, mir ist dies jedoch nicht bekannt von jedem TCP Stack mit dieser besonderen Verfeinerung.

  5. Lokale und Remote-Sequenznummern TCP: Diese sind auch nicht eindeutig genug, damit ein neues Remote-Programm nicht dieselben Werte liefern kann.

Wenn wir heute TCP umgestalten würden, würden wir vermutlich TLS oder so etwas als nicht optionales Feature integrieren. Ein Effekt davon ist, diese Art von versehentlichem und böswilligem Verbindungsentzug unmöglich zu machen, aber dies erfordert das Hinzufügen großer Felder (128 Bit und mehr), was 1981, als das Dokument für die aktuelle Version von TCP ( RFC 793 ) wurde veröffentlicht.

Ohne eine solche Verhärtung können Sie aufgrund der Mehrdeutigkeit, die durch das Zulassen des erneuten Bindens während TIME_WAIT entsteht, entweder a) veraltete Daten, die für den alten Listener bestimmt sind, falsch an einen Socket des neuen Listeners weiterleiten, wodurch entweder das Protokoll des Listeners verletzt wird oder veraltete Daten falsch eingegeben werden in die Verbindung; oder b) neue Daten für die neue Hörerbuchse, die fälschlicherweise der alten Hörerbuchse zugewiesen und somit versehentlich gelöscht wurden.

Das Sicherste ist, den TIME_WAIT-Zeitraum abzuwarten.

Letztendlich kommt es auf die Wahl der Kosten an: Warten Sie den TIME_WAIT-Zeitraum ab oder übernehmen Sie das Risiko eines unerwünschten Datenverlusts oder einer versehentlichen Dateneingabe.

Viele Serverprogramme gehen dieses Risiko ein und entscheiden, dass es besser ist, den Server sofort wieder hochzufahren, um nicht mehr eingehende Verbindungen als nötig zu verpassen.

Dies ist keine universelle Wahl. Viele Programme - auch Serverprogramme, die einen Neustart erfordern, um eine Einstellungsänderung vorzunehmen - lassen stattdessen SO_REUSEADDR in Ruhe. Möglicherweise kennt der Programmierer diese Risiken und lässt den Standard in Ruhe oder er kennt die Probleme nicht, profitiert jedoch von einem klugen Standard.

Einige Netzwerkprogramme bieten dem Benutzer eine Auswahl unter den Konfigurationsoptionen, wodurch die Verantwortung für den Endbenutzer oder den Sysadmin entfällt.

122
Warren Young

SO_REUSEADDR ermöglicht Ihrem Server, sich an eine Adresse zu binden, die sich in a befindet
TIME_WAIT-Status.

Diese Socket-Option teilt dem Kernel mit, dass selbst wenn dieser Port belegt ist (im TIME_WAIT-Status), er trotzdem weiterverwendet werden soll. Wenn es besetzt ist, aber mit einem anderen Status, erhalten Sie immer noch einen Fehler, dass die Adresse bereits verwendet wird. Dies ist nützlich, wenn Ihr Server heruntergefahren und dann sofort neu gestartet wurde, während Sockets an seinem Port noch aktiv sind.

Von nixguide.net

26
William Briand

Wenn Sie einen Socket erstellen, besitzen Sie ihn nicht wirklich. Das Betriebssystem (TCP-Stack) erstellt es für Sie und gibt Ihnen ein Handle (Dateideskriptor), um darauf zuzugreifen. Wenn Ihr Socket geschlossen ist, benötigt das Betriebssystem einige Zeit, um ihn "vollständig zu schließen", während es mehrere Status durchläuft. Wie EJP in den Kommentaren erwähnte, ist die längste Verzögerung normalerweise vom TIME_WAIT-Status. Diese zusätzliche Verzögerung ist erforderlich, um Edge-Fälle am Ende der Beendigungssequenz zu verarbeiten und sicherzustellen, dass die letzte Beendigungsbestätigung aufgrund einer Zeitüberschreitung entweder eingegangen ist oder die andere Seite selbst zurückgesetzt wurde. Hier finden Sie einige zusätzliche Überlegungen zu diesem Zustand. Die wichtigsten Überlegungen lauten wie folgt:

Denken Sie daran, dass TCP garantiert, dass alle übertragenen Daten zugestellt werden, wenn dies überhaupt möglich ist. Wenn Sie einen Socket schließen, wechselt der Server in den Status TIME_WAIT, nur um wirklich wirklich sicher zu sein, dass alle Daten vorliegen Wenn ein Socket geschlossen ist, stimmen beide Seiten durch das Senden von Nachrichten überein, dass sie keine Daten mehr senden. Dies schien mir gut genug zu sein, und nach dem Handshake sollte der Socket geschlossen werden Das Problem besteht aus zwei Gründen: Erstens kann nicht sichergestellt werden, dass die letzte Bestätigung erfolgreich übermittelt wurde, und zweitens verbleiben möglicherweise "wandernde Duplikate" im Netz, die behandelt werden müssen, wenn sie zugestellt werden.

Wenn Sie sehr schnell versuchen, mehrere Sockets mit demselben IP: Port-Paar zu erstellen, wird der Fehler "Adresse wird bereits verwendet" angezeigt, da der frühere Socket nicht vollständig freigegeben wurde. Wenn Sie SO_REUSEADDR verwenden, wird dieser Fehler beseitigt, da Überprüfungen für vorherige Instanzen überschrieben werden.

8
Eric