Squid Basics

Page 14 — Proxy server. What a proxy is, what a reverse proxy is, ACLs, and service checks.

What Squid is

Squid is a caching and forwarding proxy server.

What a proxy is

A proxy sits between a client and the destination server. Instead of:

client → website

You get:

client → proxy → website

Common reasons to use a (forward) proxy:

What a reverse proxy is

A reverse proxy is different — it represents the server to incoming clients, not the client to the outside world:

user → reverse proxy → backend app

Common reasons to use a reverse proxy (Nginx, Apache, HAProxy):

Squid is usually a forward proxy. Nginx and Apache are more commonly used as reverse proxies.

Main config

/etc/squid/squid.conf

ACL example

acl localnet src 192.168.1.0/24
http_access allow localnet
http_access deny all
http_port 3128

What this means:

ACL order matters. Squid reads rules top to bottom and stops at the first match. Put more specific allow rules before the final deny all.

Log files

/var/log/squid/access.log   # client requests
/var/log/squid/cache.log    # operational problems

Service checks

systemctl status squid
systemctl restart squid
journalctl -u squid -n 50

Troubleshooting

Config validation and live reload

The squid -k command sends signals to the running squid process. The most important are parse (validate config) and reconfigure (live reload).

# Validate the config file without restarting
squid -k parse

# If valid: no output (exit 0)
# If invalid: specific error with line number:
# FATAL: /etc/squid/squid.conf line 42: invalid ACL type 'destdomain'

# Reload config without dropping connections (graceful)
squid -k reconfigure

# Rotate log files (useful for log management scripts)
squid -k rotate

# Shutdown gracefully
squid -k shutdown

Always run squid -k parse before squid -k reconfigure or systemctl restart squid. A bad config kills the proxy for all clients without warning.

Workflow for config changes:
  1. Edit /etc/squid/squid.conf
  2. squid -k parse — validate
  3. squid -k reconfigure — apply without dropping connections
  4. tail -f /var/log/squid/access.log — verify traffic is flowing

visible_hostname directive

Without visible_hostname, Squid generates a startup warning and may use an incorrect or ugly hostname in error pages and Via headers. Set it explicitly to suppress the warning and control how the proxy identifies itself.

# /etc/squid/squid.conf
visible_hostname proxy01.internal.example.com

The warning you see without this directive: WARNING: Could not determine this machine's hostname. Please set 'visible_hostname'. This appears in /var/log/squid/cache.log on every startup.

# Full minimal squid.conf with visible_hostname
visible_hostname proxy01.internal.example.com

http_port 3128

# Internal network allowed
acl localnet src 10.0.0.0/8
acl localnet src 172.16.0.0/12
acl localnet src 192.168.0.0/16

http_access allow localnet
http_access deny all

CONNECT and ssl_bump

For HTTPS, clients ask Squid to open an opaque tunnel using the CONNECT method — everything after the TLS handshake is end-to-end encrypted and Squid only sees the destination host and byte counts. Two side effects to remember:

ssl_bump is intrusive. Full-bump requires pushing a root CA to every client, breaks certificate pinning (many apps will refuse to connect), and introduces a privacy/legal boundary you must document. Peek-and-splice is almost always enough for policy enforcement.

WPAD / PAC

WPAD (Web Proxy Auto-Discovery) lets browsers find the proxy automatically by fetching a PAC (Proxy Auto-Config) file from a well-known URL — http://wpad.<domain>/wpad.dat. You publish the file on an internal web server (and/or resolve wpad in DNS) and clients pick it up with zero manual config.

// /var/www/html/wpad.dat  (MIME type application/x-ns-proxy-autoconfig)
function FindProxyForURL(url, host) {
  // Direct for RFC1918 and internal zones — no proxy needed
  if (isPlainHostName(host) ||
      dnsDomainIs(host, ".internal.example.com") ||
      isInNet(host, "10.0.0.0",   "255.0.0.0") ||
      isInNet(host, "172.16.0.0", "255.240.0.0") ||
      isInNet(host, "192.168.0.0","255.255.0.0")) {
    return "DIRECT";
  }
  // Everything else goes through the proxy with a fallback
  return "PROXY proxy01.internal.example.com:3128; " +
         "PROXY proxy02.internal.example.com:3128; " +
         "DIRECT";
}

Serve the file as application/x-ns-proxy-autoconfig and make both wpad.<domain> and wpad resolve in DNS (browsers walk the DNS suffix list). Test with curl -H 'Accept: */*' http://wpad.internal.example.com/wpad.dat — a 404 or wrong MIME type will make clients silently fall back to DIRECT.

Authentication helpers

Squid does not do authentication itself — it calls an external helper and acts on the result. The helper is picked in squid.conf via auth_param.

Basic auth with a flat file (basic_ncsa_auth)

# /etc/squid/squid.conf
auth_param basic program /usr/lib64/squid/basic_ncsa_auth /etc/squid/htpasswd
auth_param basic realm   SysRef Proxy
auth_param basic children 5

acl authenticated proxy_auth REQUIRED
http_access allow authenticated
http_access deny all
# Create the password file (htpasswd from httpd-tools)
htpasswd -c /etc/squid/htpasswd alice
chmod 640 /etc/squid/htpasswd
chown root:squid /etc/squid/htpasswd
squid -k reconfigure

Kerberos / SPNEGO (negotiate_kerberos_auth)

# /etc/squid/squid.conf — single-sign-on against FreeIPA/AD
auth_param negotiate program /usr/lib64/squid/negotiate_kerberos_auth \
             -s HTTP/proxy01.internal.example.com@EXAMPLE.COM
auth_param negotiate children 10
auth_param negotiate keep_alive on

acl kerb_users proxy_auth REQUIRED
http_access allow kerb_users
http_access deny all
# Required environment bits:
#   - A keytab at /etc/squid/HTTP.keytab owned by squid, mode 0640
#   - KRB5_KTNAME=/etc/squid/HTTP.keytab exported to the squid service
#     (drop-in: /etc/systemd/system/squid.service.d/krb.conf)
systemctl edit squid
#   [Service]
#   Environment=KRB5_KTNAME=/etc/squid/HTTP.keytab

# Sanity check — does the helper work on the CLI?
echo 'YR' | /usr/lib64/squid/negotiate_kerberos_auth -d

Basic auth is simple but credentials cross the wire on every request — acceptable only inside a TLS-bumped setup or over a trusted LAN. Kerberos is the right choice in any FreeIPA/AD environment: users get transparent SSO and the proxy never sees a password. See Kerberos and Keytab Rotation for the identity side.