Çerez kullanarak Nginx proxy hedefini denetleme?


11

Bunun yerine Nginx kullanmak için ilginç bir Apache mod_rewrite kurulumu kullanarak ters proxy dönüştürmek çalışıyorum (dış endişeler nedeniyle biz Apache Nginx için hareket ediyor ve çoğu her şey bu bölüm dışında iyi çalışıyor).

Orijinal kurulumum bir HTTP çerezi okumak (bazı uygulamalar tarafından ayarlanmış) ve değerine bağlı olarak, ters proxy'yi farklı arka uçlara yönlendirmekti. Bunun gibi bir şey gitti:

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 kullanarak aynı elde etmeye çalışıyorum ve benim ilk yapılandırma böyle bir şey ("proxy_override" çerez adıdır):

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;
}

Ama olmadı. Nginx dayalı bir şeye yönlendirmek için birincil proxy yazarak çerezimi okuyabilir olup olmadığını görmek için çalıştım ${cookie_proxy_override}ve içeriği iyi okuduğunu görebilirsiniz, ancak ifs her zaman başarısız gibi görünüyor.

Rikih'in cevabına göre bir sonraki denemem şuydu:

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;
}

Ve şimdi ifbloğun etkinleştirildiğini görebiliyorum, ancak isteği proxy yapmak yerine (yapacağını düşündüğüm gibi) belirtilen URL'ye 302 yönlendirmesi döndürüyor - yapmaya çalıştığım şey bu değil: Sunucuya ihtiyacım var isteği arka uçlara şeffaf bir şekilde aktarmak ve yanıtı orijinal istemciye iletmek için.

Neyi yanlış yapıyorum?

Yanıtlar:


16

Bu cevaba benzer . Nginx'in bu tür sorunlara karşı deyimsel yaklaşımı geçer map.

Temel olarak, bir tanımlamak mapiçinde httpbölüm

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

Sonra sadece kullanım $my_upstreamiçinde locationbölüm (ler):

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

Nginx, harita değişkenlerini tembel olarak, yalnızca bir kez (istek başına) ve kullandığınızda değerlendirir.


3
Teşekkürler, bu benimkinden daha iyi bir yaklaşım, özellikle de adlandırılan çerez değişkenini doğrudan kullanabileceğim için (neden giremediğimden emin değilim if) ve uyguladım. Bir sorun olsa - Nginx (en azından benim sürüm: 1.0.0) numaralı yakalama sevmez map, bu yüzden ~^(?P<name>[\w-]+) $name;bunun yerine kullanmak zorunda kaldı . Cevabınızı buna göre düzenledim.
Guss

3

Sonunda benim çözüm aşağı kaynar:

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
    }
}

Test, serverher istek için kapsamda yapılır (gerçek yönlendirme çözülmeden önce) ve sadece bir değişken ayarlamak için kullanılır - bu görünüşe göre Nginx "yeniden yazma" modülünün desteklenen bir kullanımıdır. Ayrıca, $http_cookie@Rikih'in önerdiği gibi tüm testleri test eder , ancak insanların bana attığı rastgele şeylerle eşleşmediğimden emin olmak için çerezin adını içerir.

Sonra locationyeniden yönlendirme yapmak istediğiniz kapsamda, varsayılan yukarı akış yapılandırmasını içeren veya çerez tarafından üzerine yazılan değişken adını kullanın.


0

$ http_cookie denediniz mi? http://wiki.nginx.org/HttpRewriteModule

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


Bu gerçekten test için çalıştı, ancak neden belirli çerez adına karşı test edemediğimden emin değilim. Ne gibi rewritedeğildi aslında bir proxy yeniden yazma yapmak değil, bunun yerine istemciye bir yönlendirme döndürür ve ifblokta proxy_pass kullanamazsınız . Soruyu buna göre güncelledim.
Guss

0

Ben udid dayalı istek başlık tespit etmek için kullandığım örnek var ve çalışıyor, bazı fikir alacak olabilir.

   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;
    }

Hangi Nginx sürümünü kullanıyorsunuz? 1.0 kullanıyorum ve burada belirttiğiniz gibi proxy_pass kullandığımda, bu hata iletisini alıyorum: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 kullanıyorum
chocripple

belki bir göz atmak
chocripple

Forumdaki çözüm, başka bir sunucuya proxy gönderirken istek URI'sini değiştirmemek, ancak tam olarak yapmam gereken şey - orijinal URL'nin içeriğinden farklı bir uygulamayı hedeflemek için istek URI'sını yeniden yazın. Ayrıca, örneğiniz proxy_passkomutta istek URI'sini de kullanıyor gibi görünüyor , bu yüzden yukarıdaki forum tartışması verildiğinde sizin için nasıl çalışabileceğinden emin değilim.
Guss
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.