4 Punkte von GN⁺ 2024-01-17 | 1 Kommentare | Auf WhatsApp teilen
  • Speedbump ist ein in Go geschriebener TCP-Proxy, der verzögerten Situationen simuliert, indem er dem proxied TCP-Traffic variable Netzwerklatenz hinzufügt
  • Zur Basislatenz können Latenzkomponenten in Form von Sinus-, Sägezahn-, Rechteck- und Dreieckswellen addiert werden; mehrere Latenzkomponenten lassen sich gleichzeitig kombinieren
  • Das Beispiel zeigt eine Konfiguration, die Traffic zu localhost:80 auf Port 2000 proxyt und dabei 100ms Basisverzögerung, 100ms Sinus-Amplitude und eine Periode von 1m anwendet
  • Die Installation ist möglich durch Download vorgebauter Binaries pro Release, go build aus dem Sourcecode oder das Ausführen des Container-Images kffl/speedbump
  • Neben der CLI kann Speedbump auch über das Go-Paket lib als Bibliothek genutzt werden; Puffergröße, Größe der Verzögerungs-Queue, Log-Level sowie Listening-Host und -Port lassen sich per Argument anpassen

Proxy zur Simulation von TCP-Verzögerungen

  • Speedbump ist ein in Go geschriebener TCP-Proxy und kann variable Netzwerklatenz simulieren
  • Das Proxy-Ziel wird über das CLI-Argument <destination> angegeben; als Format ist host:post beschrieben
  • Standardmäßig proxyt es TCP-Traffic zum Ziel und fügt die konfigurierte Verzögerung hinzu

Installation und Ausführung

  • Die einfachste Installationsmethode ist der Download der vorgebauten Binaries, die automatisch unter Assets jedes Release angehängt werden
  • Zum Bauen aus dem Sourcecode klont man das Repository und führt anschließend go build aus
  • Für die Ausführung als Container kann das Image kffl/speedbump verwendet werden

Einfaches Nutzungsbeispiel

  • Man kann auf Port 2000 lauschen, TCP-Traffic nach localhost:80 proxyn und dabei eine Basisverzögerung von 100ms, eine Sinus-Amplitude von 100ms und eine Periode von 1m anwenden
    • Diese Konfiguration erzeugt eine maximale zusätzliche Latenz von 200ms und eine minimale zusätzliche Latenz von 0
    • Der Ausführungsbefehl lautet speedbump --latency=100ms --sine-amplitude=100ms --sine-period=1m --port=2000 localhost:80
  • Dieselbe Konfiguration kann auch mit dem Container-Image ausgeführt werden
    • Beispiel: docker run --net=host kffl/speedbump:latest --latency=100ms --sine-amplitude=100ms --sine-period=1m --port=2000 localhost:80
  • Auch eine Sägezahn-Komponente für die Verzögerung lässt sich konfigurieren
    • Das Beispiel nutzt eine Basisverzögerung von 300ms, eine Sägezahn-Amplitude von 200ms, eine Periode von 2m, Port 2000 und das Ziel localhost:80
    • Der Befehl lautet speedbump --latency=300ms --saw-amplitude=200ms --saw-period=2m --port=2000 localhost:80

Kombination von Latenzkomponenten

  • Speedbump kann mehrere Latenzkomponenten gleichzeitig anwenden
  • Das README enthält ein Beispiel für einen Verzögerungsgraphen, der Sägezahn- und Sinuswellen kombiniert

CLI-Argumente und Nutzung als Bibliothek

  • speedbump --help zeigt die Nutzung im Format speedbump [<flags>] <destination> an
  • Die wichtigsten Netzwerkeinstellungen sind:
    • --host: IP oder Hostname, auf dem gelauscht wird; ohne Angabe wird an alle Netzwerkinterfaces gebunden
    • --port: Listening-Port; Standardwert ist 8000
    • --buffer: Puffergröße für TCP-Lesevorgänge; Standardwert ist 64KB
    • --queue-size: Größe der Verzögerungs-Queue zum Speichern von Lesepuffern; Standardwert ist 1024
  • Es werden Standardwerte und Wellenform-Optionen für Verzögerungen bereitgestellt
    • --latency: Basislatenz, die dem proxied Traffic hinzugefügt wird; Standardwert ist 5ms
    • --sine-amplitude, --sine-period: Amplitude und Periode der Sinus-Latenz
    • --saw-amplitude, --saw-period: Amplitude und Periode der Sägezahn-Latenz
    • --square-amplitude, --square-period: Amplitude und Periode der Rechteck-Latenz
    • --triangle-amplitude, --triangle-period: Amplitude und Periode der Dreieck-Latenz
  • Es sind auch Optionen für den Betrieb enthalten
    • --log-level: Log-Level; mögliche Werte sind DEBUG, TRACE, INFO, WARN, ERROR
    • --version: zeigt die Anwendungsversion an
  • Speedbump kann auch als Go-Bibliothek genutzt werden und wird über das Paket lib bereitgestellt
  • Die Lizenz ist die Apache 2.0 License

1 Kommentare

 
GN⁺ 2024-01-17
Meinungen auf Hacker News
  • Ich hatte mir etwas Ähnliches angesehen, um verschiedene ActivityPub-Implementierungen unter unterschiedlichen Netzwerkgrößen und -bedingungen zu testen, aber auf meinem Rechner war mit tc schon alles installiert, was ich brauchte.
    In meiner Distribution war es im Paket iproute2 enthalten; eine Beschreibung gibt es auch hier: https://wiki.archlinux.org/title/advanced_traffic_control
    Um einer bestimmten Schnittstelle Verzögerung hinzuzufügen, führt man etwa tc qdisc add dev eth0 root netem delay 100ms aus.
    Es ist einfach zu benutzen, funktioniert auch gut in Docker-Containern, kann Bedingungen wie Verzögerung, Paketverlust und Duplikate anwenden und ist möglicherweise schon installiert.

    • tc/netem/tbf sind wirklich gut. Ich habe darauf eine einfache Python-GUI gebaut und sie auf einem Pi in einem Touchscreen-Gehäuse laufen lassen; es war eine kleine schwarze Box mit Dingen wie „Paket-Drop: [0%] [1%] [10%] [50%] / Paketbeschädigung: ...“, und Kunden waren ziemlich beeindruckt.
      Es überrascht mich, dass man ähnliche Frontends als kommerzielle Hardwareprodukte kaum sieht; wenn ich bei der Suche nichts übersehen habe, scheint es sie auf dem Markt nicht zu geben.
    • Der Nachteil von tc ist, dass es etwas seltsam und umständlich ist, wenn man es auf eingehende Pakete anwenden will.
      Ich habe früher einmal selbst einen Emulator gebaut, um ein bestimmtes kommerzielles Satellitenterminal nachzuahmen. Dieses Terminal sammelte Pakete in einer Queue und stieß sie dann als Block aus, sobald ein bestimmter Schwellenwert erreicht oder ein Timeout überschritten war. Außerdem versuchte es, kleine Pakete „freundlicherweise“ nach vorne in der Queue umzusortieren, um die Latenz zu verringern, was der TCP-Stack überhaupt nicht mochte.
    • Das Gute an speedbump ist, dass man Fehlerbedingungen über die Zeit steuern kann. tc kann das nicht.
      Das kann ziemlich nützlich sein, um sich über die Zeit ändernde Wettereffekte bei Satelliten-/RF-Verbindungen zu simulieren.
  • Netflix hatte genau so etwas gebaut; es hieß latency monkey.
    Man stellte fest, dass es viel schwieriger ist zu bestimmen, ob ein nachgelagerter Dienst „langsam“ ist, als ob er „nicht verfügbar“ ist. Deshalb war es eine wichtige Methode, zu testen, wie Dienste mit Verlangsamung und Netzwerkproblemen umgehen.
    Die Implementierung war sehr simpel: Sie droppte einen konfigurierbaren Anteil der Pakete, was Retransmits erzwang, sodass Pakete auf der Gegenseite verzögert und in anderer Reihenfolge ankamen.
    Am Ende fand man dadurch viele Probleme im Fehlerbehandlungscode rund um Netzwerkzugriffe.

  • Jeder Software Engineer, der interaktive Internet-Anwendungen baut, sollte solche Tools meiner Meinung nach im Alltag unbedingt verwenden. Nicht nur TCP, sondern auch QUIC ist nötig, und um DNS abzudecken, idealerweise auch alles über UDP.
    Ich bin überzeugt, dass 90% der aufgeblähten Webapps verschwunden wären, wenn ihre Entwickler nicht nur in vergoldeten Cadillac-Computing-Umgebungen arbeiten würden.

  • In Umgebungen mit sporadisch abbrechender Verbindung, etwa bei Katastrophenhilfe, verhalten sich viele Apps miserabel.
    Es könnte anderen helfen, wenn mehr App-Entwickler intermittierende Konnektivität simulieren und testen würden.
    Aus „Toxiproxy is a framework for simulating network conditions“ (2021) https://news.ycombinator.com/item?id=29084277#29088775:

    Vielen Apps fehlt etwa die Funktion „im Postausgang zurückhalten“, die man von einem E-Mail-Client erwartet.

    • [ ] Könnte jemand eine Referenzsammlung von toxiproxy-„Testfall-Mutatoren“ erstellen, die typische Verbindungsprobleme bei #DisasterRelief simulieren?
    • Am meisten hasse ich Fälle, in denen der Puffer nicht gefüllt wird, bevor Pakete gesendet werden. Dann kommt man bei einer schlechten Internetverbindung, also einer Umgebung mit Paket-Drops und hoher Latenz, die TCP-Retransmits verursacht, plötzlich nur noch auf 120 kps.
      Denn es werden nur 50-Byte-Pakete gesendet, und davon geht eines von zehn verloren. Währenddessen kann ein Thread auf dem Server keine sinnvolle Arbeit erledigen.
  • Auf dem Mac kann man dasselbe auch nur mit Bordmitteln machen.

    # Setup pipe  
    sudo dnctl pipe 1 config bw 1Kbit/s delay 800
    
    # Setup matching pf rule  
    echo "dummynet out proto tcp from any to 127.0.0.1 port 11211 pipe 1" | sudo pfctl -f -
    
    # Turn on firewall  
    sudo pfctl -e
    
    # Test  
    time nc -vz 127.0.0.1 11211  
    Connection to 127.0.0.1 port 11211 [tcp/*] succeeded!  
    nc -vz 127.0.0.1 11211 0.01s user 0.00s system 0% cpu 1.333 total  
    
    • Dummynet und diese Funktionen stammen aus FreeBSD und gibt es dort schon lange. Ich habe vor mehr als 15 Jahren damit Paketverlust getestet, und es funktionierte gut.
  • Es gibt ein Projekt, das schon eine Weile inaktiv ist, dessen Name aber allein schon viel sagt: https://github.com/tylertreat/comcast

  • Ich habe kürzlich versucht, auf dem Mac ein langsames Netzwerk zu simulieren, und bin auf den Network Link Conditioner gestoßen; der ist ziemlich gut. Man muss keinen Proxy oder Ähnliches einrichten.
    Er muss über die zusätzlichen Tools von Xcode installiert werden.
    https://nshipster.com/network-link-conditioner/

  • Shopifys hervorragendes Tool toxiproxy ist ebenfalls einen Blick wert: https://github.com/Shopify/toxiproxy
    Es ist auch eine sehr gute Methode, um eigene Netzwerkbibliotheken zu implementieren und zu testen, weil der Stack mit den meisten ungünstigen Situationen korrekt umgehen können sollte.
    Die Idee des „Chaos Engineering“ ist großartig.

    • Ich hatte anfangs auch nach toxiproxy gesucht, aber das Client-Server-Modell passte für mich nicht, und speedbump war genau richtig für meinen Anwendungsfall der HTTP-Latenzsimulation.
      Ich entwickle eine Fortschrittsanzeige für einen Webcrawler, aber beim Testen auf localhost ist alles zu schnell, um zu erkennen, ob etwas nicht stimmt.
      Mit speedbump muss ich nur podman run --net=host kffl/speedbump:latest --latency=1s --port=8001 localhost:8000 ausführen und den Crawler unter http://localhost:8001 testen.
      Ein sauberes Tool.
  • Es gibt ein ähnliches Tool, das ich unter Windows benutzt habe.
    https://jagt.github.io/clumsy/

    • Ich habe es vor etwa zehn Jahren verwendet, um verschiedene interkontinentale Netzwerkbedingungen zu testen, und die Ergebnisse passten gut zur Realität. Empfehlenswert.
    • Sieht cool aus, aber nach den Screenshots wirkt es eher wie eine systemweite Anwendung mit Filtern als eine Anwendung pro Adapter.
  • Auch FreeBSD hat als Teil von ipfw dummynet, mit dem man Verzögerung, Bandbreitenbegrenzung, Queue-Größe und Paketverlust injizieren kann. Das ist dieselbe Funktion wie unter MacOS.

    • Ist das so etwas wie tc unter Linux?