Počkejte na prázdný řádek za CONNECT
Přečtěte celou odpověď HTTP/1 CONNECT, než socket předáte TLS, i když stavový řádek dorazí první.
Klient uvidí 200 Connection Established, spustí TLS a okamžitě hlásí nesmysly tam, kde má být záznam TLS. Než obviníte nastavení šifer cíle, hledejte nedokončenou odpověď HTTP.
Při výměně HTTP/1 CONNECT je stavový řádek jen začátek odpovědi. Následovat mohou pole hlavičky. Prázdný řádek ukončující sekci hlaviček označuje přechod do tunelu po úspěšné odpovědi CONNECT.
HTTP/1.1 200 Connection Established\r\n
Proxy-Agent: example\r\n
\r\n
Tyto bajty mohou dorazit v jednom čtení, v několika čteních nebo ve čtení, které obsahuje i další bajty. TCP nezachovává hranice zápisu serveru.
Udělejte z předání explicitní stav parseru
- Sbírejte a parsujte stavový řádek. Používejte číselný stav místo přesné anglické fráze důvodu.
- Pokračujte, dokud nedorazí úplný terminátor sekce hlaviček. Úspěšný stavový řádek nenechá zbývající pole zmizet.
- U úspěšné odpovědi CONNECT považujte bajt hned za tímto terminátorem za začátek dat tunelu. U ostatních odpovědí postupujte podle příslušného zpracování odpovědi HTTP a autentizace.
- Předajte spojení a všechny nespotřebované bajty přes bufferované I/O rozhraní, které podporuje další protokol.
Poslední krok je důležitý i při dobrém hledání oddělovače. Bufferovaný čtenář mohl ze socketu spotřebovat víc, než parser požadoval. Spuštění TLS na holém socketu a opuštění tohoto čtenáře může nechat bajty uvíznuté v soukromém bufferu čtenáře.
Použijte lhůtu pro navázání a limit velikosti hlavičky. EOF před terminátorem je neúplná odpověď proxy, ne pozvánka čekat věčně nebo TLS stejně zkusit.
Promyslete několik hranic
Představte si čtení, které skončí po Proxy-Agent:. Parser stále potřebuje další bajty hlavičky HTTP. Představte si jiné, které skončí uprostřed závěrečné sekvence CRLF. To stále není úplná sekce hlaviček. A teď si představte úplnou úspěšnou sekci hlaviček, za níž ve stejném bufferu následují bajty tunelu: tyto bajty navíc musí předání přežít.
407 je jiný výsledek. Vyžaduje zpracování autentizace; neopravňuje TLS ClientHello do tunelu, který nebyl nikdy otevřen.
Upřednostněte udržovaný konektor, pokud není úkolem implementovat handshake. Tato hranice je specifická pro zde ukázanou výměnu HTTP/1. Proxy HTTP/2 nese CONNECT na streamu s jiným rámováním.