Aspettate la riga vuota dopo CONNECT
Leggete la risposta HTTP/1 CONNECT completa prima di consegnare il socket a TLS, anche quando la riga di stato arriva per prima.
Il client vede 200 Connection Established, avvia TLS e segnala subito assurdità dove dovrebbe esserci un record TLS. Cercate una risposta HTTP incompleta prima di dare la colpa alle impostazioni di cifratura della destinazione.
In uno scambio HTTP/1 CONNECT la riga di stato è solo l'inizio della risposta. Dopo possono arrivare campi di intestazione. La riga vuota che chiude la sezione di intestazione segna il passaggio al tunnel dopo una risposta CONNECT riuscita.
HTTP/1.1 200 Connection Established\r\n
Proxy-Agent: example\r\n
\r\n
Quei byte possono arrivare in una lettura, in più letture o in una lettura che contiene anche i byte successivi. TCP non conserva i confini di scrittura del server.
Rendete la consegna uno stato esplicito del parser
- Raccogliete e analizzate la riga di stato. Usate lo stato numerico invece di una frase di motivo inglese esatta.
- Continuate finché non è arrivato il terminatore completo della sezione di intestazione. Una riga di stato riuscita non fa sparire i campi rimanenti.
- Per una risposta CONNECT riuscita, considerate il byte subito dopo quel terminatore come inizio dei dati del tunnel. Per le altre risposte seguite la gestione appropriata di risposta HTTP e autenticazione.
- Trasferite la connessione e i byte non consumati tramite l'interfaccia I/O con buffer supportata dal protocollo successivo.
L'ultimo passo conta anche con una buona ricerca del delimitatore. Un lettore con buffer può aver consumato più socket di quanto abbia chiesto il parser. Avviare TLS sul socket nudo abbandonando quel lettore può lasciare byte bloccati nel buffer privato del lettore.
Usate una scadenza per la configurazione e un limite di dimensione dell'intestazione. Un EOF prima del terminatore è una risposta proxy incompleta, non un invito ad aspettare per sempre o a provare TLS comunque.
Ragionate su diversi confini
Immaginate una lettura che finisce dopo Proxy-Agent:. Il parser ha ancora bisogno di byte di intestazione HTTP. Immaginate un'altra che finisce a metà della sequenza CRLF finale. Non è ancora una sezione di intestazione completa. Ora immaginate una sezione di intestazione completa e riuscita seguita da byte di tunnel nello stesso buffer: quei byte in più devono sopravvivere alla consegna.
Un 407 è un esito diverso. Richiede la gestione dell'autenticazione; non autorizza un TLS ClientHello dentro un tunnel che non è mai stato aperto.
Preferite un connettore mantenuto, a meno che implementare l'handshake non sia il compito. Questo confine è specifico dello scambio HTTP/1 mostrato qui. Un proxy HTTP/2 trasporta CONNECT su uno stream con un framing diverso.