Trying out Squid Proxy

I was recently trying out Squid Proxy. I have heard of it before, can't remember where, but never got around to using it

This time my team wanted to use Squid Proxy as a way to expose and access some internal services. The Squid Proxy would be accessible only from within our company VPN - that is any device which has one of the IP addresses of our VPN can access it

Quick introduction to proxies - in this case, we are using Squid Proxy as a forward proxy, where we want the proxy to access resources on behalf of us. So, we are trying to access resources indirectly, through Squid Proxy, and not directly. Why? In this case it's because the resources are not directly accessible, as they are internal resources with internal IP addresses in an internal private network, and our users, developers, will be in public networks, the Internet.

There's also another kind of proxy called reverse proxy, where the client / user accesses the reverse proxy to get some resources, but the client doesn't know any details about the servers/services responding back to give the resources. The reverse proxy hides details about the services/servers (backends) behind it, from which it gets the resources. Usually reverse proxies also do load balancing, to balance the request load on the different instances of the service behind the reverse proxy. Usually there's more than one instance of the service, for scalability

Let's look at how I tried out Squid Proxy in my local machine :)

I'm on a MacBook Pro, with macOS Monterey version 12.7.1. I used Homebrew to install Squid Proxy in my local machine

brew install squid

I installed version 6.6 of Squid Proxy. You can see this with brew and also with squid CLI

$ brew info squid
==> squid: stable 6.6 (bottled), HEAD
Advanced proxy caching server for HTTP, HTTPS, FTP, and Gopher
http://www.squid-cache.org/
/usr/local/Cellar/squid/6.6 (179 files, 8.7MB) *
  Poured from bottle using the formulae.brew.sh API on 2024-01-08 at 16:32:34
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/s/squid.rb
License: GPL-2.0-or-later
==> Dependencies
Required: openssl@3 ✔
==> Options
--HEAD
    Install HEAD version
==> Caveats
To start squid now and restart at login:
  brew services start squid
Or, if you don't want/need a background service you can just run:
  /usr/local/opt/squid/sbin/squid -N -d\ 1
==> Analytics
install: 1,314 (30 days), 3,145 (90 days), 8,114 (365 days)
install-on-request: 1,314 (30 days), 3,145 (90 days), 8,114 (365 days)
build-error: 0 (30 days)
$ squid --version
Squid Cache: Version 6.6
Service Name: squid

This binary uses OpenSSL 3.2.0 23 Nov 2023. configure options:  '--disable-debug' '--disable-dependency-tracking' '--prefix=/usr/local/Cellar/squid/6.6' '--localstatedir=/usr/local/var' '--sysconfdir=/usr/local/etc' '--enable-ssl' '--enable-ssl-crtd' '--disable-eui' '--enable-pf-transparent' '--with-included-ltdl' '--with-gnutls=no' '--with-nettle=no' '--with-openssl' '--enable-delay-pools' '--enable-disk-io=yes' '--enable-removal-policies=yes' '--enable-storeio=yes' 'CC=clang' 'LDFLAGS=-lresolv' 'CXX=clang++' 'PKG_CONFIG_PATH=/usr/local/opt/openssl@3/lib/pkgconfig' 'PKG_CONFIG_LIBDIR=/usr/lib/pkgconfig:/usr/local/Homebrew/Library/Homebrew/os/mac/pkgconfig/12' --enable-ltdl-convenience

Now to try out Squid Proxy, I used Firefox Browser and also my terminal, the CLI, to see if it works there too

Let's start with how I did it in Firefox Browser. I'm using Firefox Browser in my Mac machine, and the version I'm using is Version 121.0 (64-bit)

Go to Settings > Network Settings > Settings button > Configure Proxy Access to the Internet > Manual proxy configuration

Here, I added proxy configuration for accessing http:// URLs under HTTP Proxy and used the same proxy configuration for accessing https:// URLs too by checking the box that said Also use this proxy for HTTPS . The configuration I added was -

Hostname: localhost

Port: 3128

It would look like this -

Once you are done configuring, ensure you press OK to save the configuration

Now, I tried to access some websites, say, for example Google

It gives this error

It says -

The proxy server is refusing connections

An error occurred during a connection to www.google.com.

- Check the proxy settings to make sure that they are correct.
- Contact your network administrator to make sure the proxy server is working.

Now, this error means that for some reason the proxy server is refusing connections, that is, not accepting connections

Now, the reason for this error here is because I never started the Squid Proxy server in my local machine. But this is a good test to see if the browser is using the proxy we configured, or if it's just not using the proxy and instead directly accessing the website we type in the URL bar

Next thing to do is, run Squid Proxy, so that Firefox is able to access the proxy server and is able to access resources using the proxy server

Before running Squid Proxy, I would recommend checking out it's help section and just skimming through it, just to get an idea of the different flags it has

$ squid --help
Usage: squid [-cdzCFNRVYX] [-n name] [-s | -l facility] [-f config-file] [-[au] port] [-k signal]
    -h | --help       Print help message.
    -v | --version    Print version details.

       -a port   Specify HTTP port number (default: 3128).
       -d level  Write debugging to stderr also.
       -f file   Use given config-file instead of
                 /usr/local/etc/squid.conf
       -k reconfigure|rotate|shutdown|restart|interrupt|kill|debug|check|parse
                 Parse configuration file, then send signal to 
                 running copy (except -k parse) and exit.
       -n name   Specify service name to use for service operations
                 default is: squid.
       -s | -l facility
                 Enable logging to syslog.
       -u port   Specify ICP port number (default: 3130), disable with 0.
       -z        Create missing swap directories and then exit.
       -C        Do not catch fatal signals.
       -D        OBSOLETE. Scheduled for removal.
       -F        Don't serve any requests until store is rebuilt.
       -N        Master process runs in foreground and is a worker. No kids.
       --foreground
                 Master process runs in foreground and creates worker kids.
       --kid role-ID
                 Play a given SMP kid process role, with a given ID. Do not use
                 this option. It is meant for the master process use only.
       -R        Do not set REUSEADDR on port.
       -S        Double-check swap during rebuild.
       -X        Force full debugging.
                 Add -d9 to also write full debugging to stderr.
       -Y        Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.

Squid Proxy requires configuration for it to work. My installation came with a default configuration file, which is at /usr/local/etc/squid.conf according to the help section. I used the default configuration since I was just playing with it and trying it out for the first time. In my case, the default configuration, along with an extra line I added, looks like this -

#
# Recommended minimum configuration:
#

# Example rule allowing access from your local networks.
# Adapt to list your (internal) IP networks from where browsing
# should be allowed
acl localnet src 0.0.0.1-0.255.255.255    # RFC 1122 "this" network (LAN)
acl localnet src 10.0.0.0/8        # RFC 1918 local private network (LAN)
acl localnet src 100.64.0.0/10        # RFC 6598 shared address space (CGN)
acl localnet src 169.254.0.0/16     # RFC 3927 link-local (directly plugged) machines
acl localnet src 172.16.0.0/12        # RFC 1918 local private network (LAN)
acl localnet src 192.168.0.0/16        # RFC 1918 local private network (LAN)
acl localnet src fc00::/7           # RFC 4193 local private network range
acl localnet src fe80::/10          # RFC 4291 link-local (directly plugged) machines

acl SSL_ports port 443
acl Safe_ports port 80        # http
acl Safe_ports port 21        # ftp
acl Safe_ports port 443        # https
acl Safe_ports port 70        # gopher
acl Safe_ports port 210        # wais
acl Safe_ports port 1025-65535    # unregistered ports
acl Safe_ports port 280        # http-mgmt
acl Safe_ports port 488        # gss-http
acl Safe_ports port 591        # filemaker
acl Safe_ports port 777        # multiling http

#
# Recommended minimum Access Permission configuration:
#
# Deny requests to certain unsafe ports
http_access deny !Safe_ports

# Deny CONNECT to other than secure SSL ports
http_access deny CONNECT !SSL_ports

# Only allow cachemgr access from localhost
http_access allow localhost manager
http_access deny manager

# This default configuration only allows localhost requests because a more
# permissive Squid installation could introduce new attack vectors into the
# network by proxying external TCP connections to unprotected services.
http_access allow localhost

# The two deny rules below are unnecessary in this default configuration
# because they are followed by a "deny all" rule. However, they may become
# critically important when you start allowing external requests below them.

# Protect web applications running on the same server as Squid. They often
# assume that only local users can access them at "localhost" ports.
http_access deny to_localhost

# Protect cloud servers that provide local users with sensitive info about
# their server via certain well-known link-local (a.k.a. APIPA) addresses.
http_access deny to_linklocal

#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#

# For example, to allow access from your local networks, you may uncomment the
# following rule (and/or add rules that match your definition of "local"):
# http_access allow localnet

# And finally deny all other access to this proxy
http_access deny all

# Squid normally listens to port 3128
http_port 3128

# Uncomment and adjust the following to add a disk cache directory.
#cache_dir ufs /usr/local/var/cache/squid 100 16 256

# Leave coredumps in the first cache dir
coredump_dir /usr/local/var/cache/squid

#
# Add any of your own refresh_pattern entries above these.
#
refresh_pattern ^ftp:        1440    20%    10080
refresh_pattern -i (/cgi-bin/|\?) 0    0%    0
refresh_pattern .        0    20%    4320

cache_mgr admin@gmail.com

I think the only thing I added here was cache_mgr admin@gmail.com which is a configuration to tell the Squid Proxy the email ID of the proxy's administrator so that it can tell it's clients / users whom to contact in case there's an issue with the proxy - using it, accessing it etc

So, I ran the Squid Proxy in foreground in the terminal (CLI) like this -

$ squid --foreground

Killing Squid Proxy when it's a foreground process is easy, just press Ctrl + C, the usual keyboard shortcut to kill a running command (process)

To use Squid Proxy in the background, just do this -

$ squid

To be able to see the Squid Proxy process, use ps aux command with grep

$ ps aux | grep --color squid
karuppiah.n      81093   0.0  0.0 33589096    280 s000  R+    1:44PM   0:00.00 grep --color squid
karuppiah.n      81089   0.0  0.1 34201172  13368   ??  S     1:44PM   0:00.05 (squid-1) --kid squid-1
karuppiah.n      81087   0.0  0.0 34182540   2084   ??  Ss    1:44PM   0:00.00 squid

Killing Squid Proxy when it's in the background, just kill the parent process, which you can find from the ps aux command. In this case, the parent process is the command squid, and it's child is (squid-1) --kid squid-1. Even when Squid Proxy runs as a foreground process, it has a child process, which you can see like this -

$ ps aux | rg squid
karuppiah.n      81167   0.0  0.1 34238612  10348 s000  S+    1:47PM   0:00.42 (squid-1) --kid squid-1 --foreground
karuppiah.n      81165   0.0  0.0 34174396   5800 s000  S+    1:47PM   0:00.03 squid --foreground
karuppiah.n      82179   0.0  0.0 33595048     12 s001  S+    3:44PM   0:00.00 rg squid

To find if the two squid processes are related and are parent and child, use the following in Mac

$ ps axj | rg squid
karuppiah.n      81165 68772 81165      0    1 S+   s000    0:00.03 squid --foreground
karuppiah.n      81167 81165 81165      0    1 S+   s000    0:00.42 (squid-1) --kid squid-1 --foreground
karuppiah.n      82177 71007 82176      0    2 S+   s001    0:00.00 rg squid

The j in ps axj gives parent process ID information

-j    Print information associated with the following keywords: user, pid, ppid, pgid, sess, jobc, state, tt, time, and command.

Finally, check if the proxy works in your Firefox browser

Now, the Google website would work. Let's try the same in the terminal. First kill the proxy, and try this -

$ export http_proxy=http://localhost:3128
$ export https_proxy=http://localhost:3128

This sets up the proxy configuration for accessing http:// links and https:// links

Now, try to access Google website using curl. Ensure the Squid Proxy is not running, hence, curl shouldn't work. This way, we know the proxy configuration is being used

$ curl google.com
curl: (7) Failed to connect to localhost port 3128 after 6 ms: Couldn't connect to server

Now, we see the error and it clearly says that it's not able to connect to the proxy server. This is because we killed the proxy server

Let's start the Squid Proxy server and try to do the curl again :)

$ curl google.com
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>

Now it all works :)

So, that's how one can configure proxy in terminal, in Firefox and test it out using Squid Proxy, for trying out forward proxy servers

MacOS also has a System Wide Proxy configuration, which is used by Google Chrome browser. But I didn't notice this to work in Chrome. I mean, when this proxy was on, but proxy server was not running, the terminal and Google Chrome browser were able to access Google website for example. Not sure if it didn't even consider the proxy configuration, or if it considered but noticed it to be down, and hence tried to access the resource (Google website etc) directly. I gotta check how to do that check, maybe using ngrep or something

Above is the System Wide Proxy looks for when configuring Proxy for a given WiFi endpoint, through Advanced settings

That's all for now ! Looking forward to learn more, write more and share more :) Let me know what you felt about the post in the comments :)