16

I would like to use nginx to proxy an entire range (9000-9999) to the same port on a different ip address. Is it possible for nginx to automatically bind to a thousand ports? Can I do this without writing 4000 lines of nginx configuration?

3 Answers 3

14

You can do this with the built-in server_port variable:

proxy_pass http://backend-host-name:$server_port;

That would make whatever port the request came in on be proxied to the same back-end port.

So you don't need 1000 proxy_pass statements. But, you may have a problem with the listen directive. It won't accept a range of ports, so you will need 1000 lines of the form:

listen 9000;
listen 9001;
listen 9002;

That list can be easily generated with a spreadsheet. You will probably also need to adjust the number of file handles allowed by nginx to handle this number of sockets. Nginx can do it, the limits may be at the OS layer. See here and here.

I will say, though that this seems to be a problematic design. Why do you need 1000 ports? Wouldn't using host names or some part of the URL to differentiate requests make more sense? It would be far more scalable - no need for 2000 sockets as a baseline.

1
  • Using the port, or even the IP address, the parsing of the query is in hands of the network. Sort of level 5 or 6 service, instead of level 7 parsing. Probably faster.
    – arivero
    Jun 24, 2019 at 10:10
11

Since NGINX version 1.15.10 the listen directive accepts port ranges.

From the documentation:

Port ranges (1.15.10) are specified with the first and last port separated by a hyphen:

listen 127.0.0.1:12345-12399;
listen 12345-12399;

Thus, using

server {
    listen 9000-9999;

    proxy_pass http://upstream-host:$server_port;
}

should do the trick.

It is important to note that he number of worker connections has to be adjusted accordingly, otherwise, NGINX will issue an error:

# nginx -s reload
nginx: [emerg] 512 worker_connections are not enough for 1000 listening sockets
9

Here's what I ended up doing instead:

server {
    server_name "~^port(?P<forwarded_port>9\d{3})\.example\.com$";
    location / { proxy_pass http://127.0.0.1:$forwarded_port; }
}

That way, you can simply connect to http://port9034.example.com;

1
  • 3
    This may open a huge security flaw on a system when used carelessly, and it's easy exploitable. Jul 9, 2023 at 21:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .