Frage Machen Sie Nginx, um beim Rückwärtsproxy den Hostnamen des Upstream zu übergeben


Ich führe mehrere Docker-Container mit Hostnamen aus:

web1.local web2.local web3.local

Routing zu diesen erfolgt basierend auf Hostname von Nginx. Ich habe einen Proxy vor diesem Setup (auf einem anderen Computer, der mit dem Internet verbunden ist), wo ich upstream definiere als:

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

Und tatsächliche virtuelle Host-Beschreibung:

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

Da Container den Hostnamen "main" anstelle von "web1.local" erhalten, reagieren sie nicht ordnungsgemäß auf die Anfrage.

Frage: Wie kann ich nginx mitteilen, den Namen des Upstream-Servers anstelle des Namens der Upstream-Gruppe von Servern in Host: header zu übergeben, wenn eine Proxy-Anfrage erfolgt?


71
2018-05-23 20:46


Ursprung


Ich glaube nicht, dass du es kannst. Warum sollten Sie Ihre Backend-Server nicht auf main oder example.com antworten lassen? Es ist nicht so, als wüsste das Backend nicht wer es ist. Das Umgekehrte ist ohne weiteres möglich: proxy_set_header Host $ host; ersetzt jede Host-Variable, die vom Upstream zurückkommt, mit dem Hostnamen von der ursprünglichen Anfrage. - Andrew Domaszek
Das Richtige ist, die Anwendung zu reparieren. - Michael Hampton♦


Antworten:


Eigentlich können Sie das über proxy_set_header tun.

Für weitere Details schaue hier: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header oder sehen Sie sich hier einen Anwendungsbeispiel an: https://stackoverflow.com/questions/12847771/configure-nginx-with-proxypass

Ich habe den dynamischen Ansatz in Ihre oben genannte Konfiguration aufgenommen:

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

Hier ist ein Beispiel mit einem statischen Hostnamen:

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

88
2018-05-24 08:10



proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for; scheint besser zu sein - sivann
@ Pavel: hab es verstanden. Eigentlich habe ich auch ein paar Recherchen und Tests gemacht. Es scheint, dass es keinen direkten Ansatz gibt, um Ihre Anforderung zu erfüllen. Also ist auch eine "Bastard" -Lösung eine Lösung. Ich frage nicht gerne, warum du das machen willst. Ich bin mir ziemlich sicher, dass Sie Ihre Gründe haben. :-) - Jens Bradler
@JensBradler Sie scheinen mehr Experten als ich, also können Sie mir sagen, was Sie über meine Lösung denken? Ich möchte dasselbe tun, weil ich zwei Kopien meiner Website von zwei Konten auf meinem ISP aus führe: site1.myisp.com und site2.myisp.com und sie antworten nur auf ihren jeweiligen Namen. Ich besitze jetzt meinen Domain-Namen und möchte meine ISP-Website nutzen, um meine Server zu balancieren. Ist das nicht ein guter Grund? Vielen Dank ;) - ncenerar
@cencerar Sie können das tun, aber dies bringt Sie zu einem einzigen Fehlerpunkt: dem Load Balancer. Wenn dies für den Lastausgleich (keine Redundanz) gilt, können Sie auch DNS-basierten Lastenausgleich in Kombination mit DNS-Failover verwenden. - Jens Bradler
Diese Antwort spiegelt wider Ratschlag des offiziellen Blogs. - Bernard Rosset


Ich hatte das gleiche Problem und löste es schließlich mit zwei Proxy-Ebenen. Hier ist, wie Sie für Ihre Situation tun können (denke ich):

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

Wie Sie sehen können, besteht der Trick darin, einen lokalen Server zu erstellen, der auf einen bestimmten Port reagiert, der den Server proxyt, indem er den richtigen Host für jeden Server neu schreibt. Dann können Sie diese lokalen Server in Ihrem Upstream verwenden und schließlich diesen Upstream im echten Proxy verwenden.


21
2017-08-20 15:20



Ich habe ursprünglich den Lua-Ansatz verwendet, bin jetzt aber komplett auf HAProxy umgestiegen, was genau das ermöglicht, was ich mit der Standardkonfiguration wollte. - pavel_karoukin


Nachdem ich die gesamte Dokumentation für nginx gelesen hatte (ich konnte den Code für das Upstream-Modul = () nicht richtig parsen, kam ich zu dieser Bastardlösung. Leider verfolgt diese Lösung nicht die ausgefallenen Hosts, sondern wählt einfach eine zufällige aus und leitet die Anfrage dorthin um. Also muss ich eine Art Überwachung einrichten, um sicherzustellen, dass alle Backends laufen.

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
2018-05-24 13:39





Wir übergeben die Upstream-Adr als separaten Header wie folgt

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

Was, wenn du es versucht hast?

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
2018-04-26 17:49





Während das Ziel logisch erscheint, Nginx wird den Host: Header nicht ändern, um dem Upstream zu entsprechen. Stattdessen behandelt es upstream Domain-Namen wie a CNAME in DNS - als eine Möglichkeit, zu einer IP-Adresse zu gelangen.

Die Anforderungsheader (und der Hauptteil) sind festgelegt, bevor der Upstream ausgewählt wird. Der Upstream kann sich mitten in der Anfrage ändern, wenn festgestellt wird, dass ein bestimmter Upstream nicht reagiert, sich die Anfrage jedoch nicht ändert.


1
2018-06-23 01:06