Forward and Reverse Proxies in Nginx

✍🏼 Written on Jul 6, 2021   
❗️ Note: it has been days since this article was written, please be aware of its timeliness
🖥  Note:Everything stems from ignorance

The Origin of This Article

Because folder/file names cannot contain colons, I mistakenly thought Chrome couldn’t use its Override feature for URLs with port numbers. As a result, I planned to modify the port-included URLs of our internal remote testing environment to the default local port 80, enabling Chrome to override them. Later, I discovered that Chrome actually can override URLs with port numbers—simply decode the colon as %3a.

After realizing my own folly, and unwilling to accept that the hour I spent configuring Nginx as a forward proxy to solve the port issue was entirely unnecessary, I decided to document the process. At least the time I invested wouldn’t be wasted, and others might avoid similar pitfalls—hence this article.

Some of these concepts may be familiar to those who studied them in college, but this is written with beginners in mind.

Terminology Explained

Forward Proxy

A forward proxy is typically client-oriented. For example, your VPN is a forward proxy—local requests are routed through the proxy server’s configured rules before being sent to the remote server. Of course, you can also configure a forward proxy for server-side requests to other server resources, in which case the forward proxy is server-oriented.

The most widespread application of forward proxies is VPNs.

Reverse Proxy

As the name suggests, this is the opposite of a forward proxy. It’s a server-side concept. When a client’s request reaches the server, it first passes through the reverse proxy configured on the server for distribution, and then the traffic is routed to different servers.

Nginx reverse proxies are widely used on the server side—for example, in load balancing. A possible strategy is: if there are five servers, randomly count incoming requests, take the modulo 5 of the count, and route traffic to the first server if the remainder is 1, the second if it’s 2, and so on. Another example is path rewriting: if the requested path is xxx/yyy, it can be rewritten as zzz, and the traffic is then directed to the server, etc.

My Requirement

I needed to access http://baidu.com:8888``, but I wanted to access it via http://baidu.com:80—that is, `http://baidu.com—to reach `http://baidu.com:8888``. So, the working principle is the same as a VPN: a forward proxy.

Challenges

Overall, it’s not difficult—just set up server.listen on port 80, match the paths, and forward requests to the correct path (e.g., port 8888) using proxy_pass. The only slightly tricky part is handling WebSocket (ws) requests, which also need to go through the proxy. So, you’ll need to include this at the beginning of the HTTP configuration:

1
2
3
4
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

Then add the following within the server.location block:

1
2
3
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

Of course, it also involves proxy_set_header, proxy_pass, etc., which are beyond the scope of this discussion. Those interested can refer to the official documentation: http://nginx.org/en/docs/http/websocket.html.

Oh, I almost forgot—the nginx server starts locally at 127.0.0.1. So, if you want to access http://baidu.com`` to reach http://baidu.com:8888``, you’ll also need to modify your local hosts file to point 127.0.0.1 to baidu.com:

1
127.0.0.1  www.baidu.com

Some students might ask, why not directly specify the port in hosts? For example, like this:

1
127.0.0.1. www.baidu.com:8888

The answer is obvious: the hosts file doesn’t support ports~

Afterword

Since I’ve been working mainly on frontend and tooling, I haven’t had much exposure to server-side development. I still haven’t figured out how to install additional modules for nginx. A quick search suggests they need to be compiled together with nginx rather than installed like software plugins. The need for plugins arises because nginx doesn’t proxy HTTPS requests by default—additional modules are required for this functionality.

Nginx seems incredibly versatile! I should definitely take time to study it properly when I get the chance!

- EOF -
Originally published at: Forward and Reverse Proxies in Nginx - Xheldon Blog