Gepufferte Daten nach einer HTTP-CONNECT-Antwort bewahren
Vermeiden Sie einen hängenden HTTP-CONNECT-Handshake, indem Sie die Kopfzeilengrenze der Antwort finden und die danach eintreffenden Bytes aufbewahren.
Ein kleiner Proxy-Wrapper kann für HTTPS funktionieren und dann hängen bleiben, wenn er für ein Protokoll wiederverwendet wird, bei dem der Server zuerst spricht. Die verdächtige Zeile ist oft die, die wartet, bis der Empfangspuffer mit \r\n\r\n endet.
TCP gibt dem Client einen Strom. Ein Empfangsaufruf kann eine halbe HTTP-Statuszeile, eine vollständige CONNECT-Antwort oder diese Antwort unmittelbar gefolgt von Tunnel-Daten zurückgeben. Es gibt keine Zusage, dass ein Lesevorgang am Ende der Kopfzeilen endet.
Die Grenze im Puffer finden
Bei einem HTTP/1.1-CONNECT-Austausch sammeln Sie Bytes, bis der Kopfzeilen-Abschluss irgendwo im Puffer erscheint. Teilen Sie am ersten Vorkommen. Analysieren Sie Statuszeile und Kopfzeilen aus dem ersten Teil; bewahren Sie alles nach der Grenze getrennt auf. Wenden Sie beim Warten ein Größenlimit für Kopfzeilen und ein Zeitlimit an, und behandeln Sie ein leeres Socket-Lesen als geschlossene Verbindung statt als erneute Einladung zur Schleife.
Eine abschließende erfolgreiche 2xx-Antwort schaltet die Verbindung unmittelbar nach diesen Kopfzeilen in den Tunnelmodus. Ihre nachfolgenden Bytes sind bereits Tunnel-Bytes. Verwerfen Sie sie nicht, warten Sie nicht auf einen CONNECT-Antwortkörper, und deuten Sie ein Content-Length-Feld nicht als Erlaubnis, einen Teil des neuen Protokolls zu verbrauchen. Informationsantworten müssen, falls vorhanden, vor dieser abschließenden Antwort behandelt werden.
Der Wrapper muss seine Reste weitergeben
Nur den darunterliegenden Socket zurückzugeben verliert alle Bytes, die der Handshake-Parser bereits daraus gezogen hat. Der nächste Leser braucht einen gepufferten Strom, der zuerst den gespeicherten Rest liefert und dann Socket-Lesevorgänge fortsetzt. Bei einem Server-first-Protokoll kann der Verlust dieser ersten Begrüßung beide Seiten unbegrenzt warten lassen.
Umgekehrt sind Bytes aus einer fehlgeschlagenen CONNECT-Antwort keine Tunnelbegrüßung. Ein 407 gehört weiterhin zum Proxy-Austausch und erfordert eine Authentifizierungsbehandlung; ein anderer Nicht-Erfolgsstatus erfordert einen passenden Fehlerpfad.
Das ist besonders wichtig, wenn ein FTP- oder SSH-Client über einen HTTP-Proxy angepasst wird. Der Proxy muss auch den angeforderten Zielport erlauben, und FTP kann zusätzliche Datenverbindungen benötigen. Korrektes Kopfzeilen-Parsing löst die Stromübergabe; es kann keine CONNECT-Berechtigung erteilen oder den zweiten Kanal von FTP bereitstellen.