Hello, I came upon a Squid proxy configured with "cache_peer ssl" (i.e., peer->use_ssl is true). The proxy forwards GETs to the peer using an SSL connection because forward.cc code knows that "SSL peers" need an SSL connection and establishes such a connection. This works well.
However, when the proxy receives a CONNECT request, it diverts the request to tunnel.cc. Tunnel.cc is aware of peer selection logic but lacks the code that establishes an SSL connection to SSL peers. Squid establishes a regular TCP connection to the SSL peer. The SSL peer receives a plain CONNECT request from Squid instead of the expected SSL handshake and closes the connection with an error. Here are my top three choices for the fix: 1) Teach tunnel.cc code to establish SSL connections to SSL peers, like forward.cc does. This design is straightforward, but duplicates significant (and sometimes rather complex) portions of forward.cc code. For example, FwdState::initiateSSL() and FwdState::negotiateSSL() would need to be duplicated (with the exception of SslBump code). 2) Remove peer selection (and SSL peer connection) code from tunnel.cc. Pass CONNECT requests to forward.cc and allow forward.cc to call tunnelStart() after selecting (and connecting to) the peer as usual. This probably requires rewriting tunnel.cc to work with clientStreams/storeEntries because forward.cc kind of relies on that API. While I would like to see that kind of design eventually, I do not want to rewrite so much just to fix this bug. And these more complex APIs are likely to also make tunneling less efficient. 3) Extract [SSL] peer connection establishment code from tunnel.cc and forward.cc into a new class. Allow tunnel.cc and forward.cc code to use that new class to establish the SSL connection as needed, returning control back to the caller (either tunnel.cc or forward.cc). This avoids code duplication but SslBump and other code specific to forward.cc will complicate a clean extraction of the forward.cc code into a stand-alone peer-connection-establishing class. My current plan is to try #3 to avoid code duplication but if it becomes too complex, go for #1 and duplicate what is necessary. What do you think? Any better ideas? Thank you, Alex. P.S. Currently, ClientHttpRequest::processRequest() calls tunnelStart(). This is where request forwarding splits between tunnel.cc and forward.cc: > /* > * Identify requests that do not go through the store and client side stream > * and forward them to the appropriate location. All other requests, request > * them. > */ > void > ClientHttpRequest::processRequest() > { > if (request->method == METHOD_CONNECT && !redirect.status) { > logType = LOG_TCP_MISS; > getConn()->stopReading(); // tunnels read for themselves > tunnelStart(this, &out.size, &al->http.code); > return; > } > > httpStart(); // calls forward.cc > }