Squid3 listens only on IPv6 after reboot — how to diagnose and fix it
Context. After a server reboot, Squid3 accepted connections only over IPv6. IPv4 clients timed out when connecting to the proxy. Root cause: no explicit IPv4 bind in the Squid configuration, so Squid listened on [::]:3128 only.
Symptoms
- IPv4 client requests time out:
curl -4 -x http://<SERVER_IPV4>:3128 http://icanhazip.com -v
# ... -> connect timeout
- Listening sockets show IPv6 only:
ss -ltnp | grep 3128
# LISTEN ... :::3128 ...
- No IPv4 listener:
ss -ltnp4 | grep 3128
# (no output)
Root cause
On many systems, an IPv6 socket does not also accept IPv4 (e.g., due to net.ipv6.bindv6only=1). If Squid binds only to [::]:3128, IPv4 connections to <SERVER_IPV4>:3128 fail.
Diagnosis checklist
-
Confirm where Squid is listening
ss -ltnp4 | grep 3128 # IPv4 ss -ltnp6 | grep 3128 # IPv6 -
Watch logs while you test
sudo tail -f /var/log/squid3/access.log /var/log/squid3/cache.log -
Verify traffic reaches the host
sudo tcpdump -n -i any tcp port 3128 # No SYNs → upstream/provider firewall # SYNs but no accept → local firewall or Squid not bound to IPv4
The fix (make it explicit)
-
Bind explicitly to IPv4 (and optionally IPv6)
Edit/etc/squid3/squid.conf(or/etc/squid/squid.conf):# IPv4 listener (required) http_port 0.0.0.0:3128 # Optional: separate IPv6 listener # http_port [::]:3128Alternative (if supported by your build):
http_port [::]:3128 ipv6only=offHowever, two explicit lines are the most predictable on older systems.
-
Minimal, safe ACLs
acl localhost src 127.0.0.1/32 acl myclient src <YOUR_TEST_SERVER_IP>/32 acl SSL_ports port 443 acl Safe_ports port 80 acl Safe_ports port 443 acl CONNECT method CONNECT http_access allow localhost http_access allow myclient http_access deny CONNECT !SSL_ports http_access deny all visible_hostname squid-proxy -
Validate and restart
sudo squid3 -k parse # or: sudo squid -k parse sudo service squid3 restart -
Verify listeners
ss -ltnp4 | grep 3128 # expect 0.0.0.0:3128 (or your server IP) ss -ltnp6 | grep 3128 # (optional) [::]:3128
Firewall hardening
UFW
sudo ufw allow 3128/tcp
# tighter (recommended during testing):
# sudo ufw allow from <YOUR_TEST_SERVER_IP> to any port 3128 proto tcp
iptables (IPv4)
# allow only your test IP, drop the rest
sudo iptables -I INPUT -p tcp -s <YOUR_TEST_SERVER_IP> --dport 3128 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 3128 -j DROP
Note: Avoid http_access allow all in production. If you temporarily use it for debugging, enforce source-IP restrictions at the OS/provider firewall.
Testing
-
HTTP smoke test (avoids TLS variables)
curl -4 -x http://<SERVER_IPV4>:3128 http://icanhazip.com -v -
HTTPS via CONNECT
curl -4 -x http://<SERVER_IPV4>:3128 https://ipinfo.io/ip -L -v # In access.log, success appears as: TCP_TUNNEL/200
Handy test script
Save as test_squid.sh, make executable (chmod +x test_squid.sh), run with your server IP.
#!/usr/bin/env bash
PROXY_IP="${1:?Usage: $0 <proxy_ipv4>}"
PORT="${2:-3128}"
echo "[1] Sockets:"
ss -ltnp4 | grep "$PORT" || echo "IPv4 not listening on :$PORT"
ss -ltnp6 | grep "$PORT" || echo "IPv6 not listening on :$PORT"
echo -e "\n[2] HTTP smoke test:"
curl -4 -x "http://$PROXY_IP:$PORT" http://icanhazip.com -sS || echo "HTTP via proxy failed"
echo -e "\n[3] HTTPS test:"
curl -4 -x "http://$PROXY_IP:$PORT" https://ipinfo.io/ip -L -sS || echo "HTTPS via proxy failed (TLS/ACL?)"
echo -e "\n[4] Recent logs:"
sudo tail -n 5 /var/log/squid3/access.log 2>/dev/null || true
sudo tail -n 5 /var/log/squid3/cache.log 2>/dev/null || true
Prevention
- Always bind IPv4 explicitly:
http_port 0.0.0.0:3128. - Keep UFW/iptables/provider firewall rules restrictive and persistent.
- Include a config validation step in provisioning:
squid3 -k parse. - Optional: add monitoring/alerts on TCP/3128 and on Squid errors.
Conclusion
The issue stemmed from a missing explicit IPv4 binding. By adding http_port 0.0.0.0:3128, setting sane ACLs, and tightening the firewall, the proxy works reliably again—across reboots—without exposing you as an open proxy.

Comments
Post a Comment