Category: Web Server and InfrastructureUpdated 2026-10-18

Reverse proxy

A reverse proxy is a server that sits in front of one or more backend servers, accepts requests from clients, forwards them to the right backend and returns the response. Clients talk only to the proxy. It is used for TLS termination, caching, load balancing and hiding the origin server, and nginx is one of the most common ones.

What a reverse proxy is and how it differs from a forward proxy

The MDN guide splits proxies in two. A forward proxy acts on behalf of clients, for example to cache or hide who is browsing. A reverse proxy does the opposite: it acts on behalf of servers, controlling and protecting access to them for load balancing, authentication, decryption or caching. Visitors see one public address and never learn which backend answered.

In nginx, the reverse proxy guide describes the job as sending a client request to a proxied server, fetching the response and returning it to the client. The key directive is proxy_pass, placed in a location. It can point to one backend or a named group of servers, and sibling directives such as fastcgi_pass and uwsgi_pass cover non-HTTP application protocols. Typical jobs: terminating TLS once at the edge, caching responses, and spreading load.

A minimal nginx reverse proxy and how to test it

This block terminates TLS and passes requests to an application on the same host. Setting Host matters because, as the nginx documentation says, it defaults to $proxy_host, the address of the backend:

server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate     /etc/ssl/example.com.crt;
    ssl_certificate_key /etc/ssl/example.com.key;
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Validate and reload without dropping connections with sudo nginx -t && sudo systemctl reload nginx, then check the response headers with curl -I https://example.com/. Remember that a URI in proxy_pass replaces the matching part of the request path, while none passes it unchanged, as the proxy module reference explains. By default nginx also buffers the backend response (proxy_buffering on) and waits at most 60 seconds between reads (proxy_read_timeout).

Real client IP and the trust problem

Behind a proxy, the backend sees the proxy's address as the client. The X-Forwarded-For header carries the original address, but MDN is blunt: if the server is reachable directly, no part of that list can be trusted, and security uses such as rate limiting must use only addresses added by a trusted proxy. Any client can send a forged header.

The realip module is not built by default and replaces the client address only for senders you list:

set_real_ip_from 192.0.2.10;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

Trust only the addresses of your own proxies. A wide set_real_ip_from range lets anyone inside it pick their own apparent address and slip past limit_req or allow lists. With several proxies in a chain, real_ip_recursive on makes nginx pick the last non-trusted address in the header instead of simply the last one.

Security benefits, risks and where it fits

A reverse proxy adds one place to enforce TLS settings, security headers, rate limits and a WAF, and a CDN in front can absorb floods before they reach you. It also hides the origin, but only while the origin address stays private. If the backend still answers on the open internet, attackers can bypass the proxy entirely, so firewall it to accept traffic from the proxy only.

The risks are configuration ones. A proxy is a single point of failure. Misplaced trust in forwarded headers breaks logging and limits. Building the proxy_pass target from client-controlled input such as $http_host lets visitors choose where nginx connects, which turns it into an open proxy. Work through the nginx security guide, and see the DDoS protection guide for the CDN role and SYN flood handling.

Related terms: nginx, TLS / SSL, WAF, Rate limiting, limit_req.

Frequently asked questions

What is a reverse proxy in simple terms?

It is a server in front of your real servers. Visitors connect to it, and it passes their requests to the right backend and returns the answer.

What is the difference between a forward proxy and a reverse proxy?

A forward proxy acts on behalf of clients, for example to hide or cache their traffic. A reverse proxy acts on behalf of servers, for load balancing, caching, decryption and protection.

How does nginx act as a reverse proxy?

Use the proxy_pass directive inside a location block to send requests to a backend such as http://127.0.0.1:8000. Add proxy_set_header lines to pass the Host header and the client address.

Can I trust the X-Forwarded-For header?

Only the part added by a proxy you control. Clients can send any value, so configure the realip module with set_real_ip_from for your own proxies only.

Does a reverse proxy hide my server completely?

No. It hides the origin address only while that address stays unknown and the origin refuses direct connections. Restrict the backend to traffic from the proxy and keep its address private.

Want to see where your own server stands?

Run the free, read-only server check, or open the Security Lab and watch the detect, contain, recover, verify loop in action.

Get your free server checkOpen the Security Lab