Understanding Proxies and Reverse Proxies: A Complete Guide
Imagine you want to send a letter to someone, but you don't want them to know your home address. What do you do? You might ask a friend to send it on your behalf. In the computer world, proxies work similarly — they're middlemen that help you communicate safely and efficiently.
What is a Forward Proxy?
The Simple Explanation
A forward proxy (often just called a "proxy") is a server that sits between you and the internet. When you want to visit a website or download something, your request first goes to the proxy server, which then fetches what you want and brings it back to you.
Think of it like this: you're in a restaurant, and instead of going to the kitchen yourself, you tell the waiter what you want. The waiter goes to the kitchen, gets your food, and brings it to you. The kitchen staff never sees you directly — they only see the waiter.
The Real-World Problem It Solves
Consider a very common situation in companies:
- Your server lives in a private subnet with no direct internet access.
- You still need to download packages, Docker images, and OS updates from the internet.
The naive options are:
- Attach a public IP to the server (high risk).
- Give it direct outbound NAT access (still expands your attack surface).
Both are bad for DMZ or production workloads.
The better solution is a forward proxy:
Your Private Server → Forward Proxy → Internet → Target Site
- You make a request (e.g., to download a package from
pypi.org). - The request is sent to your company's proxy server.
- The proxy (which has controlled internet access) calls
pypi.org. - The website sees the proxy's IP, not your private server.
- The proxy returns the response back to your server.
More Benefits of Forward Proxy
1. Privacy and Anonymity
Websites only see the proxy's IP address, not the real client. It's like wearing a mask on the internet.
2. Access Control
- Block social media or specific sites during work hours.
- Prevent access to malicious domains.
- Log and audit outbound traffic.
- Whitelist only approved destinations (e.g., package registries).
3. Content Filtering
Schools and enterprises use forward proxies to block inappropriate or risky content. Every request passes through the proxy, which can decide whether to allow or deny it.
4. Faster Access (Caching)
Forward proxies can cache responses:
- If 100 developers download the same Docker image, the proxy fetches it once and serves it from cache for the rest.
- This saves both bandwidth and time.
5. Bypass Geographic Restrictions
If the proxy is in another country, sites see the proxy's location, not yours. This is how some users access geo-restricted content (subject to legal and policy constraints).
Setting Up Squid Forward Proxy (Step-by-Step)
Installation
Ubuntu/Debian:
sudo apt update
sudo apt install squid -y
RHEL/CentOS/Fedora:
sudo yum install squid -y
# or
sudo dnf install squid -y
Basic Squid Configuration
Edit the Squid configuration file:
sudo nano /etc/squid/squid.conf
Basic configuration example:
# Squid listening port
http_port 3128
# Define your internal network (adjust to your subnet)
acl localnet src 192.168.1.0/24
acl localnet src 10.0.0.0/8
# Safe ports (standard HTTP/HTTPS)
acl SSL_ports port 443
acl Safe_ports port 80 # http
acl Safe_ports port 443 # https
acl Safe_ports port 21 # ftp
acl CONNECT method CONNECT
# Deny requests to unsafe ports
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
# Allow localhost and local network
http_access allow localhost
http_access allow localnet
# Deny all other access
http_access deny all
# Cache settings
cache_dir ufs /var/spool/squid 10000 16 256
cache_mem 256 MB
maximum_object_size 50 MB
# Logging
access_log /var/log/squid/access.log squid
cache_log /var/log/squid/cache.log
Advanced Squid Configuration with Authentication
# Enable basic authentication
auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwords
auth_param basic children 5
auth_param basic realm Squid Proxy Authentication
auth_param basic credentialsttl 2 hours
# Define authenticated users ACL
acl authenticated_users proxy_auth REQUIRED
# Allow authenticated users
http_access allow authenticated_users
http_access deny all
Create password file:
sudo apt install apache2-utils # Ubuntu/Debian
sudo yum install httpd-tools # RHEL/CentOS
# Create user
sudo htpasswd -c /etc/squid/passwords username
sudo chown proxy:proxy /etc/squid/passwords
sudo chmod 640 /etc/squid/passwords
Domain Whitelisting Configuration
# Whitelist specific domains only
acl allowed_domains dstdomain .github.com .pypi.org .npmjs.com .docker.io
acl localnet src 192.168.1.0/24
http_access allow localnet allowed_domains
http_access deny all
Start and Enable Squid
# Check configuration syntax
sudo squid -k parse
# Start Squid
sudo systemctl start squid
sudo systemctl enable squid
# Check status
sudo systemctl status squid
# View logs
sudo tail -f /var/log/squid/access.log
Firewall Configuration
# UFW (Ubuntu)
sudo ufw allow 3128/tcp
# Firewalld (RHEL/CentOS)
sudo firewall-cmd --permanent --add-port=3128/tcp
sudo firewall-cmd --reload
Configuring Linux Clients to Use Proxy
Temporary (Current Session Only)
export HTTP_PROXY="http://proxy.company.com:3128"
export HTTPS_PROXY="http://proxy.company.com:3128"
export NO_PROXY="localhost,127.0.0.1,.company.internal,192.168.1.0/24"
# Some tools use lowercase
export http_proxy="$HTTP_PROXY"
export https_proxy="$HTTPS_PROXY"
export no_proxy="$NO_PROXY"
Verify:
echo $HTTP_PROXY
echo $HTTPS_PROXY
echo $NO_PROXY
System-Wide (All Users)
Edit /etc/environment:
HTTP_PROXY="http://proxy-server.com:3128"
HTTPS_PROXY="http://proxy-server.com:3128"
NO_PROXY="localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16"
http_proxy="http://proxy-server.com:3128"
https_proxy="http://proxy-server.com:3128"
no_proxy="localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16"
User-Level (Shell Profile)
Add to ~/.bashrc or ~/.zshrc:
export HTTP_PROXY="http://proxy-server.com:3128"
export HTTPS_PROXY="http://proxy-server.com:3128"
export NO_PROXY="localhost,127.0.0.1,.internal"
export http_proxy="$HTTP_PROXY"
export https_proxy="$HTTPS_PROXY"
export no_proxy="$NO_PROXY"
Application-Specific Proxy Settings
APT (Debian/Ubuntu)
sudo nano /etc/apt/apt.conf.d/proxy.conf
Acquire::http::Proxy "http://proxy-server.com:3128";
Acquire::https::Proxy "http://proxy-server.com:3128";
YUM/DNF (RHEL/CentOS/Fedora)
sudo nano /etc/yum.conf
proxy=http://proxy-server.com:3128
Docker (systemd)
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo nano /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://proxy-server.com:3128"
Environment="HTTPS_PROXY=http://proxy-server.com:3128"
Environment="NO_PROXY=localhost,127.0.0.1,.internal"
sudo systemctl daemon-reload
sudo systemctl restart docker
Git
git config --global http.proxy http://proxy-server.com:3128
git config --global https.proxy http://proxy-server.com:3128
npm
npm config set proxy http://proxy-server.com:3128
npm config set https-proxy http://proxy-server.com:3128
pip
pip install package_name --proxy http://proxy-server.com:3128
or ~/.pip/pip.conf:
[global]
proxy = http://proxy-server.com:3128
Proxy with Authentication
export HTTP_PROXY="http://username:password@proxy-server.com:3128"
export HTTPS_PROXY="http://username:password@proxy-server.com:3128"
Security note: avoid storing plain-text passwords in files; prefer secure secrets handling where possible.
Testing Your Proxy Configuration
curl -I http://google.com
wget http://google.com
# Explicitly using a proxy
curl -I -x http://proxy-server.com:3128 http://google.com
# Test with authentication
curl -I -x http://username:password@proxy-server.com:3128 http://google.com
Setting Up Proxy in Windows (High Level)
- Use environment variables (Command Prompt or System Properties).
- Or configure Windows system proxy under Network & Internet → Proxy.
- Add exceptions for internal hosts, similar to
NO_PROXY.
What is a Reverse Proxy?
The Simple Explanation
With a forward proxy, the proxy sits in front of clients. With a reverse proxy, it sits in front of your servers.
From the outside world, everyone talks to the reverse proxy (for example Nginx or HAProxy). The reverse proxy then decides which backend server will actually handle the request.
A good mental model: your servers are in a secure room, and the reverse proxy is the receptionist at the front desk. Visitors (clients) never walk past the desk without going through the receptionist first.
A Real-World Scenario
Imagine you run an online store with multiple backend servers:
- Web Server 1 — handles some of the traffic.
- Web Server 2 — handles more traffic.
- API Server — serves API requests.
Without a reverse proxy:
- Clients connect directly to the IP of each server.
- Your real server IPs are exposed to the internet.
- Some servers may get overloaded while others are idle.
- You might need to manage SSL certificates on every server.
With a reverse proxy in front:
Client → Reverse Proxy → [ Web Server 1, Web Server 2, API Server ]
- Client connects to
https://yourshop.com. - DNS points
yourshop.comto the reverse proxy's IP. - The reverse proxy receives the request and decides where to send it.
- It forwards the request to one of the backend servers.
- The backend responds to the reverse proxy, which returns the response to the client.
Key Things a Reverse Proxy Can Do
1. Hide and Protect Your Servers
- Clients only see the reverse proxy IP, not the real servers.
- You can put strict firewall rules around your backend network.
2. Load Balancing
Distribute requests across multiple servers so one machine is not overloaded:
- Round Robin — send requests to each server in turn.
- Least Connections — send to the server with the fewest current connections.
- IP Hash — keep the same client going to the same server (helps with sessions).
3. SSL Termination
You can terminate HTTPS at the reverse proxy:
- Clients talk HTTPS to the reverse proxy.
- The reverse proxy talks HTTP or HTTPS to the backends.
- Only one place to manage and renew certificates instead of many.
4. Caching and Compression
- Cache static content (images, CSS, JS) at the edge and serve it quickly.
- Compress responses (gzip/brotli) before sending them to clients.
5. Single Entry Point for Microservices
You can route different URL paths to different services behind the reverse proxy:
location /api/ { proxy_pass http://localhost:8000/; }
location /users/ { proxy_pass http://localhost:8001/; }
location /payments/ { proxy_pass http://localhost:8002/; }
Setting Up Nginx Reverse Proxy (Step-by-Step)
Installation
Ubuntu/Debian:
sudo apt update
sudo apt install nginx -y
RHEL/CentOS/Fedora:
sudo yum install nginx -y
# or
sudo dnf install nginx -y
Basic Reverse Proxy Configuration
Create a new site configuration:
sudo nano /etc/nginx/sites-available/reverse-proxy
Simple single backend configuration:
server {
listen 80;
server_name example.com www.example.com;
location / {
proxy_pass http://192.168.1.100:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}