The way to do this is to use the ssl peek feature introduced in Squid 3.5. See here for a detailed explanation. Do note you will need to have compiled with either --with-gnutls
or --with-openssl
(check squid -v
). Some distros leave them out.
In short, the relevant squid configuration looks like this.
acl denylist_ssl ssl::server_name google.com # NOT dstdomain
acl step1 at_step SslBump1
ssl_bump peek step1
ssl_bump splice !denylist_ssl # allow everything not in the denylist
ssl_bump terminate all # block everything else
https_port 3129 intercept ssl-bump cert=/etc/squid/dummy.pem
(Aside: I am not sure why we need to only peek at step 1 and not step 2 given that step 2 involves only receiving the server certificate. The docs do not make this clear at all. Using ssl_bump peek all
as they recommend makes this stop working entirely).
And then do the usual redirect port 443 to 3129 dance using iptables (or have squid listen on 443 directly if you prefer).
-A PREROUTING -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 3129
You can use any certificate for the dummy, we actually never use it (because we're not decrypting traffic).
Something like this works.
openssl req -new -newkey rsa:4096 -sha256 -days 365 -nodes -x509 -keyout dummy.pem -out dummy.pem
Sources:
[1] https://unix.stackexchange.com/questions/613359/setting-up-squid-transparent-proxy-with-ssl-bumping-on-debian-10
[2] https://web.archive.org/web/20210128152111/https://www.cammckenzie.com/blog/index.php/2018/07/19/squid-https-interception-and-filtering-without-client-certificates/
[3] https://wiki.squid-cache.org/Features/SslPeekAndSplice