Guide to set up a proxy on Debian 11

Table of Contents

This guide is for educational and testing purposes. Using a proxy may violate websites’ terms of service. Use a proxy at your own risk.

Overview

Begin

Sign in as root

Update system and packages and install squid

# Update system packages
apt update && apt upgrade -y

# Install squid
apt install squid -y

Configure squid

Edit the file:

nano /etc/squid/squid.conf
  1. Search (Mac: Control + W) for http_access deny all
  2. Add two lines before http_access deny all
  3. Don’t add http_access allow authenticated until later if you decide to use a username and password

The section looks like this when added (note: the order is important):

acl myip src <YOUR_IP_ADDRESS> # add this
http_access allow authenticated # add this later (if you want authentication)
http_access allow myip # add this
http_access deny all

Restart squid (this takes a while):

systemctl restart squid

View real-time connections when the proxy is in use

tail -f /var/log/squid/access.log

View list of running services

systemctl list-units --type=service --state=running

(Optional) Add a username and password to use the proxy for increased security

Prompt for a username and password when the browser launches.

# Required password generator from squid
apt install apache2-utils

# Create the username and be prompted for a password
htpasswd -c /etc/squid/passwords <SQUID_USERNAME>

# Output hashed password
cat /etc/squid/passwords

Edit squid configuration file:

nano /etc/squid/squid.conf
  1. Press Control + w and find the string INSERT YOUR OWN RULE.

  2. Order matters! - Add these three lines so that it will look like the example below:

    auth_param basic program /usr/lib/squid3/basic_ncsa_auth /etc/squid/passwords
    auth_param basic realm proxy
    acl authenticated proxy_auth REQUIRED
  3. And then add this a little farther below:

    http_access allow authenticated

Snippet of squid.conf after you added the lines:

#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#
include /etc/squid/conf.d/*

auth_param basic program /usr/lib/squid3/basic_ncsa_auth /etc/squid/passwords
auth_param basic realm proxy
acl authenticated proxy_auth REQUIRED

# Example rule allowing access from your local networks.
# Adapt localnet in the ACL section to list your (internal) IP networks
# from where browsing should be allowed
#http_access allow localnet
http_access allow localhost

# And finally deny all other access to this proxy

# Allow rules for your public IP address
acl myip src <YOUR_IP_ADDRESS>
http_access allow authenticated
http_access allow myip
http_access deny all

#  TAG: adapted_http_access

Restart squid (this takes a while):

systemctl restart squid

Firewall Configuration

# Output firewall rules with a number next to it
ufw status numbered

# Allow only connections from your specified IP address to port 3128
ufw allow from <YOUR_IP_ADDRESS> to any port 3128

# Deny all other connections to port 3128
ufw deny 3128

This is what ufw status numbered looks like at the end:

     To                         Action      From
     --                         ------      ----
[ 1] 3128                       ALLOW IN    <YOUR_IP_ADDRESS>             
[ 2] 3128                       DENY IN     Anywhere                  
[ 3] 5355                       DENY IN     Anywhere                  
[ 4] 22/tcp                     ALLOW IN    <YOUR_IP_ADDRESS>             
[ 5] 22/tcp                     DENY IN     Anywhere                  
[ 6] 3128 (v6)                  DENY IN     Anywhere (v6)             
[ 7] 5355 (v6)                  DENY IN     Anywhere (v6)             
[ 8] 22/tcp (v6)                DENY IN     Anywhere (v6)

Connection timed out? Verify order

If you tried to connect via SSH and it timed out, your “22/tcp DENY IN from Anywhere” is probably above “22/tcp ALLOW IN from <YOUR_IP_ADDRESS>”.

For example, this will not allow you to connect because the rules are evaluated from top to bottom:

     To                         Action      From
     --                         ------      ----    
[ 4] 22/tcp                     DENY IN     Anywhere                  
[ 5] 22/tcp                     ALLOW IN    <YOUR_IP_ADDRESS>         

Your order may be different, but in this case, I execute two commands and then verify the order:

# Delete entry
ufw delete 5

# Re-add entry above position 4
ufw insert 4 allow from <YOUR_IP_ADDRESS> to any port 22 proto tcp

General network security configuration

Protect against SSH brute-force attacks:

Install brute-force blocker:

apt install fail2ban

Edit the configuration file to increase penalties:

sudo nano /etc/fail2ban/jail.local

Add this:

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
findtime = 10m
bantime = 1w
bantime.increment = true
bantime.factor = 4

This configuration:

# Restart fail2ban
sudo systemctl restart fail2ban

# View banned IPs
sudo fail2ban-client status sshd

# View bans in real-time
tail -f /var/log/fail2ban.log

Allow SSH only from your IP:

ufw allow from <YOUR_IP_ADDRESS> to any port 22 proto tcp
ufw deny 22/tcp

(Optional) Rate limit SSH connections

Deny connections from an IP address that has attempted to initiate 6 or more connections in the last 30 seconds.

ufw limit 22/tcp
# View results
journalctl -u ssh

# View last 50 results
journalctl -u ssh -n 50

# View results with search string
journalctl -u ssh --grep "Failed password"

Disable unused ports

Disable LLMNR (port 5355) - While useful for local network discovery, LLMNR can also be exploited for security vulnerabilities, such as poisoning and man-in-the-middle attacks.

sudo systemctl disable systemd-resolved
sudo systemctl stop systemd-resolved

Block port in ufw:

ufw deny 5355

Check ports with socket statistics

ss is a command-line tool that provides socket stats and displays various information based on various protocols. It can display port stats, TCP, UDP, RAW, and more.

ss -tuln:

Local Address:PortDefinition
0.0.0.0:*all IPv4 addresses on this system
[::]:*all IPv6 addresses on this system
*:*any address, any protocol family, any port

This is what ss -tuln outputs. Note: 12.345.67.890:123 should be <YOUR_IP_ADDRESS>:

Netid         State          Recv-Q          Send-Q                      Local Address:Port       Peer Address:Port    Process         
udp           UNCONN         0               0                           127.0.0.53%lo:53              0.0.0.0:*                       
udp           UNCONN         0               0                                 0.0.0.0:68              0.0.0.0:*                       
udp           UNCONN         0               0                           12.345.67.890:123             0.0.0.0:*                       
udp           UNCONN         0               0                               127.0.0.1:123             0.0.0.0:*                       
udp           UNCONN         0               0                                 0.0.0.0:123             0.0.0.0:*                       
udp           UNCONN         0               0                                 0.0.0.0:5355            0.0.0.0:*                       
udp           UNCONN         0               0                                 0.0.0.0:47020           0.0.0.0:*                       
udp           UNCONN         0               0                                       *:42091                 *:*                       
udp           UNCONN         0               0       [fe80::5400:5ff:fec1:87ec]%enp1s0:123                [::]:*                       
udp           UNCONN         0               0                                   [::1]:123                [::]:*                       
udp           UNCONN         0               0                                    [::]:123                [::]:*                       
udp           UNCONN         0               0                                    [::]:5355               [::]:*                       
tcp           LISTEN         0               4096                              0.0.0.0:5355            0.0.0.0:*                       
tcp           LISTEN         0               4096                        127.0.0.53%lo:53              0.0.0.0:*                       
tcp           LISTEN         0               128                               0.0.0.0:22              0.0.0.0:*                       
tcp           LISTEN         0               4096                                 [::]:5355               [::]:*                       
tcp           LISTEN         0               128                                  [::]:22                 [::]:*                       
tcp           LISTEN         0               256                                     *:3128                  *:*

General user account security configuration

(Optional) Create a sudo user and disable root

  1. Create a sudo user

    adduser <SUDO_USER>

    IMPORTANT: Test if you can SSH with the new user.

  2. Disable root (after confirming you can login via the new user)

    nano /etc/ssh/sshd_config

    Make sure these lines look like this (you may need to uncomment the line):

    PermitRootLogin no
    PasswordAuthentication no
    PubkeyAuthentication yes
    AuthorizedKeysFile .ssh/authorized_keys

    Restart ssh with one of these commands:

    systemctl restart ssh
    systemctl reload ssh

(Optional) Create SSH keys to connect without entering a password

ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_[YOUR_CUSTOM_NAME] -C "[YOUR_CUSTOM_DESCRIPTION]"

Create the path in your user directory first. You may need to create an empty file called authorized_keys in .ssh:

# Change file ownership of the .ssh contents to SUDO_USER only
sudo chown -R <SUDO_USER>:<SUDO_USER> /home/<SUDO_USER>/.ssh

# Change directory permissions (read, write, execute) to SUDO_USER only
sudo chmod 700 /home/<SUDO_USER>/.ssh

# Allow only SUDO_USER to read and modify the contents of authorized_keys
sudo chmod 600 /home/<SUDO_USER>/.ssh/authorized_keys

Then use this command to copy it from your local PC to the VPS server. Note: the .pub is the public one to copy:

ssh-copy-id -i ~/.ssh/id_ed25519_[YOUR_CUSTOM_NAME].pub user@<YOUR_VPS_IP_ADDRESS>

Connect to it using the private key on your local device:

ssh -i ~/.ssh/id_ed25519_[YOUR_CUSTOM_NAME] user@<YOUR_VPS_IP_ADDRESS>

If you want it to prompt for your private key passphrase when you use ssh user@<YOUR_VPS_IP_ADDRESS>, add this:

nano ~/.ssh/config
Host <YOUR_VPS_IP_ADDRESS>
  User <username>
  IdentityFile ~/.ssh/id_ed25519_[YOUR_CUSTOM_NAME]
  IdentitiesOnly yes

Browser Configuration

Network Settings

I recommend Firefox or a fork (Waterfox, LibreWolf) since you can set the proxy settings to affect only that browser instead of all traffic on the computer if you set it in your operating system’s network settings.

  1. Firefox > Settings > Network Settings (scroll all the way to the bottom of General)
  2. Select Manual proxy configuration
  3. Paste VPS IP address in the “HTTP Proxy” input box
  4. Paste “3128” in the “Port” input box
  5. Enable the checkbox for “Also use this proxy for HTTPS”
  6. Enable the checkbox for “Do not prompt for authentication if password is saved” if you want
  7. Select OK

Important Note

There is no encryption between you and the VPS

(Optional) Save login credentials

If it is not available, verify Ask to save passwords is enabled in Firefox settings. I have experienced issues where it did not prompt me to save. Try restarting the browser, and when it asks you for the credentials the first time, cancel or close it. Then visit a website, and it will prompt you again, hopefully with the checkbox or pop-up in the address bar.