21

I configured my Nginx as simple reverse proxy.

I'm just using basic setting

location / {
    proxy_pass foo.dnsalias.net;
    proxy_pass_header Set-Cookie;
    proxy_pass_header P3P;
}

The problem is that after some time (few days) the site behind nginx become unaccessible. Indead nginx try to call a bad ip (the site behind nginx is at my home behind my box and I'm a using a dyn-dns because my ip is not fixe). This dyn-dns is always valid (I can call my site directly) but for obscure reason Nginx get stuck with that..

So as said, nginx just give me 504 Gateway Time-out after some time. It looks like the error come when my ip change at home. Here is a sample of error log:

[error] ... upstream timed out (110: Connection timed out) while connecting to upstream, client: my.current.ip, server: myreverse.server.com, request: "GET /favicon.ico HTTP/1.1", upstream: "http://my.old
.home.ip", host: "myreverse.server.com"

So do you know why nginx is using ip instead of the DN ?

max54
  • 330
  • 1
  • 2
  • 13

2 Answers2

36

If the proxy_pass value doesn't contain variables, nginx will resolve domain names to IPs while loading the configuration and cache them until you restart/reload it. This is quite understandable from a performance point of view.

But, in case of dynamic DNS record change, this may not be desired. So two options are available depending on the license you possess or not.

Commercial version (Nginx+)

In this case, use an upstream block and specify which domain name need to be resolved periodically using a specific resolver. Records TTL can be overriden using valid=time parameter. The resolve parameter of the server directive will force the DN to be resolved periodically.

http {    

    resolver X.X.X.X valid=5s;

    upstream dynamic {
        server foo.dnsalias.net resolve;
    }

    server {

        server_name www.example.com;

        location / {
            proxy_pass http://dynamic;
            ...
        }

    }

}

This feature was added in Nginx+ 1.5.12.

Community version (Nginx)

In that case, you will also need a custom resolver as in the previous solution. But to workaround the unavailable upstream solution, you need to use a variable in your proxy_pass directive. That way nginx will use the resolver too, honoring the caching time specified with the valid parameter. For instance, you can use the domain name as a variable :

http {  

    resolver X.X.X.X valid=5s;

    server {

        server_name www.example.com;
        set $dn "foo.dnsalias.net"; 

        location / {
            proxy_pass http://$dn;
            ...
        }

    }

}

Then, you will likely need to add a proxy_redirect directive to handle redirects.

Xavier Lucas
  • 2,552
  • 20
  • 19
  • Sounds good, I will try this solution ang give feedback then. Thanks a lot. (community version) – max54 Nov 16 '14 at 17:43
  • I tried to use several resolver but nothing works, I always get `recv() failed (111: Connection refused) while resolving, resolver: X.X.X.X:53` with X as different ip adress I tried. – max54 Nov 17 '14 at 16:49
  • (too late edit) What exactly should I put in resolver ? – max54 Nov 17 '14 at 16:56
  • @max54 That's an other issue there. It means nothing is listening at X.X.X.X:53 or that a firewall is blocking you from accessing it. What's the output of `dig foo.dnsalias.net @X.X.X.X` ? You should set in this directive a list of DNS such as the ones in `/etc/resolv.conf`. – Xavier Lucas Nov 17 '14 at 17:02
  • Xavier Lucas after some time it seems that it doesn't work, my ip still is the wrong after it changed. I followed your second instrcutions about non commercial version. Still need any help :/ – max54 Nov 24 '14 at 23:18
  • @max54 I'm using this setup myself and it **works** so this is coming from something else in your machine/network and this is no more in the scope of the orignal question. Run tcpdump to convince yourself of DNS requests getting issued every `valid` period. Thus that's not really appropriate to unaccept answers like you do, without even trying to figure what's wrong on the rest of your plateform. – Xavier Lucas Nov 25 '14 at 01:15
  • You are right, my apologies. I will take another look to my whole configuration :) – max54 Nov 25 '14 at 07:36
  • this is a good solution, but keep in mind it might break your proxy_redirect if you're relying on the [default behaviour](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect) – p3drosola Apr 26 '15 at 21:00
5

Maybe check this out http://forum.nginx.org/read.php?2,215830,215832#msg-215832

resolver 127.0.0.1;
set $backend "foo.example.com";
proxy_pass http://$backend;

In such setup ip address of "foo.example.com" will be looked up
dynamically and result will be cached for 5 minutes.
DOA
  • 362
  • 1
  • 2
  • 10
  • This can be improved by adding $request_uri to the end of your $backend line. set $backend "foo.example.com/$request_uri"; – sjwoodr Apr 06 '18 at 14:20