3

I am trying to use nginx to pass an incoming connection to another server (the reason I am doing this -- the connection is coming in from a host that can't do DNS resolution, and the server that should ultimately receive the traffic needs to be resolved by DNS). I am using the following config:

stream {
        resolver 127.0.0.1 valid=1s;
        upstream server_us {
                server server.foo.com:22222;
        }
        server {
                listen 11111;
                proxy_pass server_us;
        }
}

I don't understand why the name resolution isn't expiring as specified by the "valid" directive. (i.e., if I change the IP for server.foo.com in /etc/hosts, nginx doesn't recognize the change). What am I doing wrong?

scottmlew
  • 85
  • 2
  • 10

1 Answers1

5

Nginx resolves literal domain names on start and caches resolved IPs forever.

There is resolve parameter in server directive to re-resolve domains, but it's only available in commercial subscription.

The common “hack” is to use variable in proxy_pass (but it will not be possible to use upstream directive).

The address can also be specified using variables

[...]

In this case, the server name is searched among the described server groups, and, if not found, is determined using a resolver.

E.g.

stream {
    resolver 127.0.0.1 valid=1s;

    # a hack to declare $server_us variable
    map "" $server_us {
        default server.foo.com:22222;
    }

    server {
        listen 11111;
        proxy_pass $server_us;
    }
}
Alexey Ten
  • 8,435
  • 1
  • 34
  • 36
  • Thanks for the reply. I didn't realize that the resolver is only available in the commercial version. The free version accepts it as valid, so I inferred it should work. I had tried the solution you gave (it was my first attempt after I realized nginx resolved all domain names on startup), but it is rejected as invalid with a "set directive is not allowed here" error. So this won't work, either. – scottmlew Apr 02 '20 at 13:16
  • @ScottL fixed answer – Alexey Ten Apr 02 '20 at 18:12
  • Alexey, thanks so much for your help. That syntax is accepted, but now the incoming stream doesn't seem to be redirected. I feel silly saying this, but I am not sure where it is going...right now I am testing using netcat and a netcat listener. netcat successfully connects on port 11111, but the traffic does not appear on port 22222 on either of the machines pointed to by the /etc/hosts entries I am switching between to resolve server.foo.com. It appears to be queued/cached by nginx, since nginx accepts the connection even if the server it's supposed to redirect to isn't listening. Any ideas? – scottmlew Apr 02 '20 at 22:17
  • AFAIK, DNS resolver does **not** use `/etc/hosts`. So you have to configure the resolver – Alexey Ten Apr 03 '20 at 08:12
  • See https://stackoverflow.com/a/8559797/1016033 – Alexey Ten Apr 03 '20 at 08:13
  • I now have dnsmasq setup (forwarding to the real DNS server that will be hosting the records that will change frequently), with nginx pointing to it, and Alexey's solution is working perfectly. Thank you again for the help! – scottmlew Apr 03 '20 at 16:52