Cover image for A short guide on Squid transparent proxy & SSL bumping

A short guide on Squid transparent proxy & SSL bumping

suntong profile image suntong Updated on ・4 min read


This is my second fact-collecting blog of the squid caching server series. Again, most of them will be collected from the web and reposted here, giving credit where credit is due of course.


  • Squid is a very powerful proxy server app with very little and awful documentation.
  • The google might not be your friend for this, because, caution: some config directives may be outdated.


Just install through your package manager. Check your version e.g. 3.5.4. Enable with systemctl enable --now squid. Check if it crashed with systemctl status squid since it won't display any info in the command line. Check logs in /var/log/squid - they only show up once squid has started.

Your magic command will be squid -k reconfigure which reloads the config file after any changes.

Setting up

The key is getting the config file /etc/squid/squid.conf right. It's like black magic with very little feedback.

The config file consists of directives. They do 3 things:

  1. Who and how can access the proxy, and what they can access:
    • acl: define access control lists (source, destination, protocol etc.),
    • http_access: control access for ACLs (checked in order, first rejection rejects request)
  2. How the proxy can be reached and what it actually does to incoming requests:
    • http_port, https_port: where the proxy listens
    • ssl_bump: splice, peek and bump (intercept/inspect) some SSL connections
    • cache_peer: forward some requests to another (caching) proxy
  3. Misc I/O, caching & debugging stuff:
    • logformat, access_log: specify logging
    • refresh_pattern, cache_dir: configure caching
    • debug_options: additional debug logging

Modes of use

  • Normal forward proxy: clients connect to the internet through this. Squid: http_port
  • Reverse / acceleator proxy: sits in front of servers to cache and route data. Squid: http_port accel
  • Transparent / intercepting proxy: requests are routed to this with a firewall / iptables without the client knowing. Squid: http_port intercept, https_port ssl_bump intercept

Obtaining SSL key

Install openssl. Then:

mkdir -p /etc/squid/cert/
cd /etc/squid/cert/
# This puts the private key and the self-signed certificate in the same file
openssl req -new -newkey rsa:4096 -sha256 -days 365 -nodes -x509 -keyout myCA.pem -out myCA.pem
# This can be added to browsers
openssl x509 -in myCA.pem -outform DER -out myCA.der

Then assign the above files and folders to the squid user.

Initialize SSL database

With the below config, Squid will generate a new 'fake' self-signed certificate for each bumped SSL connection (that the clients will hate). These will be cached in a folder.

On Fedora 29, it can be done with:

sudo -u squid /usr/lib64/squid/security_file_certgen -c -s /var/spool/squid/ssl_db -M 4MB

(This is the default directory. If you try to start Squid with SSL signing without initializing this folder, it will crash, and you can get some guidance with systemctl status squid)

Fix clients

Clients hate self-signed certs for good reasons.

  • Browsers: use the myCA.der file to import the certificate.
  • Linux: copy the cert files to /etc/pki/ca-trust/source/anchors and then run update-ca-trust or whatever you have on your distribution, YMMV.
  • Node.js: Node will hate self-signed certs and you will have to modify the default HTTPS agent (locally or globally) or each request's options. You have 2 options:
    1. Read the PEM file and add the Buffer to the ca option.
    2. Set rejectUnauthorized to false - this is unsafe, allows man-in-the-middle attacks.
    3. If using the request library, set strictSSL to false.
  • Headless Chrome (Puppeteer): start Chromium with --ignore-certificate-errors, start Puppeteer with ignoreHTTPSErrors set to true.

Divert traffic to the transparent proxy with iptables

From other computers, we use the PREROUTING chain, specifying the source with -s:

iptables -t nat -A PREROUTING -s -p tcp --dport 80 -j REDIRECT --to-port 3129
iptables -t nat -A PREROUTING -s -p tcp --dport 443 -j REDIRECT --to-port 3130

On localhost this is a tougher issue since we want to avoid forwarding loops (packet is diverted to Squid but it should be sent to the Internet when Squid done its thing). Fortunately iptables can differentiate between packet owner users. We need to use the OUTPUT chain for locally-generated packets. So we allow packets by root and squid through and divert everything else to Squid.

iptables -t nat -A OUTPUT -p tcp -m tcp --dport 80 -m owner --uid-owner root -j RETURN
iptables -t nat -A OUTPUT -p tcp -m tcp --dport 80 -m owner --uid-owner squid -j RETURN
iptables -t nat -A OUTPUT -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 3129
iptables -t nat -A OUTPUT -p tcp -m tcp --dport 443 -m owner --uid-owner root -j RETURN
iptables -t nat -A OUTPUT -p tcp -m tcp --dport 443 -m owner --uid-owner squid -j RETURN
iptables -t nat -A OUTPUT -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 3130


In the config, set debug_options. E.g. some general debug logs and detailed ACL info:

debug_options ALL,2 28,9


Here are lots of good links:

Omitted. See the original article


  • This blog is mostly taken from here, published in January 2019 under the CC-BY-SA license, with much condensing and slight editing on my own.
  • The cover image is taken from squid-cache.org


Editor guide