Vraag Zorg dat nginx de hostnaam van de upstream passeert bij reverseproxying


Ik voer verschillende dockercontainers met hostnamen:

web1.local web2.local web3.local

Routing naar deze gedaan op basis van hostnaam door nginx. Ik heb een proxy voor deze opstelling (op een andere machine verbonden met internet) waar ik stroomopwaarts definieer als:

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

En daadwerkelijke beschrijving van de virtuele host:

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

Omdat containers hostnaam 'main' ontvangen in plaats van 'web1.local', reageren ze niet correct op het verzoek.

Vraag: hoe kan ik nginx vertellen dat de naam van de upstream-server moet worden doorgegeven in plaats van de naam van de stroomopwaartse groep servers in Host: header wanneer een verzoek om proxy wordt ingediend?


71
2018-05-23 20:46


oorsprong


Ik denk niet dat je het kan. Waarom stel je niet je backend-servers in op resp. Main of example.com? Het is niet zo dat de backend niet weet wie het is. Het omgekeerde is gemakkelijk mogelijk: proxy_set_header Host $ host; zal elke Host-variabele die terugkomt van stroomopwaarts vervangen door de hostnaam van het oorspronkelijke verzoek. - Andrew Domaszek
Het juiste ding om te doen is om de applicatie te repareren. - Michael Hampton♦


antwoorden:


Eigenlijk kunt u dat doen via proxy_set_header.

Zie hier voor meer informatie: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header of bekijk hier een voorbeeld use-case: https://stackoverflow.com/questions/12847771/configure-nginx-with-proxy-pass

Ik heb de dynamische benadering opgenomen in uw hierboven geplaatste configuratie:

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 is een voorbeeld met een statische hostnaam:

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; lijkt beter - sivann
@pavel: snap het. Eigenlijk heb ik ook wat onderzoek en enkele tests gedaan. Het lijkt erop dat er geen directe benadering is om aan uw vereiste te voldoen. Dus zelfs een "verbasterde" oplossing is een oplossing. Ik vraag je niet graag waarom je dit zou willen doen. Ik ben er vrij zeker van dat je je redenen hebt. :-) - Jens Bradler
@ JensBradler Je lijkt meer expert dan ik, kun je me vertellen wat je van mijn oplossing vindt? Ik wil hetzelfde doen omdat ik twee exemplaren van mijn website vanaf twee accounts op mijn internetprovider gebruik: site1.myisp.com en site2.myisp.com en ze reageren alleen op hun respectievelijke naam. Ik bezit nu mijn domeinnaam en ik wil mijn ISP-website gebruiken om de balans van mijn servers te laden. Is dat niet een goede reden? Dank u zeer ;) - ncenerar
@ncenerar U kunt dat doen maar dit brengt u naar een enkel punt van falen: de load-balancer. Als dit voor taakverdeling is (geen redundantie), kunt u ook gebruik maken van op DNS gebaseerde taakverdeling in combinatie met DNS-failover. - Jens Bradler
Dit antwoord weerspiegelt advies van de officiële blog. - Bernard Rosset


Ik had hetzelfde probleem en ik loste het uiteindelijk op met behulp van twee niveaus van proxy. Hier is hoe je zou kunnen doen voor uw situatie (denk ik):

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

Zoals u ziet, is het de kunst om een ​​lokale server te maken die reageert op een bepaalde poort die de server proxy maakt door voor elke server de juiste host te herschrijven. Vervolgens kunt u deze lokale servers in uw upstream gebruiken en die stroomopwaarts gebruiken in de echte proxy.


21
2017-08-20 15:20



Ik heb oorspronkelijk de Lua-methode gebruikt, maar ben nu volledig overgestapt op HAProxy, waarmee ik precies kon doen wat ik wilde met standaardconfiguratie. - pavel_karoukin


Dus van het lezen van alle documentatie voor nginx (ik kon code niet echt analyseren voor upstream module = () Ik kwam met deze verbasterde oplossing. Helaas houdt deze oplossing niet de mislukte hosts bij, maar selecteer gewoon willekeurige een en verzoek om omleiden naar deze. Dus ik moet een soort van controle instellen om ervoor te zorgen dat alle backends actief zijn.

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





We geven de upstream-addr door als een aparte header zoals deze

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

Wat als je het probeerde?

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





Hoewel het doel logisch lijkt, nginx zal de Host: header niet wijzigen om de upstream te matchen. In plaats daarvan behandelt het upstream domeinnamen als een CNAME in DNS - als een manier om naar een IP-adres te gaan.

De verzoekheaders (en hoofdtekst) worden gerepareerd voordat de upstream is geselecteerd. De upstream kan het middenverzoek wijzigen als blijkt dat een bepaalde upstream niet-responsief is, maar het verzoek verandert niet.


1
2018-06-23 01:06