The SSL-bump bypass code on intercepted HTTPS traffic generates a fake
CONNECT request from the original destination IP:port in an attempt to
trigger a TCP tunnel being opened for the un-bumped data to be
transferred over.
The current implementation breaks in two situations:
1) when IPv6 traffic is intercepted
The URL field generated does not account for the additional []
requirements involved when IPv6+port are combined.
The resulting fake requests look like:
CONNECT ::1:443 HTTP/1.1
Host: ::1
.. .which are both invalid, and will fail to parse. Breaking IPv6 HTTPS
interception bypass.
The attached patch resolves this by using Ip::Address::ToURL() function
which was created for the purpose of generating URL hostnames from raw-
IP + port including the bracketing when required.
2) when a non-443 port is being intercepted
The Host: header generated is missing the port and Squid Host: header
validity will reject the outbound
CONNECT 127.0.0.1:8443 HTTP/1.1
Host: 127.0.0.1
... this is an invalid request. Squid is currently ignoring the Host
header. However Squid tunnel.cc does make use of peering and may relay
the fake request Host: to upstream peers where we cannot be so sure what
will happen.
The attached patch resolves this issue by re-using the generated IP:port
string for both URL and Host: fields, which preserves teh port in Host:
regardless of value. This also means there is an unnecessary :443 tagged
on for most HTTPS traffic, however the omission of port from the Host:
header is only a MAY and this should not cause any issues.
Amos
=== modified file 'src/client_side.cc'
--- src/client_side.cc 2013-02-12 11:34:35 +0000
+++ src/client_side.cc 2013-03-06 07:04:11 +0000
@@ -3641,8 +3641,8 @@
// fake a CONNECT request to force connState to tunnel
static char ip[MAX_IPSTRLEN];
static char reqStr[MAX_IPSTRLEN + 80];
- connState->clientConnection->local.NtoA(ip, sizeof(ip));
- snprintf(reqStr, sizeof(reqStr), "CONNECT %s:%d HTTP/1.1\r\nHost:
%s\r\n\r\n", ip, connState->clientConnection->local.GetPort(), ip);
+ connState->clientConnection->local.ToURL(ip, sizeof(ip));
+ snprintf(reqStr, sizeof(reqStr), "CONNECT %s HTTP/1.1\r\nHost:
%s\r\n\r\n", ip, ip);
bool ret = connState->handleReadData(reqStr, strlen(reqStr));
if (ret)
ret = connState->clientParseRequests();