--- title: "How to Set Up a Squid Proxy Server on Ubuntu 24.04" description: "Install and configure a Squid forward proxy on Ubuntu 24.04 with password authentication, IP restrictions, domain blocking and caching, then test it with curl." category: "Use Cases" language: en source: https://cubepath.com/docs/use-cases/proxy-server-with-squid updated: 2026-09-25 --- # How to Set Up a Squid Proxy Server on Ubuntu 24.04 Squid is a mature open-source forward proxy: clients send their web requests to it, and Squid fetches the content on their behalf, optionally caching it, filtering it and logging every request. In this tutorial you will install Squid on Ubuntu 24.04, lock it down so only authenticated users can use it, block a list of domains, and test it from a client with `curl` and a browser. ## Prerequisites To follow this guide you need: - A server running Ubuntu 24.04 LTS, for example a CubePath VPS, with at least 1 GB of RAM and a few GB of free disk space for the cache. - A non-root user with `sudo` privileges and UFW enabled with SSH allowed. - The public IP address of the machine you will connect from, referred to as `your_client_ip`. > Warning: A proxy that accepts connections from anyone (an "open proxy") is found by scanners within hours and abused for spam and attacks, which gets your IP blocklisted. Every configuration in this guide requires authentication and ends with `http_access deny all`. ## Step 1 - Installing Squid Squid is in the Ubuntu repositories. Install it together with `apache2-utils`, which provides the `htpasswd` tool you will use to create proxy users: ```bash sudo apt update sudo apt install squid apache2-utils ``` The service starts automatically. Check its status: ```bash systemctl status squid --no-pager ``` The output should show `active (running)`. Ubuntu 24.04 ships Squid 6, which you can confirm with `squid -v | head -n 1`. ## Step 2 - Creating proxy users Squid can check usernames and passwords against a file in `htpasswd` format with its `basic_ncsa_auth` helper. Create the file and the first user, replacing `your_user` with the username you want: ```bash sudo htpasswd -c /etc/squid/passwords your_user ``` You will be asked for the password twice. To add more users later, run the same command without `-c`, which would otherwise overwrite the file. Squid runs as the `proxy` user, so it needs read access to the file, while other users should not: ```bash sudo chown root:proxy /etc/squid/passwords sudo chmod 640 /etc/squid/passwords ``` Test the helper directly by typing the username and password separated by a space: ```bash echo 'your_user your_password' | sudo -u proxy /usr/lib/squid/basic_ncsa_auth /etc/squid/passwords ``` ```output OK ``` A wrong password prints `ERR`. ## Step 3 - Writing a minimal configuration The default `/etc/squid/squid.conf` is over 9,000 lines, almost all comments, and by default only allows clients on private networks. Keep it as a reference and write a short configuration you fully understand: ```bash sudo mv /etc/squid/squid.conf /etc/squid/squid.conf.orig sudo nano /etc/squid/squid.conf ``` Paste the following: ```text # Port Squid listens on http_port 3128 # Authentication with the htpasswd file auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwords auth_param basic realm Squid proxy auth_param basic credentialsttl 2 hours acl authenticated proxy_auth REQUIRED # Ports clients may connect to acl SSL_ports port 443 acl Safe_ports port 80 acl Safe_ports port 443 acl Safe_ports port 1025-65535 acl CONNECT method CONNECT # Domains nobody may visit acl blocked_sites dstdomain "/etc/squid/blocked_domains.txt" # Access rules, evaluated top to bottom; the first match wins http_access deny !Safe_ports http_access deny CONNECT !SSL_ports http_access allow localhost manager http_access deny manager http_access deny blocked_sites http_access allow authenticated http_access deny all # Cache: 256 MB in memory, 2 GB on disk cache_mem 256 MB maximum_object_size 100 MB cache_dir ufs /var/spool/squid 2000 16 256 coredump_dir /var/spool/squid # Don't reveal client IPs to the websites they visit forwarded_for delete via off refresh_pattern ^ftp: 1440 20% 10080 refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 refresh_pattern . 0 20% 4320 ``` The key parts are: - `acl` lines define named conditions (a user is authenticated, a port is 443, a domain is in a list). They do nothing on their own. - `http_access` lines use those conditions to allow or deny requests. Order matters: unsafe ports and blocked domains are denied before authenticated users are allowed, and `deny all` catches everything else. - `CONNECT` is the method browsers use to tunnel HTTPS through the proxy. Squid cannot see or cache the content of HTTPS sites, but it still logs the domain and applies the rules above. - `cache_dir ufs /var/spool/squid 2000 16 256` creates a 2,000 MB disk cache split into 16 first-level and 256 second-level directories. Create the blocklist file, one domain per line. A leading dot also matches all subdomains: ```bash sudo nano /etc/squid/blocked_domains.txt ``` ```text .facebook.com .tiktok.com ``` Check the configuration for errors: ```bash sudo squid -k parse ``` The command prints the configuration it processed; look for lines containing `ERROR` or `FATAL`. If there are none, the file is valid. ## Step 4 - Initializing the cache and restarting Squid The disk cache directories must exist before Squid can use them. Stop the service, create them, and start it again: ```bash sudo systemctl stop squid sudo squid -z --foreground sudo systemctl start squid ``` Confirm Squid is listening on port 3128: ```bash sudo ss -tlnp | grep 3128 ``` ```output LISTEN 0 256 *:3128 *:* users:(("squid",pid=5120,fd=13)) ``` ## Step 5 - Opening the firewall Even with authentication, there is no reason to expose the proxy to the whole internet. Allow port 3128 only from the addresses that will use it: ```bash sudo ufw allow from your_client_ip to any port 3128 proto tcp ``` Repeat the command for each additional client address, then check the rules with `sudo ufw status`. ## Step 6 - Testing the proxy From your client machine, request a page through the proxy with `curl`. The `-x` option sets the proxy and `-U` the credentials: ```bash curl -x http://your_server_ip:3128 -U your_user:your_password -I https://example.com ``` ```output HTTP/1.1 200 Connection established HTTP/2 200 content-type: text/html ... ``` The first `200 Connection established` comes from Squid, the second from the website. Now check that the rules work. Without credentials, Squid refuses the request: ```bash curl -x http://your_server_ip:3128 -I https://example.com ``` ```output HTTP/1.1 407 Proxy Authentication Required ``` A blocked domain is rejected even with valid credentials: ```bash curl -x http://your_server_ip:3128 -U your_user:your_password -I https://www.facebook.com ``` ```output HTTP/1.1 403 Forbidden ``` Finally, confirm that the requests are logged on the server: ```bash sudo tail -n 3 /var/log/squid/access.log ``` ```output 1759312000.123 412 198.51.100.23 TCP_TUNNEL/200 5120 CONNECT example.com:443 your_user HIER_DIRECT/93.184.215.14 - 1759312005.456 0 198.51.100.23 TCP_DENIED/407 3920 CONNECT example.com:443 - HIER_NONE/- text/html 1759312010.789 0 198.51.100.23 TCP_DENIED/403 3874 CONNECT www.facebook.com:443 - HIER_NONE/- text/html ``` Each line shows the client IP, the result code, the destination and the authenticated user. ## Step 7 - Configuring clients To use the proxy from a browser or the whole operating system, set a manual HTTP and HTTPS proxy of `your_server_ip` on port `3128`: - **Firefox:** Settings > Network Settings > Manual proxy configuration, and check "Also use this proxy for HTTPS". - **Windows:** Settings > Network & internet > Proxy > Manual proxy setup. - **macOS:** System Settings > Network > your connection > Details > Proxies, enable "Web proxy (HTTP)" and "Secure web proxy (HTTPS)". The browser asks for the username and password on first use. For command-line tools on Linux, export the standard variables: ```bash export http_proxy="http://your_user:your_password@your_server_ip:3128" export https_proxy="$http_proxy" ``` > Important: The connection between the client and Squid is plain HTTP, and basic authentication only encodes the password, it does not encrypt it. Use the proxy from trusted networks, or reach it through a VPN such as WireGuard and allow port 3128 only on the VPN interface. ## Managing Squid day to day After editing `squid.conf` or the blocklist, validate and apply the changes without dropping active connections: ```bash sudo squid -k parse sudo systemctl reload squid ``` Squid's logs are rotated daily by logrotate (`/etc/logrotate.d/squid`). To see how much of the traffic is served from the cache, count the result codes in the access log: ```bash sudo awk '{print $4}' /var/log/squid/access.log | cut -d/ -f1 | sort | uniq -c | sort -rn ``` ```output 1834 TCP_TUNNEL 212 TCP_MISS 97 TCP_HIT 41 TCP_DENIED ``` `TCP_HIT` and `TCP_MEM_HIT` are requests served from the cache. Since most traffic today is HTTPS (`TCP_TUNNEL`), expect a low hit rate unless clients download a lot of plain HTTP content such as package repositories. ## Troubleshooting - **Squid fails to start.** Run `sudo squid -k parse` and `journalctl -u squid -n 50`. A missing `/etc/squid/blocked_domains.txt` or passwords file is a common cause. - **`curl: (7) Failed to connect`.** The firewall is blocking the client. Check that `your_client_ip` is your real public IP (`curl -4 https://ifconfig.me` on the client) and that it appears in `sudo ufw status`. - **`407` even with the right password.** Test the helper as in Step 2. If it prints `ERR`, recreate the user with `htpasswd`; if it cannot open the file, fix the owner and permissions. - **`403` for sites that should work.** A rule above `http_access allow authenticated` matched. Check the blocklist; `.example.com` matches every subdomain of `example.com`. ## Conclusion You now have a Squid forward proxy on Ubuntu 24.04 that only serves authenticated users from known addresses, blocks unwanted domains, caches cacheable content and logs every request. From here you can define time-based ACLs with `acl work_hours time`, limit bandwidth per user with delay pools, or chain this proxy to an upstream one with `cache_peer`.