1

When I set my reverse proxy to forward from it's own port 80 to it's own port 8080, I do so, i get the following warning

2016/03/28 22:05:59 [alert] 4193#0: 512 worker_connections are not enough

which is presumably the result of an infinite loop.

In the accepted answer for Nginx Config: Front-End Reverse Proxy to Another Port, the user wrote "I'm assuming that nginx is not the server listening on port 5010 as well as 80, correct?" Is that because reverse proxies can't forward to themselves? Or is there another reason why this infinite loop is happening, and that comment was just a red herring?

Below is my nginx.conf. I get the warning when I go to router.example.com. When I remove what's between #### BEGIN BAD LINES ####, it works well.

user    root;
worker_processes    1;
worker_cpu_affinity 0101;
master_process  off;
worker_priority 10;
error_log   /tmp/var/log/nginx/error.log;
pid /tmp/var/run/nginx.pid;
worker_rlimit_nofile    8192;
events {
    worker_connections  512;
}
http {
    log_format   main '$remote_addr - $remote_user [$time_local]  $status '
    '"$request" $body_bytes_sent "$http_referer" '
    '"$http_user_agent" "$http_x_forwarded_for"';

    # Because end of http://nginx.org/en/docs/http/server_names.html
    server_names_hash_bucket_size  64; 


    # From NixCraft
    # http://www.cyberciti.biz/tips/using-nginx-as-reverse-proxy.html

    # Host required
    server {
        listen      80 default_server;
        server_name "";
        return      444;
    }

  #### BEGIN BAD LINES ####
    ## Start router proxy ##
    server {
        listen       80;
        server_name  router.example.com
                     tomatopaste.example.com;
        access_log  /var/log/nginx/log/router.example.access.log  main;
        error_log  /var/log/nginx/log/router.example.error.log;

        ## send request back to apache1 ##
        location / {
            proxy_pass  http://192.168.1.1:8080/;
            proxy_redirect default;
            proxy_buffering off;
            proxy_set_header        Host            $host;
            proxy_set_header        X-Real-IP       $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
    ## End ##
  #### END BAD LINES ####


    ## Start primary proxy ##
    server {
        listen       80;
        server_name  jira.example.com
                     confluence.example.com
                     stash.example.com
                     cacti.example.com;
        access_log  /var/log/nginx/log/lamp.example.access.log  main;
        error_log  /var/log/nginx/log/lamp.example.error.log;

        ## send request back to apache1 ##
        location / {
             proxy_pass  http://192.168.1.99/;
             proxy_redirect default;
             proxy_buffering off;
             proxy_set_header        Host            $host;
             proxy_set_header        X-Real-IP       $remote_addr;
             proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
    ## End ##



    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }

    # Websockets
    server {
        listen 8686;
        server_name other.example.com;
        location / {
            proxy_pass http://192.168.1.99:8686;
            proxy_redirect default;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }
    } 
}
  • 1
    Nginx has no problem to proxy to itself. I don't see where it listens to 8080 though – Alexey Ten Mar 29 '16 at 04:04
  • 4
    Small nitpick: the official domain name to use in examples and for hiding your real domain name is [example.com](https://example.com) rather than sample.com. Other domain names tend to be owned by people already ([sample.com is owned](https://web.archive.org/web/sample.com)). – Olathe Mar 29 '16 at 04:31
  • @Olathe Whoops. Thanks for the heads up. I must have been more tired than I realized last night writing it. Fixed! – TinyTheBrontosaurus Mar 29 '16 at 11:42
  • @alexeyTen The 8080 listen is not part of nginx, but it is on the same IP. It's part of AdvancedTomato, so I believe it's apache (?) – TinyTheBrontosaurus Mar 29 '16 at 11:43

1 Answers1

1

I think the issue is not one of "Why can't a reverse proxy point to itself?" so much as "Why shouldn't a reverse proxy point to itself?". As commenters have pointed out, nginx, httpd, and other proxy software can be configured to proxy connections back to themselves; nothing in the software or configuration prevents this.

However, as you surmise, the issue becomes one of resources. An HTTP reverse proxy, configured to proxy requests back to itself (either directly or indirectly via another proxy, such as httpd) needs to maintain some state for that request (in order to send the response back to the caller). If the request simply loops through the same proxies repeatedly (due to configuration), eventually some state/resource limit is reached, e.g.:

512 worker_connections are not enough

and the request forwarding terminates. Thus the answer to "Why shouldn't a reverse proxy point at itself?" is: "Eventually the reverse proxy runs out of resources and is unable to properly service the request." As the number of reverse proxies in the chain increases, the probability of inadvertent configuration leading to a loop/cycle increases, and as the number of proxies in the loop increases, the harder it can be to detect that such a loop is happening. (Perhaps applications like httpd and nginx can examine headers like X-Forwarded-For, assuming the header value is trusted, to detect such loops, i.e. to see if the proxy itself already appears in that forwarding chain?)

In your particular case, to prove empirically that it is indeed an infinite loop of forwarding, we would need to correlate the httpd log entries with the nginx log entries; I suspect that we would indeed see the cycle in the graph of reverse proxing by doing so.

Hope this helps!

Castaglia
  • 3,239
  • 3
  • 19
  • 40