NGINX Unit 1.13.0 and 1.14.0 Introduce Reverse Proxying and Address-Based Routing

by

in

It’s been quite a while since our last post, and we’ve got major news to share about our latest NGINX Unit releases, namely 1.13.0 and 1.14.0. They introduce new features that add to our toolset and extend the range of scenarios where you can take advantage of NGINX Unit – reverse proxying in NGINX Unit 1.13.0 and address‑based routing in NGINX Unit 1.14.0. Let’s look at the two new features in detail.

HTTP Reverse Proxying

In a sense, the very name NGINX has come to mean reverse proxying. While this may not be necessarily warranted (NGINX Plus is much more than a one‑trick pony), what matters now is that the feature has come to NGINX Unit as well, becoming a family trait of sorts.

NGINX Unit enables reverse proxying within its general routing framework: the new proxy option, which configures proxying of requests to a specified address, joins the pass and share options already familiar to you from our posts about internal routing and static file serving. As of this writing, the proxy address configuration supports IPv4, IPv6, and Unix socket addresses.

Here’s a sample routes object with the proxy option enabled:

If an incoming request satisfies the match condition, NGINX Unit establishes a proxy connection to the address specified by the proxy option and relays the request to it, returning the response (or an error status) to the client. Otherwise, the request is matched against subsequent match conditions in the route.

At first glance, the configuration may seem rather bland. However, this is only the beginning of NGINX Unit’s evolution as a reverse proxy, and even in this basic form it enables you to offload requests that don’t require NGINX Unit’s dynamic capabilities to other servers, and to architect custom request‑processing scenarios by chaining NGINX Unit listeners and instances.

Earlier versions of NGINX Unit, despite their many capabilities, could serve only as endpoints for incoming client requests. Now NGINX Unit can serve as an intermediate node within your web framework as well, accepting all kinds of traffic, maintaining a dynamic configuration, serving high‑demand requests on its own, and acting as a reverse proxy for your existing backend solutions.

Keep in mind, however, that the availability of proxied addresses isn’t automatically validated; if you misconfigure an address or accidentally create a redirect loop, NGINX Unit reports an error only when a request is unsuccessful.

For further details, see our documentation.

Address-Based Routing

Address‑based routing, added in NGINX Unit 1.14.0, extends the routing mechanism, enabling address matching against two newly introduced match options: source and destination. The former matches the connected client’s IP address, whereas the latter matches the target address of the request.

With this release, NGINX Unit’s routing engine can now match address values against individual IPv4‑ or IPv6‑based patterns and arrays of patterns. In turn, valid patterns may be wildcards with port numbers, exact addresses, or address ranges in CIDR notation:

This type of matching can be freely combined with other matching types. As with the match conditions introduced in previous releases, you can negate address‑based patterns by prefixing them with the exclamation mark (!). In the following example, the destination option matches all target addresses except 127.0.0.1:

For further details, see our documentation.

Use Case: IP Address Filtering and Access Management

Finally, let’s explore the pragmatic synergy of both newly introduced capabilities. Consider a scenario where we have two largely identical servers, 192.168.1.100 and 192.168.1.101, each running a single web app instance on port 8080. We want them to serve internal and external users alike, enforcing several limitations in the process:

  • Users in some regions of the globe are denied access.
  • Of all local users, only the admin has access to the privileged section of the app.
  • A trusted partner has access to the same section on par with the admin.
  • Static files are served separately to improve the app servers’ performance.
  • Administrative operations are limited to a single server to improve security.

In a rather unexpected turn of events, here we employ NGINX Unit as a reverse proxy only, to display its newly acquired capabilities. (To view or download the complete configuration for this use case, click view raw in the footer of any of the next three snippets.)

Let’s start with the entry points. In our NGINX Unit instance, we set up two listeners for external and internal traffic, configuring two distinct certificate bundles for added security and pointing each listener to a different route:

We define the two routes (internal and external) to introduce domain‑specific limitations for incoming traffic. Both routes have a match condition that enforces administrator‑only access to the /admin URI: the internal route allows access only to local users who possess a specific cookie, while the external route allows access only from a particular IP address belonging to a trusted partner. The other match condition in each route allows access to all non‑admin URIs by local users and by users on any external IP address outside the restricted partner network, respectively. Both routes channel all valid traffic to a route called common.

Here’s the common route with three match conditions that respectively offload static file handling from the app servers, direct administrative operations to a single server address (192.168.1.100) to improve security and troubleshooting), and facilitate session persistence by assigning all requests arriving via the listener for the internal route to the server that also handles administrative requests. The final action object unconditionally relays all remaining requests to the second of the two servers (192.168.1.101). Separating internal and non-administrative external traffic in this way simplifies access monitoring and rights management.

What’s Next

The latest release of NGINX Unit arrived in late December, but our sights are already trained on a few important improvements that shall contribute to the steady evolution of our project. These include round‑robin load balancing, rootfs support to advance our initial app isolation a tad further, advanced logic for handling static assets, memory performance improvements, and extended networking capabilities. Stay tuned!

We’re interested in other capabilities you want to see in NGINX Unit. Please visit our GitHub repository to join the discussions and development.

For a list of all changes in releases 1.13.0 and 1.14.0, see the NGINX Unit changelog.