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

  1. Sbírejte a parsujte stavový řádek. Používejte číselný stav místo přesné anglické fráze důvodu.
  2. Pokračujte, dokud nedorazí úplný terminátor sekce hlaviček. Úspěšný stavový řádek nenechá zbývající pole zmizet.
  3. 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.
  4. 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.

Související články