0

upstream does not work when the proxyed server has more than one host name binding on the same port.

I ran into this issue while trying to configure nginx (1.9.12-1~trusty) to proxy_pass a Windows Server 2012 host.

I have reproduced the same behavior on my own Windows 10 machine.

In the below configuration all host names point to the same machine IP.

Requests work sometimes

Note: I exepect this is when localhost:7778 is choosen to be proxyed.

http {
    upstream w {
        server test1:80;
        server test2:80;
        server localhost:7778;
    }

    server {
        listen       8001;
        server_name  localhost;

        location / {
            proxy_pass http://w;
        }
    }
}

Requests work none of the time

Note: edited as pointed out by Alexey.

http {
    upstream w {
        server test1:80;
        server test2:80;
        # server localhost:7778;
    }

    server {
        listen       8001;
        server_name  localhost;

        location / {
            proxy_pass http://w;
        }
    }
}

Requests work all the time

http {

    server {
        listen       8001;
        server_name  localhost;

        location / {
            proxy_pass http://test1:80;
        }
    }
}

or

http {

    server {
        listen       8001;
        server_name  localhost;

        location / {
            proxy_pass http://test2:80;
        }
    }
}

or

http {

    server {
        listen       8001;
        server_name  localhost;

        location / {
            proxy_pass http://localhost:7778;
        }
    }
}

Is there a way around this?

Michael
  • 3
  • 1
  • 1
  • 3
  • Second example misses `http://` in `proxy_pass`. Too bad that your upstreams require different hostnames. You should configure them to use the same name and use that name in `proxy_set_header Host ....` – Alexey Ten Mar 07 '16 at 21:27
  • proxy_set_header Host is the answer, do you want to add an answer? – Michael Mar 08 '16 at 09:57

1 Answers1

6

When you use proxy_pass without proxy_set_header directives, nginx will use some default headers. Most times it's what you would want or, at least, harmless, but in your case you have to set them manually.

When you write proxy_pass http://w, nginx will set proxy_set_header Host w. If you need another Host header, you should set it explicitly. Most common is to use proxy_set_header Host $host (or proxy_set_header Host $http_host).

So this should work for you:

upstream w {
    server test1:80;
    server test2:80;
    server localhost:7778;
}

server {
    listen       8001;
    server_name  localhost;

    location / {
        proxy_pass http://w;
        proxy_set_header Host $host;
    }
}
Alexey Ten
  • 8,435
  • 1
  • 34
  • 36
  • It's worth noting, that setting the host explicitly (rather than using $host) can help when testing (getting familiar with) this behavior. – Michael Mar 08 '16 at 22:01