End2End UDP

Die Übertragung von UDP-Paketen kann aus meiner Sicht noch wichtiger und kritischer sein als HTP, was Sie per End2End-HTTP relativ einfach bewerkstelligen können. UDP ist nicht nur ein Protokoll für DNS-Abfragen sondern insbesondere für Audio/Video in VoIP-Umgebungen. Bei Sprache und Bild macht es keinen Sinn verlorene Pakete nachzureichen, da die Zeit ja nicht stehen bleibt. Es geht um Echtzeitkommunikation. Auch Firewalls und NAT-Router verhalten sich sich bei UDP immer mal anders. Daher haben ich neben End2End-UDP3478 mit dem Sonderfall "TURN-Server" noch ein "End2End-UDP" gebaut, welches Unidirektional arbeitet.

Interessant wird dieses Netzwerkthema mit VoIP. Hier werden ja speziell UDP-Pakete mit Audio/Video-Daten gesendet, die bitte schön möglichst kontinuierlich und ohne Ausfälle übertragen werden sollen. Das klassische Monitoring mit MRTG/PRTG und anderen Mitteln hilft hier bei der Überwachung nicht, da sie zu große Abstände der Messung (meist 5 oder 10 min) haben und damit z.B. eine Unterbrechung von weniger als 1 Sek gar nicht erkennen können. Hier hilft nur eine aktive Probe, bei der UDP-Pakete mit der richtigen Größe, Anzahl und Abstand versendet und der Empfang überprüft wird. Am besten natürlich noch in beide Richtungen.

Diese Seite beschreibt ein Skript, welches sich noch in der Entwicklung befindet.

Überlegungen

Zuerst denken wir in großen Herausforderungen und ein Script, welches UDP-Pakete sendet und empfängt, könnte die Basis für ein richtiges VoIP-Assessemt werden. Dazu wäre natürlich eine zentrale Konfiguration und ein Reporting gewünscht und vielleicht sogar die Verteilung. Solche Produkte gibt es aber schon und integrieren gleich noch die Switch-Ports und Skype QoE-Daten samt grafischer Visualisierung. Wenn jemand eine Bachelor oder Master-Arbeit dazu schreiben möchte, habe ich sicher nichts dagegen. Meine Ziele sind aber einfacher und auf die Anforderungen bei Kunden bezogen.

  • Die Zeit ist nicht genau
    Schon der Versuch von einem Endpunkt die Daten an einen anderen Endpunkt zu senden und wieder zurück zu erhalten ist gar nicht einfach. Die Zeit auf allen Servern ist nicht zwingend identisch und Server laufen durchaus ein paar Millisekunden weg, bis NTP die Zeit wieder nach justiert. Ich habe das bei Skripten schon gesehen, die einen Zeitstempel senden und beim Empfänger die Differenz immer weiter zunimmt oder abnimmt. Zudem braucht auch ein Programm etwas Zeit ein UDP-Paket anzunehmen und zu verarbeiten. Der "Empfangszeitpunkt ist also etwas vor dem "Messzeitpunkt".
  • Die Richtung ist entscheidend
     Wenn ein Packet aber den Hinweg und Rückweg durchläuft, dann kann ich dennoch nicht davon ausgehen, dass die Zeit auf beiden Wege gleich ist. LAN-Leitungen nicht oft nicht symmetrisch (z.B. DSL) oder gleichmäßig ausgelastet. Daher ist mit die einzelne Richtung sogar wichtiger, z.B. besser auf jeder Seite ein Sender und Empfänger mit Auswertung. Allerdings kann dann nur der Empfänger auswerten aber nicht der Sender
  • Multi Threading?
    Nun möchte ich natürlich nicht auf jedem Endpunkt das Skript gleich mehrfach starten um mehrere Verbindungen parallel laufen zu lassen. Die Lösung sollte also mehrere Verbindungen über idealerweise einen Port bedienen können.
  • NAT-Probleme
    Bei VoIP-Übertragungen passiert es gerne mal, dass eine Richtung "Stumm" bleibt, z.B. in einer Konferenz oder mit Silence Detection. Es werden also nur Pakete in eine Richtung gesendet und die andere UDP-Richtung ist ungenutzt. Dennoch darf eine Firewall hier den zweiten Kanal nicht nach einiger Zeit aus seiner Sessiontable löschen. Daher soll End2End-UDP auch diesen Fall abdecken, indem Endpunkt 1 ein Paket an Endpunt2 sendet und damit die Verbindung aufbaut aber dann nur noch Endpunkt2 zurücksendet. Bricht die Verbindung dann irgendwann ab, da von Endpunkt 1 kein Paket mehr an Endpunkt 2 geht ?
  • Auswertung am Empfänger - Reporting Zentral
    Ich denke, dass der Sender in der UDP-Payload vielleicht einen Zeitstempel, eine Sequence-Nummer und die Senderate (Zeit zwischen Paketen) übermittelt. Anhand dieser Werte kann der Empfänger dann relativ einfach fehlende Pakete, falsche Reihenfolge, Jitter und Gesamtlaufzeit ermitteln und als Mittelwerte an eine zentrale Stelle liefern.
  • Zentraler Controller und Report-Empfänger
    Alle Module sollten von einem zentralen Service ihre Konfiguration erhalten, d.h. an wen sie Daten senden und von wem Sie Daten annehmen sollen. Über den gleichen Weg kann auch eine Rückmeldung bei Fehlern kommen.

Dies ist nur eine erste Näherung an die Aufgabenstellung. Die Grundlagen zum Senden und Empfangen von UDP-Paketen habe ich ja schon beschrieben:

Funktion

Das Skript ist wieder mal ein PowerShell-Code geworden, welcher über Parameter umfangreich steuerbar ist. Das Skript kann als Client oder Server arbeiten und der Server kann sogar mehrere Clients bedienen. Ein Client kann auch mehrere Server ansprechen. Aber nur der Server erfasst die Daten und speichert sie in einer CSV-Datei. Dabei gibt es zwei Betriebsarbeiten zu unterscheiden.

  • Normalbetrieb
    Der Client sendet und der Server empfängt und wertet aus. Das ist der Regelfall, wenn ich Verbindungen überwachen will
  • NAT-Test
    Dies ist ein Sonderfall, bei den sowohl der Client als auch der Server mit dem Parameter "natkey" und dem gleichen Wert gestartet werden. In dem Fall sendet der Client ein Paket zum Server und der Server liefert dann Pakete zum Client. Der Client erfasst dann die Daten und schreibt Sie weg.

Ob das Programm als Client oder Server fungiert, wird über den Parameter "RemoteServer" gesteuert. Schauen wir uns die Parameter einfach einmal an:

Parameter Default Beschreibung

[string[]]$RemoteServer

$null

Hier wird der DNS-Name oder die IP-Adresse (auch Plural) angegeben, an die das Skript die UDP-Pakete senden soll. Sobald der Parameter genutzt wird, arbeitet das Skript im "Client-Mode"

[string]$natkey

$null

Wird hier ein Wert angegeben, dann schaltet das Skript in den NAT-Mode um, wobei beide Endpunkte den gleichen String verwenden müssen. Der "Client" ist wieder das Skript, bei dem auch "RemoteServer" gefüllt ist und er sendet ein Paket an den RemoteServer. Der RemoteServer aber sieht den Key in diesem Paket und sendet nun seinerseits Daten an den Client zur Auswertung

[string]$listenudpport

50000

Auf diesem Port öffnet der Server (oder Client im NAT-Betrieb) einen Listener und nimmt Pakete entgegen.

[string]$sourceudpport

$null

Mit diesem SourcePort sendet der Client (oder Server im NAT-Betrieb) seine Pakete weg. Wird kein Port angegeben, dann wird der ListenerPort genutzt.

[string]$remoteudpport

50000

Dies ist der Zielport der Gegenseite, an den der Client oder Server im NAT-Betrieb die Pakete sendet

[long]$idletime

100

Diese Zeit (in Millisekunden) lässt der Sender zwischen jeder Verarbeitung vergehen. Der Abstand der Pakete ist daher etwas größer, wenn er mehr Pakete zu senden hat

[string]$logdirectory

".\"

Hier können Sie den Pfad angeben, in dem das Skript de Ergebnisse protokolliert. Um Platz zu sparen, werden nur Zeiten geschrieben, wenn es Aussetzer gegeben hat

[byte]$warn1sec

2

Wenn das älteste Paket vor mehr als 2 Sekunden empfangen wurde, dann wird eine gelbe Warnung protokolliert.

[byte]$warn2sec

5

Wenn das älteste Paket vor mehr als 5 Sekunden empfangen wurde, dann wird eine rote Warnung protokolliert

[byte]$inactivesec

60

Wenn so lange von einem Client nichts mehr kommt dann werden die Warnungen eingestellt und der Client aus der Liste gestrichen.

[switch]$detailed

$false

Aktiviert eine erweiterte Ausgabe der Aktionen zwecks Fehlersuche

Beispiel "Normal Mode"

Am einfachsten ist die Funktion mit zwei Bildern zu sehen.

  • Client (Erkennbar am RemoteServer)
    Das erste Bild zeigt den Sender, der mit Port 50001 als Quelle an den Port 50000 der Gegenseite sendet. Der Listenport kommt hier nicht zum Einsatz aber Port 50.000 war schon durch das anderes belegt. Sie sehen für jedes gesendete Paket ein "S"
  • Server
    Auf der anderen Seite wartet das Skript auf eingehende Pakete. Es wurde ganz ohne Parameter gestartet und lauscht damit auf Port 50000. Sie sehen hier einige "grüne" R (Receive) aber auch einige gebe "2" und rote "5"-Zeichen. Die sagen aus, dass hier 2 oder mehr Sekunden oder sogar 5 oder mehr Sekunden keine Pakete angekommen sind

Die Aktionen auf der Empfängerseite werden natürlich in einer CSV-Datei geloggt, die das Datum und die Stunde (TUC-Zeit) als Dateinamen verwendet.

Beispiel NAT Mode

In der Betriebsart NAT ändert sich die Anzeige.

  • Client (Erkennbar am RemoteServer
    Der Client sendet am Anfang den NATEY als Startzeichen zum Server aber dann schaltet er in den Empfangsmode um. Hier ist wichtig, dass der ListenPort und der SourceUDPPort identisch sind

    Auch hier ist zu sehen, dass einmal eine Pause für 2 Sekunden und dann sogar 4x 5 Sekunden hintereinander aufgetreten sind
  • Server
    Der Server hingegen meldet den Eingang der NAT-Anforderung und startet den Versand an die erkannte Quell-IP und Port.

Hinweis: Ich habe den Test auf einen Computer über "Localhost" gemacht. Paketverluste habe ich einfach dadurch provoziert, dass ich im Fenster des Sender mit der Maus etwas Text markiert und damit den Prozess angehalten habe.

Beim NAT-Mode ist natürlich etwas störend, wenn man keinen Zugriff auf die entferne Seite hat.

Download und Aufruf

Kein Download

Ich habe diesen End2End-Sensor für Tests und Evaluierungen von UDP-Verbindungen über direkte Verbindungen und NAT-Verbindungen genutzt aber das Skript hat nicht den Status erreicht, dass ich es hier veröffentlichen kann. Es hat sich vielmehr überholt, da die meisten A/V-Probleme mittlerweile in Zusammenhang mit Microsoft Teams zu analysieren sind und ich dazu das Skript End2End-UDP3478 und von mir insbesondere Rimscout eingesetzt wird

Weitere Links