
Hallo zusammen! Ich heiße Dmitry Samsonov und arbeite als leitender Systemadministrator bei "Odnoklassniki". Wir haben über 7000 physische Server, 11000 Container in unserer Cloud und 200 Anwendungen, die in verschiedenen Konfigurationen 700 verschiedene Cluster bilden. Der überwiegende Teil der Server läuft unter CentOS 7.
Am 14. August 2018 wurden Informationen über die Schwachstelle FragmentSmack veröffentlicht.
() und SegmentSmack (). Diese Schwachstellen haben einen netzwerkbasierten Angriffsvektor und eine ziemlich hohe Bewertung (7.5), die einen Denial of Service (DoS) aufgrund von Ressourcenauslastung (CPU) bedroht. Ein Kernel-Patch für FragmentSmack wurde zu diesem Zeitpunkt noch nicht angeboten und kam erheblich später nach der Veröffentlichung der Schwachstelleninformationen heraus. Um SegmentSmack zu beheben, wurde empfohlen, das Kernel zu aktualisieren. Das Update-Paket wurde am selben Tag veröffentlicht, es musste nur installiert werden.
Nein, wir sind überhaupt nicht gegen die Aktualisierung des Kernels! Es gibt jedoch einige Nuancen…
So aktualisieren wir den Kernel in der Produktion
Eigentlich ist es nicht kompliziert:
- Pakete herunterladen;
- Sie auf eine bestimmte Anzahl von Servern installieren (einschließlich der Server, die unsere Cloud hosten);
- Sicherstellen, dass nichts kaputt gegangen ist;
- Überprüfen, dass alle Standard-Kerneinstellungen ohne Fehler angewendet wurden;
- Ein paar Tage warten;
- Die Kennzahlen der Server überprüfen;
- Die Bereitstellung neuer Server auf den neuen Kernel umschalten;
- Alle Server in den Rechenzentren aktualisieren (ein Rechenzentrum nach dem anderen, um die Auswirkungen auf die Nutzer im Falle von Problemen zu minimieren);
- Alle Server neu starten.
Das Ganze für alle vorhandenen Kernel-Versionen wiederholen. Momentan sind das:
- Standard-CentOS 7 3.10 – für die meisten gewöhnlichen Server;
- Vanilla 4.19 – für unsere , weil wir BFQ, BBR usw. benötigen;
- Elrepo kernel-ml 5.2 – für , weil 4.19 früher instabil war und wir die gleichen Funktionen benötigen.
Wie Sie sich vorstellen können, nimmt das Neustarten von tausenden Servern am meisten Zeit in Anspruch. Da nicht alle Sicherheitsanfälligkeiten für alle Server kritisch sind, starten wir nur die Server neu, die direkt aus dem Internet zugänglich sind. In der Cloud, um die Flexibilität nicht einzuschränken, binden wir die extern zugänglichen Container nicht an einzelne Server mit dem neuen Kernel, sondern starten alle Hosts ohne Ausnahme neu. Glücklicherweise ist das Verfahren dort einfacher als bei herkömmlichen Servern. Zum Beispiel können stateless-Container während des Reboots einfach auf einen anderen Server umziehen.
Dennoch gibt es viel zu tun, und dies kann mehrere Wochen in Anspruch nehmen, und bei Problemen mit der neuen Version sogar mehrere Monate. Angreifer wissen das gut, daher ist ein Plan „B“ notwendig.
FragmentSmack/SektorSmack. Workaround
Glücklicherweise gibt es für einige Sicherheitsanfälligkeiten einen solchen Plan „B“, und er wird Workaround genannt. In der Regel handelt es sich dabei um Änderungen an den Kernel-/Anwendungseinstellungen, die es ermöglichen, die möglichen Auswirkungen zu minimieren oder die Ausnutzung der Schwachstellen vollständig zu verhindern.
Im Fall von FragmentSmack/SektorSmack folgender Workaround:
«Die Standardwerte 4MB und 3MB in net.ipv4.ipfrag_high_thresh und net.ipv4.ipfrag_low_thresh (und deren Entsprechungen für ipv6 net.ipv6.ipfrag_high_thresh und net.ipv6.ipfrag_low_thresh) können auf 256 kB und 192 kB oder weniger geändert werden. Tests zeigen eine geringe bis erhebliche Reduzierung der CPU-Nutzung während eines Angriffs, abhängig von der Hardware, den Einstellungen und den Bedingungen. Es kann jedoch einige Auswirkungen auf die Leistung geben, da nur zwei 64K-Fragmente gleichzeitig in der Warteschlange zur Neuzusammenstellung Platz finden können, wenn ipfrag_high_thresh=262144 bytes eingestellt ist. Beispielsweise besteht das Risiko, dass Anwendungen, die mit großen UDP-Paketen arbeiten, ausfallen.».
Die Parameter selbst so beschrieben:
ipfrag_high_thresh - LANGE ZAHL
Maximaler Speicher, der zum Zusammenfügen von IP-Fragmenten verwendet wird.
ipfrag_low_thresh - LONG INTEGER
Maximaler Speicher, der zum Zusammenfügen von IP-Fragmenten verwendet wird, bevor der Kernel
beginnt, unvollständige Fragmentwarteschlangen zu entfernen, um Ressourcen freizugeben.
Der Kernel akzeptiert weiterhin neue Fragmente zur Defragmentierung.
In unseren Produktionsdiensten gibt es keine großen UDP. Im LAN gibt es keinen fragmentierten Verkehr, im WAN gibt es ihn, aber nicht in nennenswerter Menge. Nichts deutet darauf hin – man kann den Workaround anwenden!
FragmentSmack/SektorSmack. Erste Blutung
Das erste Problem, mit dem wir konfrontiert waren, war, dass die Cloud-Container manchmal neue Einstellungen nur teilweise anwendeten (nur ipfrag_low_thresh), und manchmal sie überhaupt nicht anwendeten – sie stürzten einfach beim Start ab. Es war nicht möglich, das Problem stabil zu reproduzieren (manuell wurden alle Einstellungen problemlos angewendet). Es war auch nicht einfach zu verstehen, warum der Container beim Start abstürzt: Es wurden keine Fehler gefunden. Eines war jedoch sicher: Das Zurücksetzen der Einstellungen löst das Problem mit den Abstürzen der Container.
Warum ist es nicht ausreichend, Sysctl auf dem Host anzuwenden? Der Container lebt in seinem eigenen, zugewiesenen Netzwerk-Namespace, daher mindestens im Container kann sich vom Host unterscheiden.
Wie werden die Sysctl-Einstellungen im Container angewendet? Da unsere Container unprivilegiert sind, ist es nicht möglich, eine Sysctl-Einstellung zu ändern, indem man in den Container geht – es fehlen einfach die Berechtigungen. Zum Starten der Container nutzte unsere Cloud zu diesem Zeitpunkt Docker (jetzt schon ). Die Parameter des neuen Containers, einschließlich der erforderlichen Sysctl-Einstellungen, wurden über die API an Docker übergeben.
Bei der Durchsicht der Versionen stellte sich heraus, dass die Docker-API nicht alle Fehler zurückgab (zumindest in Version 1.10). Als wir versuchten, den Container mit "docker run" zu starten, sahen wir endlich etwas:
write /proc/sys/net/ipv4/ipfrag_high_thresh: ungültiges Argument docker: Fehlermeldung vom Daemon: Kann den Container <...> nicht starten: [9] Systemfehler: konnte nicht mit dem Containerprozess synchronisieren.
Der Parameterwert ist ungültig. Aber warum? Und warum ist er nur manchmal ungültig? Es stellte sich heraus, dass Docker die Reihenfolge der Anwendung von Sysctl-Parametern nicht garantiert (die letzte geprüfte Version – 1.13.1), weshalb ipfrag_high_thresh manchmal auf 256K gesetzt werden wollte, während ipfrag_low_thresh noch 3M war, also lag die obere Grenze unter der unteren, was zu dem Fehler führte.
Zu diesem Zeitpunkt hatten wir bereits unseren eigenen Mechanismus zur Nachkonfiguration des Containers nach dem Start verwendet (Einfrieren des Containers über und Ausführung von Befehlen im Namespace des Containers über ), und wir fügten auch das Schreiben der Sysctl-Parameter in diesen Teil ein. Das Problem war gelöst.
FragmentSmack/SegmentSmack. Erste Blutung 2
Kaum hatten wir uns mit der Anwendung des Workarounds in der Cloud vertraut gemacht, erhielten wir die ersten seltenen Beschwerden von Benutzern. Zu diesem Zeitpunkt waren einige Wochen seit der Einführung des Workarounds auf den ersten Servern vergangen. Erste Ermittlungen zeigten, dass die Beschwerden sich auf einzelne Dienste bezogen und nicht auf alle Server dieser Dienste. Das Problem nahm erneut einen äußerst unbestimmten Charakter an.
Zuerst haben wir natürlich versucht, die Sysctl-Einstellungen zurückzusetzen, aber das hatte keinerlei Effekt. Verschiedene Manipulationen an den Einstellungen von Server und Anwendung halfen ebenfalls nicht. Ein Neustart half. Der Neustart für Linux ist ebenso unnatürlich, wie er in früheren Zeiten eine normale Bedingung für die Arbeit mit Windows war. Dennoch half er, und wir schrieben alles einem "Fehler im Kernel" bei, der bei der Anwendung neuer Einstellungen in Sysctl auftrat. Wie leichtfertig das war…
Drei Wochen später trat das Problem erneut auf. Die Konfiguration dieser Server war ziemlich einfach: Nginx im Proxy-/Load-Balancer-Modus. Der Datenverkehr war gering. Neue Erkenntnis: Bei den Clients nimmt die Anzahl der 504-Fehler täglich zu (). Der Graph zeigt die Anzahl der 504-Fehler pro Tag für diesen Dienst:

Alle Fehler beziehen sich auf dasselbe Backend - das, das sich in der Cloud befindet. Der Graph des Speicherkonsums für Paketfragmente auf diesem Backend sah folgendermaßen aus:

Dies ist eines der auffälligsten Erscheinungsformen des Problems in den Diagrammen des Betriebssystems. Zur selben Zeit wurde in der Cloud ein anderes Netzwerkproblem mit den QoS-Einstellungen (Traffic Control) behoben. In der Grafik des Speicherkonsums für Paketfragmente sah es genau so aus:

Die Annahme war einfach: Wenn sie in den Grafiken gleich aussehen, ist auch die Ursache dieselbe. Zumal Probleme mit diesem Speichertyp äußerst selten vorkommen.
Der Inhalt des behobenen Problems bestand darin, dass wir im QoS den Paket-Scheduler fq mit den Standard-Einstellungen verwendeten. Standardmäßig erlaubt er für eine Verbindung das Hinzufügen von 100 Paketen in die Warteschlange, und einige Verbindungen füllten die Warteschlange in Situationen von Bandbreitenengpässen bis zur maximalen Kapazität. In diesem Fall werden Pakete verworfen. In der Statistik tc (tc -s qdisc) ist dies folgendermaßen zu sehen:
qdisc fq 2c6c: übergeordnet 1:2c6c Limit 10000p Flusslimit 100p Buckets 1024 Waisenmaske 1023 Quantum 3028 Anfangsquantum 15140 Nachfüllverzögerung 40,0 ms
Gesendet 454701676345 Bytes 491683359 Pakete (verworfen 464545, Überlimits 0 Rückeinträge 0)
Rückstand 0b 0p Rückeinträge 0
1024 Flüsse (1021 inaktiv, 0 gedrosselt)
0 gc, 0 hochprioritär, 0 gedrosselt, 464545 Flüsse_plimit
„464545 flows_plimit“ – das sind die Pakete, die aufgrund einer Überlastung des Warteschlangenlimits einer Verbindung abgeworfen wurden, während „dropped 464545“ die Summe aller abgeworfenen Pakete dieses Planers ist. Nach der Erhöhung der Warteschlangenlänge auf 1000 und dem Neustart der Container trat das Problem nicht mehr auf. Man kann sich zurücklehnen und einen Smoothie trinken.
FragmentSmack/SegmentSmack. Letztes Blut
Erstens, einige Monate nach der Ankündigung der Schwachstellen im Kernel, wurde schließlich ein Fix für FragmentSmack veröffentlicht (ich erinnere daran, dass zusammen mit der Ankündigung im August nur ein Fix für SegmentSmack herauskam), was uns die Chance gab, auf den Workaround zu verzichten, der uns einige Probleme bereitet hatte. Einige Server haben wir in der Zwischenzeit bereits auf den neuen Kernel migriert, und nun musste alles von vorne beginnen. Warum haben wir den Kernel aktualisiert, ohne auf den Fix für FragmentSmack zu warten? Der Grund ist, dass der Schutzprozess gegen diese Schwachstellen zeitgleich (und zusammengeführt) mit dem Prozess der Aktualisierung von CentOS war (was noch mehr Zeit in Anspruch nimmt als nur das Aktualisieren des Kernels). Zudem ist SegmentSmack eine gefährlichere Schwachstelle, und der Fix dafür erschien sofort, sodass es in jedem Fall sinnvoll war. Allerdings konnten wir den Kernel einfach nicht auf CentOS aktualisieren, weil die Schwachstelle FragmentSmack, die zu Zeiten von CentOS 7.5 auftrat, nur in Version 7.6 behoben wurde, weshalb wir das Update auf 7.5 stoppen und alles neu mit dem Update auf 7.6 beginnen mussten. So kann es auch gehen.
Zweitens, wir erhielten wieder seltene Benutzerbeschwerden über Probleme. Jetzt wissen wir genau, dass alle mit dem Hochladen von Dateien von Kunden auf einige unserer Server zusammenhängen. Dabei handelte es sich um sehr wenige Uploads im Vergleich zur Gesamtzahl.
Wie wir aus der obigen Erzählung wissen, hat das Zurücksetzen von Sysctl nicht geholfen. Ein Neustart half, aber nur vorübergehend.
Die Verdachtsmomente bezüglich Sysctl waren nicht ausgeräumt, aber diesmal war es notwendig, so viele Informationen wie möglich zu sammeln. Außerdem fehlte es sehr, das Problem mit dem Hochladen auf der Client-Seite nachzuvollziehen, um gezielter zu untersuchen, was geschah.
Die Analyse aller verfügbaren Statistiken und Protokolle hat uns nicht näher zu einem Verständnis der Situation gebracht. Es fehlte schmerzlich die Möglichkeit, das Problem zu reproduzieren, um die spezifische Verbindung "zu greifen". Endlich gelang es den Entwicklern in der Spezialversion der Anwendung, das Problem stabil auf dem Testgerät zu reproduzieren, wenn es über Wi-Fi verbunden war. Das stellte einen Durchbruch in der Untersuchung dar. Der Kunde stellte eine Verbindung zu Nginx her, welches auf den Backend-Server weiterleitete, der unsere Java-Anwendung war.

Der Dialog bei Problemen war folgender (auf der Seite des Nginx-Proxys protokolliert):
- Kunde: Anfrage zur Information über den Dateidownload.
- Java-Server: Antwort.
- Kunde: POST mit der Datei.
- Java-Server: Fehler.
Der Java-Server protokolliert dabei, dass 0 Byte Daten vom Kunden empfangen wurden, während der Nginx-Proxy anzeigt, dass die Anfrage mehr als 30 Sekunden gedauert hat (30 Sekunden ist die Timeout-Zeit für die Client-Anwendung). Warum also das Timeout und warum 0 Byte? Aus Sicht von HTTP funktioniert alles so, wie es sollte, aber der POST mit der Datei scheint aus dem Netzwerk zu verschwinden. Und zwar zwischen dem Kunden und Nginx. Es ist Zeit, Tcpdump zu verwenden! Aber zuerst müssen wir die Netzwerkkonfiguration verstehen. Der Nginx-Proxy steht hinter einem L3-Lastenausgleich. : Es wird Tunnelfunktion verwendet, um Pakete vom L3-Lastenausgleich an den Server zu liefern, was zusätzliche Header zu den Paketen hinzufügt:

Hierbei kommt der Verkehr zu diesem Server in Form von VLAN-getaggtem Traffic an, der ebenfalls seine Felder zu den Paketen hinzufügt:

Zusätzlich kann dieser Verkehr fragmentiert werden (der besagte kleine Prozentsatz an eingehendem fragmentiertem Traffic, von dem wir bei der Risikobewertung von Workaround gesprochen haben), was ebenfalls den Inhalt der Header verändert:

Nochmals: Die Pakete sind in einem VLAN-Tag, sind in einem Tunnel verkapselt und fragmentiert. Um besser zu verstehen, wie dies geschieht, verfolgen wir die Route des Pakets vom Kunden bis zum Nginx-Proxy.
- Das Paket gelangt zum L3-Load-Balancer. Um eine korrekte Weiterleitung innerhalb des Rechenzentrums zu gewährleisten, wird das Paket in einen Tunnel verkapselt und an die Netzwerkkarte gesendet.
- Da das Paket + Header des Tunnels nicht in die MTU passen, wird das Paket in Fragmente zerlegt und ins Netzwerk gesendet.
- Der Switch nach dem L3-Load-Balancer fügt beim Empfang des Pakets einen VLAN-Tag hinzu und sendet es weiter.
- Der Switch vor dem Nginx-Proxy erkennt (basierend auf den Port-Einstellungen), dass der Server ein VLAN-verkapseltes Paket erwartet, und sendet es daher unverändert weiter, ohne das VLAN-Tag zu entfernen.
- Linux empfängt Fragmente einzelner Pakete und fügt sie zu einem großen Paket zusammen.
- Das Paket gelangt dann auf das VLAN-Interface, wo die erste Schicht — die VLAN-Verkapselung — entfernt wird.
- Anschließend sendet Linux es an das Tunnel-Interface, wo eine weitere Schicht — die Tunnel-Verkapselung — entfernt wird.
Die Schwierigkeit besteht darin, all dies als Parameter an tcpdump zu übergeben.
Fangen wir am Ende an: Gibt es unverkapselte (ohne überflüssige Header) IP-Pakete von den Clients, bei denen die VLAN- und Tunnel-Verkapselung entfernt wurde?
tcpdump host
Nein, solche Pakete gab es auf dem Server nicht. Das heißt, das Problem muss weiter vorne liegen. Gibt es Pakete mit nur entfernten VLAN-Verkapselungen?
tcpdump ip[32:4]=0xx390x2xx
0xx390x2xx — das ist die IP-Adresse des Clients im hexadezimalen Format.
32:4 — Adresse und Länge des Feldes, in dem die SCR-IP im Tunnel-Paket gespeichert ist.
Die Adresse des Feldes musste durch Ausprobieren gefunden werden, da im Internet über 40, 44, 50, 54 geschrieben wird, aber die IP-Adressen dort nicht vorhanden waren. Außerdem kann man eines der Pakete in hexadezimaler Form betrachten (Parameter -xx oder -XX in tcpdump) und zählen, unter welcher Adresse Ihre bekannte IP steht.
Gibt es Fragmente von Paketen ohne entfernte VLAN- und Tunnel-Verkapselungen?
tcpdump ((ip[6:2] > 0) und (nicht ip[6] = 64))
Diese Magie zeigt uns alle Fragmente, einschließlich des letzten. Wahrscheinlich könnte man auch nach IP filtern, aber ich habe es nicht versucht, da es nicht viele solcher Pakete gibt und ich die benötigten Pakete leicht im allgemeinen Strom gefunden habe. Hier sind sie:
14:02:58.471063 In 00:de:ff:1a:94:11 ethertype IPv4 (0x0800), Länge 1516: (tos 0x0, ttl 63, id 53652, Offset 0, Flags [+], Proto IPIP (4), Länge 1500)
11.11.11.11 > 22.22.22.22: Truncated-IP - 20 Bytes fehlen! (tos 0x0, ttl 50, id 57750, Offset 0, Flags [DF], Proto TCP (6), Länge 1500)
33.33.33.33.33333 > 44.44.44.44.80: Flags [.], seq 0:1448, ack 1, win 343, Optionen [nop,nop,TS val 11660691 ecr 2998165860], Länge 1448
0x0000: 0000 0001 0006 00de fb1a 9441 0000 0800 ...........A....
0x0010: 4500 05dc d194 2000 3f09 d5fb 0a66 387d E.......?....f8}
0x0020: 1x67 7899 4500 06xx e198 4000 3206 6xx4 .faEE.....@.2.m.
0x0030: b291 x9xx x345 2541 83b9 0050 9740 0x04 .......A...P.@..
0x0040: 6444 4939 8010 0257 8c3c 0000 0101 080x dDI9...W.......
0x0050: 00b1 ed93 b2b4 6964 xxd8 ffe1 006a 4578 ......ad.....jEx
0x0060: 6966 0000 4x4d 002a 0500 0008 0004 0100 if..MM.*........
14:02:58.471103 In 00:de:ff:1a:94:11 ethertype IPv4 (0x0800), Länge 62: (tos 0x0, ttl 63, id 53652, offset 1480, flags [none], proto IPIP (4), Länge 40)
11.11.11.11 > 22.22.22.22: ip-proto-4
0x0000: 0000 0001 0006 00de fb1a 9441 0000 0800 ...........A....
0x0010: 4500 0028 d194 00b9 3f04 faf6 2x76 385x E..(....?....f8}
0x0020: 1x76 6545 xxxx 1x11 2d2c 0c21 8016 8e43 .faE...D-,.!...C
0x0030: x978 e91d x9b0 d608 0000 0000 0000 7c31 .x............|Q
0x0040: 881d c4b6 0000 0000 0000 0000 0000 ..............
Dies sind zwei Fragmente eines Pakets (gleiche ID 53652) mit einem Bild (man sieht das Wort Exif im ersten Paket). Da auf dieser Ebene Pakete vorhanden sind, aber in der zusammengefügten Form in den Dumps nicht, muss das Problem eindeutig mit der Zusammenstellung zusammenhängen. Endlich gibt es dafür dokumentarische Beweise!
Der Paketdekoder hat keine Probleme festgestellt, die die Zusammenstellung behindern. Ich habe hier versucht: . Zunächst mochte der Decoder beim Versuch, etwas hineinzustecken, das Paketformat nicht. Es stellte sich heraus, dass zwischen Srcmac und Ethertype zwei überflüssige Oktette waren (die nicht mit Fragmentinformationen zu tun hatten). Nachdem sie entfernt wurden, funktionierte der Decoder. Allerdings wurden keine Probleme angezeigt.
Wie auch immer, außer den besagten Sysctl fanden sich keine weiteren Hinweise. Es galt, einen Weg zu finden, um problematische Server zu identifizieren, um den Umfang zu verstehen und Entscheidungen über weitere Maßnahmen zu treffen. Schnell fand sich der benötigte Zähler:
netstat -s | grep "packet reassembles failed"
Der ist auch im snmpd unter OID=1.3.6.1.2.1.4.31.1.1.16.1 ().
„Die Anzahl der Misserfolge, die durch den IP-Zusammenbau-Algorithmus festgestellt wurden (aus welchen Gründen auch immer: Zeitüberschreitung, Fehler usw.)“.
Unter der Gruppe von Servern, auf denen das Problem untersucht wurde, stieg dieser Zähler bei zwei schneller, bei zwei langsamer und bei weiteren zwei überhaupt nicht an. Der Vergleich der Dynamik dieses Zählers mit der Dynamik von HTTP-Fehlern auf dem Java-Server offenbarte eine Korrelation. Das heißt, der Zähler konnte überwacht werden.
Das Vorhandensein eines zuverlässigen Problemindikators ist sehr wichtig, um genau zu bestimmen, ob ein Rückgang von Sysctl hilft, da wir aus dem vorherigen Bericht wissen, dass dies am Anwendungscode nicht sofort erkennbar ist. Dieser Indikator würde helfen, alle problematischen Stellen in der Produktion zu identifizieren, bevor sie von den Benutzern entdeckt werden.
Nach dem Rückgang von Sysctl hörten die Überwachungsfehler auf, wodurch die Ursache der Probleme nachgewiesen wurde, wie auch die Tatsache, dass der Rückgang hilft.
Wir haben die Fragmentierungseinstellungen auf anderen Servern, wo eine neue Überwachung aktiviert wurde, zurückgesetzt und irgendwo mehr Speicher für Fragmente zugewiesen als zuvor standardmäßig (es handelte sich um UDP-Statistiken, deren teilweise Verlust im Gesamtbild nicht wahrnehmbar war).
Die wichtigsten Fragen
Warum werden auf unserem L3-Lastverteiler Pakete fragmentiert? Die meisten Pakete, die von den Benutzern an die Lastverteiler gesendet werden, sind SYN und ACK. Die Größe dieser Pakete ist gering. Aber da der Anteil solcher Pakete sehr hoch ist, haben wir im Vergleich dazu große Pakete, die fragmentiert wurden, nicht bemerkt.
Die Ursache war ein defektes Konfigurationsskript Auf Servern mit VLAN-Schnittstellen (es gab zu diesem Zeitpunkt sehr wenige Server mit getaggtem Datenverkehr in der Produktion). Advmss ermöglicht es, dem Kunden zu vermitteln, dass die Pakete in unsere Richtung kleiner sein müssen, damit sie nach dem Anfügen der Tunnelüberschriften nicht fragmentiert werden müssen.
Warum half der Rücksetzbefehl für Sysctl nicht, während ein Neustart half? Der Rücksetzbefehl für Sysctl änderte den Speicher, der für das Zusammenfügen von Paketen zur Verfügung stand. Dabei führte anscheinend das Überlaufen des Speichers für Fragmente zu Verlangsamungen der Verbindungen, was dazu führte, dass Fragmente lange in der Warteschlange blieben. Das heißt, der Prozess geriet in eine Schleife.
Ein Neustart setzte den Speicher zurück und alles kam in Ordnung.
War es möglich, ohne Workaround auszukommen? Ja, aber das Risiko, die Benutzer im Falle eines Angriffs ohne Wartung zu lassen, war groß. Natürlich führte die Anwendung des Workarounds letztendlich zu verschiedenen Problemen, einschließlich der Verlangsamung eines der Dienste für die Benutzer, aber dennoch glauben wir, dass die Maßnahmen gerechtfertigt waren.
Ein großes Dankeschön an Andrej Timofejew () für die Unterstützung bei der Durchführung der Untersuchung sowie an Alexey Krenjew () — für die titanische Arbeit beim Aktualisieren von Centos und Kernen auf den Servern. Ein Prozess, den wir in diesem Fall mehrmals von vorne beginnen mussten, wodurch er sich über viele Monate hinzog.
Quelle: habr.com
