Sometimes you need to setup a proxy server so that you can mask your IP address for making web requests using your browser. In some situations, you may want to intercept every web request and reject some requests such as rejecting social media websites at work. Sometimes you want only authorized users to access the internet at your workplace and want to monitor their web access. One may also need to cache web requests to build their own content delivery network. In such scenarios, you can install a web proxy like Squid on Linux.
Setting it up on a Debian or Ubuntu system is very easy and this post will show you how. However, this post is limited to setting up the Squid proxy server only as a HTTP/FTP proxy and not for caching. That would be a different post for the future.
+================+ +==============+
| | | |
| BROWSER |<=====>|||| HTTP/FTP PACKETS ||||<=====>| PROXY SERVER |<=====>|||| INTERNET WEBSITE
| | | |
+================+ +==============+
INSTALLATION
If you want to run a web proxy, you need a server that is publicly visible on the internet. So for this example, you can use a Linode nanode which is $5 per month or a DigitalOcean VM.
Once you have setup the latest Debian (Buster as of this writing) or Ubuntu (2022.01 as of this writing) you can install the squid
software. Once it installs it starts up, but we need to configure it so we shut it down.
$ sudo su - root
root$ apt update && apt upgrade && apt -y install squid
root$ systemctl stop squid
CONFIGURATION
Now let’s configure the software. Edit the /etc/squid/squid.conf
file that has been setup by the operating system during installation. Most of the defaults are fine. In our case we only want to support HTTP, HTTPS and FTP protocols so the ports that we want to allow are 80, 443 and 21, respectively.
So your access control list (acl
) should look like below, where you comment out every other port that you do not want to support.
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
Now let’s create a custom file for our usage and place it in /etc/squid/conf.d/
and let’s call it local.conf
and add the following to it. Below is the content of /etc/squid/conf.d/local.conf
. Replace the MY_EXTERNAL_IP_ADDRESS
with your network’s external IP address, if you want to restrict access to Squid to
just your network. This is important for security. If you want to add several IP addresses, you must create one new line for each IP address and have the same acl
name so that the http_access allow
will work on that name.
## digest authentication - dumb but password is encrypted
auth_param digest program /usr/lib/squid/digest_file_auth -c /etc/squid/private/digest_authentication
auth_param digest children 32 startup=0 idle=1
## use any realm name here but it will be needed to generate the authentication token
auth_param digest realm MySquid Digest Authentication
auth_param digest nonce_garbage_interval 5 minutes
auth_param digest nonce_max_duration 30 minutes
auth_param digest nonce_max_count 50
acl authenticatedusers proxy_auth REQUIRED
# deny anyone who has not authenticated
http_access deny !authenticatedusers
### setup IP based access
http_access allow localhost
acl mybrowser src MY_EXTERNAL_IP_ADDRESS
http_access allow mybrowser
## change this to the hostname you want to use in the error messages
visible_hostname squid01
via off
forwarded_for off
request_header_access Allow allow all
request_header_access Authorization allow all
request_header_access WWW-Authenticate allow all
request_header_access Proxy-Authorization allow all
request_header_access Proxy-Authenticate allow all
request_header_access Cache-Control allow all
request_header_access Content-Encoding allow all
request_header_access Content-Length allow all
request_header_access Content-Type allow all
request_header_access Date allow all
request_header_access Expires allow all
request_header_access Host allow all
request_header_access If-Modified-Since allow all
request_header_access Last-Modified allow all
request_header_access Location allow all
request_header_access Pragma allow all
request_header_access Accept allow all
request_header_access Accept-Charset allow all
request_header_access Accept-Encoding allow all
request_header_access Accept-Language allow all
request_header_access Content-Language allow all
request_header_access Mime-Version allow all
request_header_access Retry-After allow all
request_header_access Title allow all
request_header_access Connection allow all
request_header_access Proxy-Connection allow all
request_header_access User-Agent allow all
request_header_access Cookie allow all
request_header_access All deny all
cache deny all
Now that you have saved this file as /etc/squid/conf.d/local.conf
we need to create the authentication file /etc/squid/private/digest_authentication
for Squid to use as a list of username and passwords.
root$ mkdir -p /etc/squid/private/
## setup the password and choose a username
root$ htdigest -c /etc/squid/private/digest_authentication 'MySquid Digest Authentication' <username>
Adding password for <username> in realm MySquid Digest Authentication
New password:
Re-type new password:
root$ chown -R proxy:proxy /etc/squid/private/
root$ chmod go-rwx /etc/squid/private/
Now you can restart the server:
root$ systemctl start squid
root$ netstat -vnatp | grep squid | grep LISTEN
tcp6 0 0 :::3128 :::* LISTEN 11111/(squid-1)
SECURITY
-
To secure the connection, it makes sense to setup a firewall such as
ufw
or use Linode’s cloud firewall setup to allow only connections from known IP addresses. If you want to allow global access, you must use a very strong password and keep your server up to date since you will see bot attacks. In my case, I have restricted access to the Squid server to my home IP and manually adjust the firewall when the IP changes. -
You can also add the IP address to the
acl
in thelocal.conf
file and let Squid reject other IP addresses. -
Using username/password authentication you can allow multiple users to access Squid and restrict access.
-
You can look at the logs present in
/var/log/squid/access.log
to see which websites were accessed by which user and from which IP address.
CONNECTING TO THE WEB PROXY
We can use curl
to test the proxy access first.
$ curl -v --proxy-digest -U <username>:<password> -x http://<IP ADDRESS>:3128 https://www.vikaskumar.org/
Here the username
and password
are the ones you had setup using the htdigest
command above.
The IP address is the external IP address of the server on which you are running the Squid proxy and 3128 is the default port.
You can then try to reach a website like https://www.ipinfo.io to verify that you are pretending to send your request from the Squid proxy server’s IP address.
BROWSER SETTINGS
On Firefox you must setup the proxy settings by following instructions.
You can select the Manual Proxy Configuration
and setup the same IP address for the HTTP(s) and FTP fields, and port 3128 for the port. Then when you try to access a website it will prompt you for a username and password, and you can enter the credentials you had setup earlier.
CONCLUSION
With this we come to the end of setting up an external web proxy server that allows you to have applications hide their IP address when they make HTTP(s) requests.