리버스 프록시시 nginx가 업스트림의 호스트 이름을 전달하도록 설정


89

호스트 이름으로 여러 도커 컨테이너를 실행합니다.

web1.local web2.local web3.local

nginx에 의한 호스트 이름을 기반으로 수행됩니다. 이 설정 앞에 (인터넷에 연결된 다른 컴퓨터에서) 다음과 같이 업스트림을 정의하는 프록시가 있습니다.

    upstream main {
      server web1.local:80;
      server web2.local:80;
      server web3.local:80;
    }

실제 가상 호스트 설명 :

    server {
      listen 80;
      server_name example.com;
      location / {
        proxy_pass http://main;
      }
    }

이제 컨테이너는 "web1.local"대신 "main"호스트 이름을 수신하므로 요청에 제대로 응답하지 않습니다.

질문 : 요청을 프록시 할 때 Host : 헤더의 업스트림 서버 그룹 이름 대신 nginx에 업스트림 서버 이름을 전달하도록하려면 어떻게해야합니까?


3
나는 당신이 할 수 있다고 생각하지 않습니다. 왜 백엔드 서버가 main 또는 example.com에 응답하도록 설정하지 않습니까? 그것은 백엔드가 누구인지하지 않는 것처럼 아니다 것입니다. 반대의 경우도 가능합니다 : proxy_set_header Host $ host; 업스트림에서 돌아 오는 호스트 변수를 원래 요청의 호스트 이름으로 바꿉니다.
Andrew Domaszek

올바른 방법은 응용 프로그램을 수정하는 것입니다.
Michael Hampton

답변:


109

실제로 proxy_set_header를 통해 그렇게 할 수 있습니다.

자세한 내용은 http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header를 참조하거나 여기에서 유스 케이스 예제를 참조하십시오. https://stackoverflow.com/questions/12847771/configure-nginx- with-proxy-pass

위의 게시 구성에 동적 접근 방식을 포함 시켰습니다.

server {
  listen 80;
  server_name example.com;
  location / {
    proxy_pass       http://main;
    proxy_set_header Host            $host;
    proxy_set_header X-Forwarded-For $remote_addr;
  }
}

정적 호스트 이름을 가진 예는 다음과 같습니다.

server {
  listen 80;
  server_name example.com;
  location / {
    proxy_pass       http://main;
    proxy_set_header Host            www.example.com;
    proxy_set_header X-Forwarded-For $remote_addr;
  }
}

7
proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for; 더 좋아 보인다
Sivann

1
@pavel : 알겠습니다. 실제로 나는 약간의 연구와 테스트도했다. 귀하의 요구 사항을 충족시키는 직접적인 접근 방법이없는 것 같습니다. 따라서 "개별화 된"솔루션도 솔루션입니다. 왜 이런 일을하고 싶은지 묻고 싶지 않습니다. 당신의 이유가 있다고 확신합니다. :-)
Jens Bradler

@JensBradler 당신은 나보다 더 전문가처럼 보입니다. 내 솔루션에 대해 어떻게 생각하는지 말해 주시겠습니까? 나는 내 ISP에 두 계정에서 내 웹 사이트의 두 복사본을 실행하기 때문에 동일한 작업을 수행 할 : site1.myisp.com그리고 site2.myisp.com그들은 그들의 각각의 이름에 반응한다. 이제 도메인 이름을 소유하고 있으며 ISP 웹 사이트를 사용하여 서버의로드 균형을 조정하고 싶습니다. 그 좋은 이유가 아닌가? 대단히 감사합니다;)
ncenerar

1
@ncenerar 그렇게 할 수 있지만로드 밸런서라는 단일 실패 지점으로 연결됩니다. 중복이 아닌로드 균형 조정을위한 것이라면 DNS 장애 조치와 함께 DNS 기반로드 균형 조정을 사용할 수도 있습니다.
Jens Bradler

2
이 답변 은 공식 블로그의 조언을 반영합니다 .
Bernard Rosset

28

나는 같은 문제가 있었고 마침내 두 가지 수준의 프록시를 사용하여 문제를 해결했습니다. 다음은 상황에 맞는 방법입니다.

server {
  listen      8001 default_server;
  server_name web1.example.com;
  location / {
    proxy_pass       http://web1.local:80;
    proxy_set_header Host web1.local:80;
  }
}

server {
  listen      8002 default_server;
  server_name web2.example.com;
  location / {
    proxy_pass       http://web2.local:80;
    proxy_set_header Host web2.local:80;
  }
}

server {
  listen      8003 default_server;
  server_name web3.example.com;
  location / {
    proxy_pass       http://web3.local:80;
    proxy_set_header Host web3.local:80;
  }
}

upstream main {
  server 127.0.0.1:8001;
  server 127.0.0.1:8002;
  server 127.0.0.1:8003;
}

server {
  listen      80;
  server_name example.com;
  location / {
    proxy_pass http://main;
  }
}

보다시피 트릭은 각 서버에 적합한 호스트를 다시 작성하여 서버를 프록시 할 특정 포트에 응답하는 로컬 서버를 만드는 것입니다. 그런 다음 업스트림에서이 로컬 서버를 사용하고 실제 프록시에서 해당 업스트림을 사용할 수 있습니다.


원래 Lua 접근 방식을 사용했지만 이제는 표준 구성으로 원하는 것을 수행 할 수있는 HAProxy로 완전히 전환되었습니다.
pavel_karoukin

3

따라서 nginx에 대한 모든 문서를 읽음으로써 (실제로 업스트림 모듈 = ()에 대한 코드를 파싱 할 수 없었습니다.이 나쁜 해결책을 찾았습니다. 불행히도이 솔루션은 실패한 호스트를 추적하지는 않지만 무작위로 하나를 선택하고 요청을 리디렉션합니다. 모든 백엔드가 실행되도록 모니터링을 설정해야합니다.

server {
        listen 80;
        server_name example.com;
        resolver 127.0.0.1;

        location / {
                set $upstream "";
                rewrite_by_lua '
                        local upstreams = {
                                "http://web1.dokku.localdomain",
                                "http://web2.dokku.localdomain",
                                "http://web3.dokku.localdomain",
                                "http://web4.dokku.localdomain"
                        }
                        ngx.var.upstream = upstreams[ math.random( #upstreams ) ] 
                ';
                proxy_pass $upstream;
        }
}

2

업스트림 가산기를 이와 같은 별도의 헤더로 전달합니다.

server {
  listen 80;
  server_name example.com;
  location / {
    proxy_pass       http://main;
    proxy_set_header Host            $host;
    proxy_set_header X-Forwarded-For $remote_addr;
    add_header       X-Upstream      $upstream_addr;
  }
}

시도하면 어떻게 되나요?

server {
  listen 80;
  server_name example.com;
  location / {
    proxy_pass       http://main;
    proxy_set_header Host            $upstream_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    add_header       X-Host          $host;
  }
}

2

목표는 논리적으로 보이지만 nginx는 Host : 헤더를 업스트림과 일치하도록 변경하지 않습니다 . 대신, DNS에서 upstream도메인 이름 CNAME을 IP 주소로 가져 오는 방법으로 취급 합니다 .

요청 헤더 (및 본문)는 업스트림이 선택되기 전에 고정됩니다. 특정 업스트림이 응답하지 않는 것으로 확인되었지만 요청이 변경되지 않는 경우 요청 중반에 업스트림이 변경 될 수 있습니다.


0

흠. 비슷한 설정을 가지고 있는데 간단하게 수행했습니다.

location / {
    ... 
    proxy_set_header X-Forwarded-Host $http_host;
    proxy_pass ...;
}

의 사용 $http_host(수신 요청의 HTTP 호스트 헤더) 여기가 아닌 $host(서버 호스트 이름 구성) 클라이언트에 의해 전달 된 동일한 호스트 헤더 내 테스트에서, 상류까지 전달됩니다.

https://stackoverflow.com/questions/14352690/change-host-header-in-nginx-reverse-proxy참조하십시오 .


0

다른 사람들이 이미 $ upstream과 같은 스크립트 변수를 사용하여 게시 했으므로 원하는대로 설정할 수 있으며 추가 헤더 해킹없이 문제를 해결할 것입니다.

값이 조건부 (이름에 $가 없음)가 아닌 경우 프록시 패스 핸들러 위협 스크립트 변수는 구성 단계에서 업스트림으로 백업되어 나중에 사용됩니다.

이 문제를 생략하고 (무료 버전) 업스트림의 장점을 최대한 활용하는 간단한 방법은 다음과 같습니다 Split_Clients.

split_clients $request_uri $my_upstream {
              33%          server1.domainX.com;
              33%          server2.domainX.com;
# Always use DOT at end entry if you wonder why, read the SC code.
              *            server3.domainX.com;  
}
location / {
    ... 
    proxy_pass http://$my_upstream;
}

위의 예는 업스트림과 거의 동일하게 보입니다. 매핑을 수행하는 다른 모듈 (예 : chash_map_module )이 있지만 트리 외부에 있으므로 자체적으로 빌드해야합니다. 일부 사용 사례에서는 불가능합니다 /

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.