HTTP Keep-alive
Der Inhalt der Seite war erst nur ein Kapitel der Seite TCP Session Timeout aber sehr schnell hat sich gezeigt, dass das Kapitel zu umfangreich wurde. Ich beschreibe die Hintergründe von HTTP-Verbindungen, welche über die Optionen Keep-Alive auch länger bestand haben können.
Beachten Sie dazu auch HTTP Chunked und TCP Session Timeout
Der Anfang von Keep-alive
In den Anfangszeiten von HTTP bestand ein HTTP-Request aus dem Aufbau der TCP-Verbindung, der Anfrage und Antwort und kurz darauf dem Abbau der Verbindung. Das hat kostbare "Connections" auf dem WebServer gespart aber zu mehr Datenvolumen und längerer Antwortzeit geführt. Schon sehr früh wurde daher überlegt, wie man mehrere HTTP-Requests über eine einmal aufgebaute TCP-Verbindung führen kann. Mit der Nutzung von HTTPS ist es noch wichtiger, dass eine einmal etablierte "kostbare" TLS-Verbindung samt Zertifikatsübertragung und Prüfung nicht gleich wieder verworfen wird.
So wurde im HTTP-Header das Feld "Connection: keepalive" definiert, mit dem der Client dem Server sagen kann, dass die Verbindung nach der Antwort nicht abgebaut werden soll und weitere Anfragen sequentiell folgen können. Mit HTTP 1.1 wurde festgelegt, dass alle Verbindungen per Default "Persistent" sind, es sei denn ein Headereintrag fordert etwas anderes. Die Verbindung bleibt solange bestehen, bis eine der beiden Seiten die TCP-Verbindung abbaut. Es gibt im HTTP-Protokoll keinen Mechanismus, um per HTTP ein Platzhalter-Paket zu senden, um die Verbindung aufrecht zu erhalten. Das ist wieder Aufgabe des TCP-Stacks und das können auch mal 2 Stunden bis zum nächsten Keep-alive sein. Allerdings kann ein Client natürlich einfach einen HTTP-Request selbst absetzen um irgend etwas zu übertragen.
Allerdings sollte ein WebServer mit einem "Connection: keep-alive" antworten, damit der Client dies weiß und die Verbindung beibehält.
Hinweis:
In HTTP 1.1, all connections are considered persistent unless declared otherwise.
The HTTP persistent connections do not use separate keepalive messages, they
just allow multiple requests to use a single connection. However, the default
connection timeout of Apache httpd 1.3 and 2.0 is as little as 15 seconds and
just 5 seconds for Apache httpd 2.2 and above.
Quelle:
https://en.wikipedia.org/wiki/HTTP_persistent_connection
Keep-Alive im Trace
Hier eine Anfrage per "Invoke-WebRequest" und die Antwort des WebServers, der trotz HTTP 1.1 auch noch einen "Connection" und "Keep-Alive"-Header mit sendet.
Der WebServer schlägt hier also einen Timeout von 15 Sekunden vor. Wenn ich die Anfrage immer wieder mache, dann sehe ich in meinem Wireshark die entsprechenden Pakete und Source Ports. Wenn ich nach mehr als 15 Sekunden warte, dann startet der Client eine neue Verbindung.
Schaue ich mir die TCP-Handshake-Meldungen zu der ersten Verbindung an, dann sehe ich den Handshake, die Zwischenquittungen auf die Anfragen und dass ca. 69 Sekunden nach der letzten Quittung der Webserver die Verbindung abbaut.
Er hält sich also selbst nicht an seine Vorgabe von 15 Sekunden. Diese Information brauchen wir aber später noch für eine Analyse. Zuerst möchte ich aber einfach ein paar Gegenstellen analysieren, Wie sie auf einen HTTP-Request reagieren. Liefern Sie einen "Connection: Keep-alive", welcher Timeout wird vom Server vorgegeben und wer baut wann die Verbindung ab.
Outlook und Keep-alive
Wenn Sie sich Outlook gegen Office 365 anschauen, dann sehen Sie keinen "Connection: Keep-alive" in der Antwort. Hier kommt dann "chunked" zum Einsatz. Mehr Details finden Sie dazu auf HTTP Chunked:
Damit meldet der Server, dass noch Daten nachkommen können. Quasi "Streaming". Auch Fiddler zeigt das entsprechend an. Es gibt zwar schon einem 200 OK aber da die Transaktion noch nicht abgeschlossen ist, wird der Code nicht angezeigt und das Symbol für einen offenen Download vorangestellt.
Auch in dem Fall ist es natürlich interessant, wie der darunterliegende TCP-Stack damit umgeht. Sowohl der Client als auch der Server könnte ja die Verbindung abbauen. In der Regel wird sie aber eben nicht durch den Endpunkte abgebaut. Damit sind diese Verbindungen dem Risiko ausgesetzt, dass jemand anderes den TCP-Kanal kappt.
Nicht alle WebServer unterstützen Keep-Alive oder melden es nicht. Teilweise kann ich es verstehen, wenn die Seite sowieso direkt eine Umleitung auf ein Anmeldeseite unter einer anderen URL oder eine Wechsel auf HTTPS mit einem anderen Port forciert. Dann ist es sicher besser die "falsche" Verbindung nicht aufrecht zu halten.
Test mit Gegenstellen
Ich habe die Aufrufe in der PowerShell mit "(Invoke-webrequest <url> -UseBasicParsing).headers" ausgeführt, um gleich die Header zu sehen und mit BasicParsing weitere Umleitungen, JavaScript u.a. Dinge zu vermeiden. Parallel habe ich mit Wireshark die TCP-Verbindung aufgezeichnet und gewartet, bis Sie abgebaut wird.
Gegenstelle | Connection: Keep-alive | Keep-alive | Transfer-encoding: chunked | FIN-Zeit | Ergebnis |
---|---|---|---|---|---|
Synology DS216J-NAS (lokal) |
Ja |
20 Sek |
Nein |
65 Sek |
Die Webverwaltung des NAS unterstützt Keep-alive mit 20 Sekunden und beendet die Verbindung nach ca. 65 Sekunden |
Ja |
15 Sek |
Nein |
15 Sek |
Die Apache Webserver von 1und1 nehmen es sehr genau und beenden die Verbindung direkt nach 15 Sekunden |
|
Nein |
Nein |
Nein |
0 Sek |
Microsoft liefert hier einen "302 Moved
Permanently" und beendet die TCP-Verbindung
sofort aktiv |
|
Nein |
Nein |
Ja |
100 Sek |
Eine TCP-Session wird von Google nach 100 Sekunden abgebaut |
|
Nein |
Nein |
Nein |
100 Sek |
Diesmal ist es hier aber mein Client, der die Verbindung abbaut. Interessant, da Invoke-WebRequest vom Server nicht über einen Timeout-Header
dahingehend angewiesen wurde. |
Ich fand es schon überraschend, dass die Office 365 Dienste weder Keep-Alive noch Chunked nutzen. Allerdings ist diese Auswertung aus irreführen, da die Funktion durch den WebService auf der anderen Seite individuell pro Request gesteuert werden kann. Wenn ich mit Fiddler nachschaue, wie mein Outlook oder Smartphone mit Office 365 spricht, dann kommt dort natürlich "Chunked" zum Einsatz. Insofern sind solche einfachen Tests nur bedingt aussagekräftig.
Rauswurf mit "Close"
Aber es gibt auch das andere Extrem, dass eine Gegenstelle ein "Connection: close" vorgibt. Das passiert bei einem ADFS-Server z.B. im Fehlerfall:
So kann sich ein WebServer ganz schnell von Verbindungen befreien, bei denen wohl keine weiteren Zugriffe zu erwarten sind.
Ein Grund könnte aber auch sein, dass der Client zu viele Zugriffe parallel startet. Der meist genutzte Client dürfte ein Browser sein und hier haben die verschiedenen Hersteller eigene Werte hinterlegt. So nutzt der IE8 und höher bis zu 6 parallele persistente Verbindungen, die aber bei Inaktivität nach 60 Sekunden abgebaut werden. Hier sollten Sie also nie in das Problem laufen, dass eine Verbindung zu früh durch Transfersysteme gekappt wird. Firefox baut seine Verbindungen nach 115 Sekunden wieder ab. Die Zahl ist knapp unter den 120 Sekunden, die Microsoft für Office 365 Verbindungen empfiehlt.
- HTTP Chunked
- Cloud NAT/Proxy
- Invoke-Webrequest - Parameter "DisableKeepAlive"
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-webrequest?view=powershell-6 - HTTP persistent connection
https://en.wikipedia.org/wiki/HTTP_persistent_connection - Chunked transfer encoding
https://en.wikipedia.org/wiki/Chunked_transfer_encoding - Persistent Connection Behavior of Popular Browsers (Sehr
alter Stand)
http://pages.cs.wisc.edu/~cao/papers/persistent-connection.html
Weitere Links
- HTTP Chunked
- TCP Session Timeout
- TCP SYN ACK RES
- TCP Retransmit Monitoring
- Packet Loss
- Outlook TCP-Connections
- TCP Retransmit Monitoring
- Cloud Verbindung
- Network Perimeters & TCP Idle session settings for Outlook on Office 365
https://blogs.technet.microsoft.com/onthewire/2014/03/04/network-perimeters-tcp-idle-session-settings-for-outlook-on-office-365/ - For Exchange 2010, 2013, and 2016 do this before calling
Microsoft
https://blogs.technet.microsoft.com/david231/2015/03/30/for-exchange-2010-and-2013-do-this-before-calling-microsoft/ - Things that you may want to know about TCP Keepalives
https://blogs.technet.microsoft.com/nettracer/2010/06/03/things-that-you-may-want-to-know-about-tcp-keepalives/ - How to troubleshoot non-browser apps that can’t sign in to
Office 365, Azure, or Intune
https://support.microsoft.com/en-us/help/2637629/how-to-troubleshoot-non-browser-apps-that-can-t-sign-in-to-office-365 - Requirements for Internet Hosts -- Communication Layers
4.2.3.6 TCP Keepalives
https://tools.ietf.org/html/rfc1122#page-101 - Appendix A: TCP/IP Configuration Parameters
https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc739819 - Keepalive - Wikipedia
https://en.wikipedia.org/wiki/Keepalive - Ryte WIki Keep-Alive
https://de.ryte.com/wiki/Keep-Alive - Bedeutung von HTTP-Headern
https://schepp.GitHub.io/HTTP-headers/#/ - Cloudflare: When TCP sockets refuse to die
https://blog.cloudflare.com/when-tcp-sockets-refuse-to-die/