Nginx proxy_pass redirect to URL from query string

Viewed 1970

I'm using Nginx and trying to redirect using proxy_pass to a URL that comes as a query string. I also want to avoid passing any other parameters to that URL.

This is the url I'm sending to the proxy: http://10.10.10.10/proxydownload?url=http://www.test.com/d/guid/download&session=123

This is what I have in the nginx.conf:

location /proxydownload {
    proxy_pass $arg_url;
}

However, this is generating a 502 error, and I don't know why. According to the logs, $arg_url contains "http://www.test.com/d/guid/download", and that's the url I want to hit. I tried to hardcode the URL in proxy_pass and it worked:

location /proxydownload {
    proxy_pass http://www.test.com/d/guid/download;
}

Is there's something incorrect on the way I use $arg_url?

2 Answers

This happens because when you hardcode the value passed to http://nginx.org/r/proxy_pass, without using any variables, then the default resolver, from /etc/resolv.conf, is used at the time that the configuration is parsed and loaded — any subsequent changes in the IP address won't be picked up.

If, instead, you use variables, then you must also use the http://nginx.org/r/resolver directive to specify a resolver. Note that you can still use a DNS name when specifying a resolver, but keep in mind that such name will likely only be resolved once, at configuration load or reload time. Of course, as per Dayo's answer, it's best to use a local DNS resolver for best security, but if, for example, you know that all your domains will be delegated to a certain authoritative nameserver, for example, including ns2.he.net., then you might as well simply specify such a server as the resolver.

Speaking of security, however, it doesn't seem like a very good idea to trust user's input for specification of the upstream server. This is one of these things that greatly increases the attack vector — both for using your server as a free proxy_pass to anywhere on the internet (potentially exhausting your resources from being available for valid use), as well as by a malicious actor to try to exploit a potential vulnerability in your nginx by a malicious upstream server controlled by the attacker (take a look at CVE-2013-2070, for example).

Using proxy_pass with variables is a complex and poorly documented minefield.

I assume your 502 error was "no resolver defined to resolve ..."

In this case, you need to install bind (yum install bind) and add a resolver to your config.

location /proxydownload {
    resolver 127.0.0.1 [::1];
    proxy_pass $arg_url;
}

Using an external resolver such as Google's 8.8.8.8 would work without the need for bind but there are Potential Security Issues.

Related