Un piccolo wrapper proxy può funzionare per HTTPS e poi bloccarsi quando viene riutilizzato per un protocollo il cui server parla per primo. La riga sospetta è spesso quella che attende che il buffer di ricezione termini con \r\n\r\n.

TCP fornisce al client uno stream. Una singola chiamata di ricezione può restituire metà di una riga di stato HTTP, una risposta CONNECT completa, o quella risposta seguita immediatamente dai dati del tunnel. Non c'è alcuna garanzia che una lettura si fermi alla fine delle intestazioni.

Trovare il limite all'interno del buffer

Per uno scambio HTTP/1.1 CONNECT, accumula byte finché il terminatore delle intestazioni non appare in qualsiasi punto del buffer. Dividi alla sua prima occorrenza. Analizza la riga di stato e le intestazioni dalla prima parte; conserva separatamente tutto ciò che segue il limite. Applica un limite di dimensione delle intestazioni e un timeout durante l'attesa, e tratta una lettura vuota del socket come una connessione chiusa anziché come un altro invito a ripetere il ciclo.

Una risposta 2xx finale riuscita porta la connessione in modalità tunnel subito dopo quelle intestazioni. I byte che la seguono sono già byte di tunnel. Non scartarli, non attendere un corpo di risposta CONNECT, e non interpretare un campo Content-Length come permesso di consumare parte del nuovo protocollo. Le risposte informative, se presenti, vanno gestite prima di quella risposta finale.

Il wrapper deve inoltrare i propri resti

Restituire solo il socket sottostante perde i byte che il parser dell'handshake ha già estratto da esso. Il lettore successivo ha bisogno di uno stream bufferizzato che restituisca prima la coda salvata e poi riprenda le letture dal socket. Per un protocollo in cui il server parla per primo, perdere quel saluto iniziale può lasciare entrambe le parti in attesa indefinita.

Viceversa, i byte di una risposta CONNECT fallita non sono un saluto del tunnel. Un 407 appartiene ancora allo scambio proxy e richiede la gestione dell'autenticazione; un altro stato non riuscito richiede un percorso di errore adeguato.

Questo conta soprattutto quando si adatta un client FTP o SSH attraverso un proxy HTTP. Il proxy deve anche consentire la porta di destinazione richiesta, e FTP può aver bisogno di connessioni dati aggiuntive. Un'analisi corretta delle intestazioni risolve il passaggio dello stream; non può concedere l'autorizzazione CONNECT né fornire il secondo canale di FTP.

Articoli correlati