쿠키를 사용하여 Nginx 프록시 대상을 제어합니까?


11

Nginx를 대신 사용하기 위해 흥미로운 Apache mod_rewrite 설정을 사용하여 리버스 프록시를 변환하려고합니다 (외부 우려 때문에 Apache에서 Nginx로 이동하고 있으며이 부분을 제외한 모든 것이 잘 작동합니다).

내 원래 설정은 HTTP 쿠키 (일부 응용 프로그램에서 설정)를 읽고 그 값에 따라 역방향 프록시를 다른 백엔드로 보냅니다. 그것은 다음과 같이 갔다 :

RewriteCond %{HTTP_COOKIE}  proxy-target-A
RewriteRule ^/original-request/ http://backend-a/some-application [P,QSA]

RewriteCond %{HTTP_COOKIE}  proxy-target-B
RewriteRule ^/original-request http://backend-b/another-application [P,QSA]

RewriteRule ^/original-request http://primary-backend/original-application [P,QSA]

Nginx를 사용하여 동일한 결과를 얻으려고하는데 초기 구성은 다음과 같습니다 (여기서 "proxy_override"는 쿠키의 이름입니다).

location /original-request {
    if ($cookie_proxy_override = "proxy-target-A") {
        rewrite . http://backend-a/some-application;
        break;
    }
    if ($cookie_proxy_override = "proxy-target-B") {
        rewrite . http://backend-b/another-application;
        break;
    }
    proxy_pass http://primary-backend/original-application;
}

그러나 그렇지 않았습니다. Nginx가 기본 프록시를 작성하여 쿠키를 기반으로 무언가를 리디렉션하여 쿠키를 읽을 수 있는지 확인하려고 시도했지만 쿠키가 ${cookie_proxy_override}내용을 잘 읽지 만 if항상 실패하는 것처럼 보입니다.

Rikih의 대답에 따르면 다음 시도는 다음과 같습니다.

location /original-request {
    if ($http_cookie ~ "proxy-target-A") {
        rewrite . http://backend-a/some-application;
        break;
    }
    if ($http_cookie ~ "proxy-target-B") {
        rewrite . http://backend-b/another-application;
        break;
    }
    proxy_pass http://primary-backend/original-application;
}

이제 if블록이 활성화 된 것을 볼 수 있지만 요청을 프록시 처리하는 대신 지정된 URL로 302 리디렉션을 반환합니다. 이것은 내가하려는 것이 아닙니다. 서버가 필요합니다. 백엔드에 요청을 투명하게 릴레이하고 원래 클라이언트에 응답을 파이프합니다.

내가 무엇을 잘못하고 있지?

답변:


16

이 답변과 비슷합니다 . 이런 종류의 문제에 대한 Nginx의 관용적 접근 방식은 map입니다.

기본적으로, 당신은 정의 maphttp섹션

map $cookie_proxy_override $my_upstream {
  default default-server-or-upstream;
  ~^(?P<name>[\w-]+) $name;
}

그런 다음 섹션 $my_upstream에서 간단히 사용 location하십시오.

location /original-request {
  proxy_pass http://$my_upstream$uri;
}

Nginx는 맵 변수를 한 번만 (요청 당) 그리고 사용할 때 게으르게 평가합니다.


3
고마워, 그것은 더 나은 접근 방식입니다. 가장 주목할만한 것은 명명 된 쿠키 변수를 직접 사용할 수 있기 때문에 (내가 왜 그런지 모르겠습니다 if) 구현했습니다. Nginx (적어도 내 버전 : 1.0.0)는의 번호 매기기 캡처를 좋아하지 않으므로 한 가지 문제 map가 있습니다 ~^(?P<name>[\w-]+) $name;. 그에 따라 답변을 편집했습니다.
Guss

3

결국 내 솔루션은 다음과 같이 요약됩니다.

server {
    ...
    set $upstream "default-server-or-upstream";
    if ($http_cookie ~ "proxy_override=([\w-]+)") {
        set $upstream $1;                                   
    }

    location /original-request {
        proxy_pass http://$upstream/original-application
    }
}

테스트는 server각 요청 의 범위 에서 수행되며 (실제 리디렉션이 해결되기 전에) 변수를 설정하는 데 사용됩니다. 이는 분명히 Nginx "다시 쓰기"모듈의 지원되는 사용법입니다. 또한 $http_cookie@Rikih가 제안한 것처럼 전체를 테스트 하지만 쿠키 이름을 포함하여 사람들이 나에게 던질 수있는 임의의 물건과 일치하지 않는지 확인합니다.

그런 다음 location리디렉션을 수행하려는 범위에서 기본 업스트림 구성을 포함하거나 쿠키로 덮어 쓴 변수 이름을 사용합니다.


0

$ http_cookie를 사용해 보셨습니까? http://wiki.nginx.org/HttpRewriteModule

if ($ http_cookie ~ * "proxy-target-A") {foo; }


특정 쿠키 이름으로 테스트 할 수없는 이유는 확실하지 않지만 실제로 테스트를 수행했습니다. 내가 싫어하는 것은 rewrite실제로 프록시 다시 작성을 수행하지 않고 대신 클라이언트로 리디렉션을 반환한다는 것입니다. if블록 에서 proxy_pass를 사용할 수 없습니다 . 이에 따라 질문을 업데이트했습니다.
거스

0

udid를 기반으로 요청 헤더를 감지하는 데 사용하는 샘플이 있으며 작동 중입니다. 어떤 아이디어를 얻을 수 있습니다.

   location / {
      proxy_set_header Host $http_host;
  if ($request_uri ~ ^/(.*)udid=xxxxxxxxxxxxxx(.*)$) {
    proxy_pass   http://1.1.1.1$request_uri;
    break;
  }
  if ($request_uri ~ ^/(.*)udid=yyyyyyyyyyyyyy(.*)$) {
    proxy_pass   http://3.3.3.3$request_uri;
    break;
  }
       proxy_pass http://2.2.2.2$request_uri;
    }

어떤 버전의 Nginx를 사용하고 있습니까? 1.0을 사용하고 있고 여기에 지정한대로 proxy_pass를 사용하면이 오류 메시지가 나타납니다.nginx: [emerg] "proxy_pass" may not have URI part in location given by regular expression, or inside named location, or inside the "if" statement, or inside the "limit_except" block in /etc/nginx/conf.d/proxy.conf:47
Guss

내가 사용의 nginx-0.8.53-1.el5
chocripple

당신이 좀 걸릴 할 수 있습니다 forum.nginx.org/read.php?2,13955,15981
chocripple

포럼의 해결책은 다른 서버로 프록시 할 때 요청 URI를 변경하지 않는 것입니다. 그러나 이것이 정확히해야 할 일입니다. 원래 URL에 포함 된 것과 다른 응용 프로그램을 대상으로 요청 URI를 다시 작성하십시오. 또한 귀하의 예제는 proxy_pass명령 에서 요청 URI도 사용하는 것 같으므로 위의 포럼 토론에서 그것이 어떻게 작동하는지 잘 모르겠습니다.
거스
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.