TCP Retransmit Monitoring

Jede Nutzung von Diensten über TCP/IP ist abhängig von der Zuverlässigkeit der Verbindung. Verlorene Pakete, und dazu zählen lange Laufzeiten ebenso, sind immer unerwünscht und ein Zeichen einer schlechten Leitung. Nur wir kann ein normaler Anwender oder auch jemand im Support solche Daten ermitteln? Im Idealfall könnte er mit WireShark u.a. die Pakete analysieren aber das ist oft schon Spezialwissen. Windows selbst hat aber einen passenden Performance Counter.

TCP SYN und ACK

Im Gegensatz zu UDP oder ICMP ist TCP eine "gesicherte Verbindung". Das bedeutet zwar nicht automatisch "verschlüsselt" aber zumindest gegen Paketverluste sichert das TCP-Protokoll die Daten ab. Dazu gibt es ein Handshake-Protokoll, bei dem ein gesendetes Paket von der anderen Seite mit einer Antwort oder Quittung bestätigt wird. Bleibt diese Bestätigung aus, nimmt der Sender von einem Paketverlust an und sendet das Paket erneut. Ein Antwortpaket einer bidirektionalen Verbindung der Gegenseite muss der Sender natürlich auch quittieren oder beantworten. Nur eine Quittung selbst wird nicht quittiert. Der Verlust einer Quittung wird erkannt, wenn die Folgepakete gesendet werden und die darin enthaltene "Sequence Number" nicht passt.

Die Zeit, nach dem ein Paket quittiert werden muss ist nicht statisch, sondern muss natürlich dynamisch auf die Laufzeit der Pakete angepasst werden. In einem internen LAN verhandeln die Partner daher eher kurze Zeitfenster. Bei einer Verbindung um den halben Globus, bei dem ein Paket schon in eine Richtung 200ms und mehr unterwegs ist, werden längere Fristen genutzt. Fakt ist aber, dass die beiden Partner immer über den Status ihrer Verbindung im Klaren sind.

Fehler der Verbindung erkennen

Natürlich kann es Fehler bei Verbindungen geben. Hierbei sind zwei Fälle zu betrachten:

  • Paketverlust
    Es kann durchaus sein, dass ein Paket "verloren" geht. Dann muss der Sender diese erkennen und das Paket erneut senden. Wenn man mal von Funkstrecken ausgeht, sollten Pakete aber nie verloren gehen. Die Zeiten von Kollisionen (CSMA-CD) auf BNC-Kabeln sind mit Switches und Router eigentlich hinfällig. Ein Paketverlust passiert also eher dann, wenn ein Router ein Paket aufgrund einer Überlastungsituation (Queue voll) absichtlich verwirft. Das ist dann natürlich schon wieder interessant für eine Auswertung, denn dieses Paket wird vom Client erneut gesendet und kostet damit zumindest auf einer Teilstrecke zweimal Übertragungsleistung. Das möchte man eigentlich verhindern.
  • Verbindungsverlust
    In dem Fall können die beiden Parteien die Verbindung nicht weiter aufrecht erhalten, z.B.: wenn eine Seite ungeplant "offline" gegangen ist. Gerade mobile Geräte verlieren oft die Funkverbindung (WLAN, GSM) oder werden aus einer Dockingunit gezogen. Die Verbindungen werden zwar oft umgehend wieder aufgebaut aber mit einer neuen IP-Adresse ist es ein Neuaufbau und es dauert einige Minuten, bis die alte Verbindung auf der verbliebenen Seite weggeräumt wird

Während die Verbindungsverluste zwar schon interessant sein können finde ich die Paketverluste viel aussagekräftiger. Gerade wenn eine Verbindung eigentlich "stabil" ist, ist dieser Counter über die Zeit ein guter Indikator für Probleme beim Netzwerk. Gerade kurzfristige Überlastsituationen sind so auf dem Client recht gut zu erkennen.

Leider sind diese Counter nur auf dem Client zu finden, der auch die Verbindung hält. Eine Überwachung "auf der Leitung", also z.B. an der Firewall o.ä. ist ungleich schwerer aber technisch denkbar, wenn die Firewall den Session-Status mitführt und Timeouts erkennt und erfasst.

Die Counter auf dem Client sind problemlos mit Perfmon zu finden. Hier exemplarisch auf einem Windows 2012R2 Server, der als VPN-Server aus dem Internet erreichbar ist.

Über einen zeitlichen Verlauf ist durchaus zu sehen, dass die ein oder anderen Pakete erneut übertragen werden. In dem Beispiel wird IPv4 häufiger genutzt als IPv6 aber is auf den Peak in der Mitte sind die Retransmits bei IPv4 und IPv6 nahe beieinander.

Ich habe hier leider nicht die Zahlen zur Auslastung der Netzwerkkarte überlagert, da diese ja dann auch nur für den Server aussagekräftig sind. Es könnte aber interessant sein, die Auslastung der WAN-Anbindung dazu anzuzeigen. Hierbei könnte man wohl schon eher Rückschlüsse auf Engpässe auf dem zweiten Hop schließen.

Leider ist per Perfmon keine Analyse pro Endpunkt oder Ziel möglich. Clients und Server haben ja in der Regel viele Verbindungen zu anderen Systemen. Einige davon sind über ein WAN angebunden während andere Systeme im LAN sind und eher kein Probleme haben sollten. Insofern würde ich den Counter zumindest als Vorwarnung oder zusätzlichem Indikator mit beobachten.

Leider ist es ein "Pro Sekunde" Counter und keine Aufsummierung der erneut gesendete Pakete. Wer die Daten also auswertet muss quasi im Sekundentakt mitlesen. Es reicht nicht alle paar Minuten mal nachzuschauen und die Differenz zu bilden. Per PowerShell geht das ja recht einfach

(Get-Counter "\TCPv4\erneut übertragene segmente/s").countersamples[0].cookedvalue

Das ist natürlich nur eine einmalige Abfrage. Interessanter wird es die Abfrage zu "sammeln"

Get-Counter `
   -Counter "\TCPv4\erneut übertragene segmente/s" `
   -SampleInterval 1 `
   -MaxSamples 60

Dieser Aufruf sammelt im Abstand von 1 Sekunde die Counter bis er 60 Messwerte zusammen hat. Im Idealfall also 1 Minute. Die Messung kann man auch direkt auswerten

Get-Counter `
   -Counter "\TCPv4\erneut übertragene segmente/s" `
   -SampleInterval 1 `
   -MaxSamples 60 `
| %{$_.countersamples[0].cookedvalue} `
| Measure-Object -Average -Maximum -Minimum -Sum

Count    : 60
Average  : 1,57075686692718
Sum      : 94,2454120156305
Maximum  : 6,60186012816069
Minimum  : 0
Property :

Aus diesem kleinen Einzeiler könnte man vermutlich sehr schnell ein Analysewerkzeug schaffen, welches auf einem Server bei Bedarf aktiviert werden könnte, z.B. in der Form:

(1..1440 `
| %{ Get-Counter `
      -Counter "\TCPv4\erneut übertragene segmente/s" `
      -SampleInterval 1 `
      -MaxSamples 60 `
| %{$_.countersamples[0].cookedvalue} `
| Measure-Object -Average -Maximum -Minimum -Sum
}) | export-csv retransmit.csv -notypeinformation

Dieses Skript läuft nun ziemlich genau einen Tag (1440 Minuten) und erfasst jeweils 60 Messwerte mit 1 Sekunde abstand um die Mittelwert, Minimum und Maximum letztlich in eine CSV-Datei für die weitere Auswertung zu schreiben. Dieses Skript können Sie per Taskplaner einfach beim Start des Computers und dann jede Nacht wieder starten lassen und später bei Problemen schauen, ob es Übereinstimmungen gibt.

Die Aussagekraft der Ergebnisse hängt natürlich auch davon ab, wie viele Pakete real übertragen wurden. Die Retransmits sollten also immer in Relation zur Gesamtzahl der Pakete gesehen werden. Zudem werden nur TCP-Pakete betrachtet. Ein Server der aufgrund eines Netzwerkausfalls gar keine Anfragen bekommt und daher auch nicht antworten muss, kann auch keine Wiederholungen ausgeben. Die Daten sind also auf einem Client eher sinnvoll zu erfassen, da hier der Zeitpunkt einer von Anwender gemeldeten Störung dann auch auf diese Werte abgebildet werden kann.

NETSTAT

Auch die Kommandozeilenapplikation Netstat, liefert zusätzliche statistische Daten für die Fehlersuche. Die Kurzform auf einem deutschen Windows 7 System ist:

C:\>netstat -s | findstr "Erneut"
  Erneut übertragene Segmente         = 170768
  Erneut übertragene Segmente         = 139

Die erste Zeile ist für IPv4, die zweite für IPv6. Das ist hier so nicht sichtbar aber wenn Sie "Netstat -s" ohne Filter starten, dann sehen Sie umfangreiche Statistiken. Hier ein Auszug.

C:\Users\fcarius>netstat -s

IPv4-Statistik

  Empfangene Pakete                    = 23634444
  Empfangene Vorspannfehler            = 0
  Empfangene Adressfehler              = 2166
  Weitergeleitete Datagramme           = 0
  Empfangene unbekannte Protokolle     = 1
  Empfangene verworfene Pakete         = 502720
  Empfangene übermittelte Pakete       = 23982687
  Ausgabeanforderungen                 = 10886350
  Verworfene Routingpakete             = 0
  Verworfene Ausgabepakete             = 14864
  Ausgabepakete ohne Routing           = 567
  Reassemblierung erforderlich         = 132
  Reassemblierung erfolgreich          = 66
  Reassemblierung erfolglos            = 0
  Erfolgreiche Datagrammfragmentierung = 0
  Erfolglose Datagrammfragmentierung   = 0
  Erzeugte Fragmente                   = 0

IPv6-Statistik

  Empfangene Pakete                    = 324011
  Empfangene Vorspannfehler            = 0
  Empfangene Adressfehler              = 103
  Weitergeleitete Datagramme           = 0
  Empfangene unbekannte Protokolle     = 0
  Empfangene verworfene Pakete         = 90404
  Empfangene übermittelte Pakete       = 329683
  Ausgabeanforderungen                 = 134892
  Verworfene Routingpakete             = 0
  Verworfene Ausgabepakete             = 74
  Ausgabepakete ohne Routing           = 1
  Reassemblierung erforderlich         = 4
  Reassemblierung erfolgreich          = 2
  Reassemblierung erfolglos            = 0
  Erfolgreiche Datagrammfragmentierung = 0
  Erfolglose Datagrammfragmentierung   = 0
  Erzeugte Fragmente                   = 0

ICMPv4-Statistik

                            Empfangen Gesendet
  Meldungen                 16578       72495
  Fehler                    0           0
  Ziel nicht erreichbar     5479        61384
  Zeitüberschreitung        150         0
  Parameterprobleme         0           0
  Quelldrosselung           0           0
  Umleitungen               0           0
  Echoantworten             10836       112
  Echos                     113         10999
  Zeiteinträge              0           0
  Zeiteintragantworten      0           0
  Adressmasken              0           0
  Adressmaskenantworten     0           0
  Routeranfragen            0           0
  Routerankündigungen       0           0

ICMPv6-Statistik

                            Empfangen   Gesendet
  Meldungen                 2741        44453
  Fehler                    0           0
  Ziel nicht erreichbar     5           8
  Paket zu groß             0           0
  Zeitüberschreitung        0           0
  Parameterprobleme         0           0
  Echos                     1           0
  Echoantworten             0           1
  MLD-Abfragen              0           0
  MLD-Berichte              6           0
  MLD-Beendigungen          0           0
  Routeranfragen            0           2576
  Routerankündigungen       1012        0
  Nachbaranfragen           57          41725
  Nachbarankündigungen      1660        143
  Umleitungen               0           0
  Routerneunummerierungen    0           0

TCP-Statistik für IPv4

  Aktiv geöffnet                      = 322061
  Passiv geöffnet                     = 277
  Erfolglose Verbindungsversuche      = 87360
  Zurückgesetzte Verbindungen         = 152615
  Aktuelle Verbindungen               = 66
  Empfangene Segmente                 = 21519133
  Gesendete Segmente                  = 9309219
  Erneut übertragene Segmente         = 170707

TCP-Statistik für IPv6

  Aktiv geöffnet                      = 404
  Passiv geöffnet                     = 315
  Erfolglose Verbindungsversuche      = 480
  Zurückgesetzte Verbindungen         = 232
  Aktuelle Verbindungen               = 2
  Empfangene Segmente                 = 11506
  Gesendete Segmente                  = 11438
  Erneut übertragene Segmente         = 139

UDP-Statistik für IPv4

  Empfangene Datagramme = 2016516
  Keine Anschlüsse      = 265357
  Empfangsfehler        = 235968
  Gesendete Datagramme  = 1361368

UDP-Statistik für IPv6

  Empfangene Datagramme = 140560
  Keine Anschlüsse      = 29256
  Empfangsfehler        = 61158
  Gesendete Datagramme  = 64510

Monitoring

Aktuell habe ich ein entsprechendes Monitoring noch nicht als eigenständiges Skripte umgesetzt. Ich beobachte dazu einige Zeit lang mal meine eigenen Erfahrungen auf meinem Client. Ich könnte mir aber gut vorstellen, dass eine Komponente auf einem Client solche Daten sehr gut erfassen und auch zentral melden kann. Gerade mit der Zunahme der Cloud und Heimarbeitern sehe ich einen Mehrwert, wenn die IT diese Daten erhalten kann und damit z.B. Orte mit schlechteren TCP-Verbindungen lokalisieren kann.

Allerdings beziehen sich diese Daten immer nur auf TCP-Verbindungen. Die aus meiner Sicht kritischeren UDP-Verbindungen, die bei Skype for Business und Microsoft Teams in Verbindung mit Audio und Video zum Einsatz kommen, werden durch diesen Counter nicht erfasst. Hier sind dann wieder die QoE-Reports durch den Client selbst relevant.

Analyse auf dem Kabel ?

Jede Überwachung auf dem Client ist natürlich von der Mitarbeit des Clients abhängig. Als Netzwerkadmin wünscht man sich natürlich eine Option solche Fehler auf dem "Kabel" oder dem Router zu messen. Technisch sollte das auch recht einfach sein, wenn man z.B. mit WireShark oder anderen Tools einfach die Pakete mitschneidet und die "Retransmit" sucht. Das macht z.B. WireShark schon von alleine und über diesen Weg könnte man auch gleich die IP-Adresse der Quelle und des Ziels samt Port ermitteln.

Auf diese Idee sind schon diverse Tools und Hersteller gekommen. Meine Liste ist sicher nicht repräsentativ. Aus meiner Sicht sollte es aber für jede Firewall ein leichtes sein, zu den TCP-Sessions, die solche Geräte sowieso pflegen müssen, entsprechende Daten zu erfassen und z.B. per NetFlow/IPFix bereit zu stellen. Vielleicht macht ja auch Microsoft in Office 365 so etwas um die Qualität der Anbindung verschiedener Bereiche zu überwachen. Es wäre zumindest ein "Vorwarnsignal", wenn diese erneuten Übertragungen plötzlich ansteigen.

Ich habe bislang noch keine solche Analyse-Werkzeuge selbst genutzt oder bei Kunden gesehen. Ich würde mich über Rückmeldungen meiner Leser zu meinen Einschätzungen freuen.

Weitere Links