Namensbasierte virtuelle Nginx-Hosts unter IPv6

44

Ich habe einen Nginx-Server, auf dem fast ein halbes Dutzend verschiedene Websites betrieben werden. Es läuft auf einem Linode, der gerade native IPv6-Unterstützung hat (Dallas Data Center), und ich versuche, die meisten meiner Sites für den Dual-Stack-Betrieb zu konfigurieren. Ich habe den ersten mit einer IPv6-Subdomain wie der folgenden gestartet:

server {
    listen [::]:80 ipv6only=on;
    listen 80;

    server_name example.com ipv6.example.com;

    root /var/www/example.com/htdocs;

    #More stuff, including PHP, WordPress
}

Dies funktioniert hervorragend - example.com ist (vorerst) nur IPv4-fähig und ipv6.example.com ist nur IPv6-fähig (hauptsächlich zu Testzwecken). Ich kann ping6 ipv6.example.com, und auch wget ipv6.example.comohne ins Schwitzen zu geraten - so viel war angenehm schmerzfrei (nachdem ich das "gotcha" so gefunden hatte, wie Nginx virtuelle Hosts bindet, was das ipv6only=onArgument und die doppelten listenAnweisungen erforderlich macht ).

Ich versuche jetzt jedoch, dies zu erweitern, um meine anderen Domänen zu unterstützen, beginnend mit static.example.com. Wenn ich jedoch den gleichen Ansatz wie oben verwende (die dualen listenAnweisungen, einschließlich des ipv6only=onArguments), wird beim Neustart von nginx der folgende Fehler angezeigt:

* Starting Nginx Server...
nginx: [emerg] a duplicate listen options for [::]:80 in /etc/nginx/sites-enabled/example.com.conf:3

Es scheint, dass die Bindungsmethode von Nginx für IPv6 möglicherweise keine namensbasierten virtuellen Hosts zulässt. Muss ich zusätzliche IPv6-Adressen von meinem Host beziehen (kein Problem) und IP-basiertes virtuelles Hosting auf IPv6 mit benanntem virtuellem Hosting über IPv4 verwenden? Oder fehlt mir eine Lösung, mit der meine Konfigurationen auf beiden Stacks konsistent bleiben?

Ich hatte gehofft, meine Site rechtzeitig zum Welt-IPv6-Tag vollständig auf dem IPv6-Stack zu haben , aber wenn ich dies nicht schnell klären kann, bin ich möglicherweise nicht bereit. Vom praktischen Standpunkt aus keine große Sache - keine meiner Websites kann sich als "große Organisation" qualifizieren - aber helfen Sie mir, mein Geek-Credo zu bewahren!

Bearbeitet, um hinzuzufügen:

Dank der Antwort von @kolbyjack habe ich jetzt einen voll funktionsfähigen Dual-Stack-Webserver. Aus Gründen der Klarheit bearbeite ich die Lösung, die er mir gegeben hat, damit jeder klar sehen kann, wie die Antwort lautet.

Mein voreingestellter catchall vhost hat folgende listenAnweisungen:

listen 80 default_server;
listen 8080 default_server;
listen [::]:80 default_server ipv6only=on;
listen [::]:8080 default_server ipv6only=on;

Ich weiß nicht, ob die Reihenfolge wichtig ist, aber da ist es. Dann hat jeder zusätzliche vhost die folgenden listenAnweisungen:

listen 80;
listen [::]:80;

(Oder 8080 für denjenigen, der stattdessen diesen Port abhört.) Der wichtige Teil hier scheint das völlige Fehlen zusätzlicher Argumente für alle listenAnweisungen außer den vhost-Standardanweisungen zu sein - dh keine Wiederholung von ipv6only=on.

Nochmals vielen Dank an @kolbyjack für die Lösung hier!

Kromey
quelle
Mit Nginx 1.2.1 musste ich nicht angeben ipv6only=on. Alles andere blieb jedoch gleich, danke dafür!
BeepDog

Antworten:

46

Sie benötigen nur Listen-Optionen für eine Deklaration für einen Socket. Im Allgemeinen würden Sie sie in die Deklaration einfügen, die auch das default_server-Flag enthält, aber für einige Optionen können Sie sie meiner Meinung nach einfach für eine beliebige listen-Direktive festlegen. Entfernen Sie einfach ipv6only = on von allen Listenern mit einer Ausnahme.

kolbyjack
quelle
2
Warten Sie, ich bin verwirrt. Ich dachte, dass mindestens eine Listen-Direktive pro Server-Deklaration erforderlich ist - ansonsten wie würde nginx wissen, mit welchem ​​Server-Block auf welchen Port (s) geantwortet werden soll? Ich habe es oben nicht erwähnt, weil ich es nicht für relevant hielt, aber ich habe einen Server auf 8080, den Rest auf 80, und ich beabsichtige, 443 für ein Paar anzubieten, sobald ich es ausgebügelt habe und dann besorge ich mir ein SSL Zertifikat.
Kromey
In der Dokumentation sieht es so aus, als bräuchten die Sites auf Port 80 überhaupt keine Listen-Direktive, nur eine mit dem default_server-Flag auf meinem catchall-vhost. Dies schlägt jedoch für meinen Server auf 8080 immer noch fehl, für den ich auch einen Standard-Catchall verwende (der Catchall wird geschrieben, um einfach alle Anforderungen für einen Hostnamen zu ignorieren, den ich nicht explizit in einem anderen vhost konfiguriert habe).
Kromey
1
Ich sage nicht, dass Sie alle Ihre Listen-Direktiven entfernen sollen. Entfernen Sie einfach das ipv6only = on-Flag von allen außer einem. Ohne eine Listen-Direktive auf jedem Server hören sie standardmäßig nur 80; die ipv6 enthalten kann oder nicht. Ich denke, der richtige Ansatz ist, beide Listen-Direktiven in jeden Server einzuschließen, aber nur ipv6only = auf einem der Server zu setzen.
Kolbyjack
4
Ah, ich verstehe jetzt, was du meinst. Ich habe Ihren Beitrag ursprünglich falsch gelesen. Dies hat bei mir funktioniert: ipv6only=onWird nur (für jeden Port, den ich abhöre) in meinem Standard-vhost (neben default_server) aufgeführt; Jeder vhost spezifiziert dann einfach listen 80;und listen [::]:80(überhaupt keine zusätzlichen Parameter), um sowohl auf IPv4 als auch auf IPv6 zu funktionieren. Jetzt muss ich nur noch die AAAA-Datensätze für meine Dual-Stack-Domains hinzufügen. Vielen Dank!
Kromey
1
funktionierte auch für mich, aber ich verstehe nicht, warum ich nginx auf ipv4 für mehrere Blöcke hören kann, aber nicht ipv6. . können Sie erklären ?
Adeerlike