Wie verwende ich Nginx als Reverse-Proxy mit mehreren IPs und SSL?

Wie verwende ich Nginx als Reverse-Proxy mit mehreren IPs und SSL?

Ich möchte einen Nginx-Reverseproxy mit mehreren Domänen und einer IP für jede von ihnen einrichten, um unterschiedliche SSL-Zertifikate zu verwenden. Als Betriebssystem verwende ich Ubuntu, das auf einer KVM/Qemu-VM installiert ist.

So wie ich Nginx verstehe, sollte es in der Lage sein, eine Domäne (und die dazugehörigen Subdomänen) über eine IP zu bedienen. Aber ich bekomme es nicht zum Laufen ...

Das ist meine Nginx-Konfiguration:

/etc/nginx/sites-enabled/meine_erste_Domäne

server {
  listen x.x.x.84:80;                                   # this is a public ip
  server_name firstdomain.com;

  access_log /var/log/nginx/access.log proxy;     # I made my own logformat
  error_log  /var/log/nginx/error.log;

  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header Client-IP $remote_addr;
  proxy_set_header X-Host $host;
  proxy_set_header Host $host;
  proxy_set_header X-Forwarded-For $remote_addr;

  location / {
    rewrite ^/(.*) https://firstdomain/$1;  # redirect to https
  }
}

server {
  listen x.x.x.84:443 ssl;                            # this is a public ip
  server_name firstdomain.com;

  ssl_certificate      /etc/nginx/ssl/combined.firstdomain.com.crt;
  ssl_certificate_key  /etc/nginx/ssl/wildcard.firstdomain.com.key;

  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header Client-IP $remote_addr;
  proxy_set_header X-Host $host;
  proxy_set_header Host $host;
  proxy_set_header X-Forwarded-For $remote_addr;

  access_log /var/log/nginx/access.log proxy;
  error_log  /var/log/nginx/error.log;

  location / {
    proxy_pass http://x.x.x.85;                       # this is a public ip, too 
    proxy_redirect off;
  }
}

Diese Konfiguration ist meiner Meinung nach sehr einfach. Jede Anfrage auf Port 80 sollte auf Port 443 umgeleitet werden. Die Konfiguration für eine zweite Domäne ist sehr ähnlich.

/etc/nginx/sites-enabled/eine andere Domäne

server {
  listen x.x.x.87:80;                                   # this is a public ip
  server_name anotherdomain.org;

  access_log /var/log/nginx/access.log proxy;     # I made my own logformat
  error_log  /var/log/nginx/error.log;

  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header Client-IP $remote_addr;
  proxy_set_header X-Host $host;
  proxy_set_header Host $host;
  proxy_set_header X-Forwarded-For $remote_addr;

  location / { 
    rewrite ^/(.*) https://anotherdomain.org/$1;  # redirect to https
  }   
}

server {
  listen x.x.x.87:443 ssl;                            # this is a public ip
  server_name anotherdomain.org;

  ssl_certificate      /etc/nginx/ssl/combined.anotherdomain.org.crt;
  ssl_certificate_key  /etc/nginx/ssl/wildcard.anotherdomain.org.key;

  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header Client-IP $remote_addr;
  proxy_set_header X-Host $host;
  proxy_set_header Host $host;
  proxy_set_header X-Forwarded-For $remote_addr;

  access_log /var/log/nginx/access.log proxy;
  error_log  /var/log/nginx/error.log;

  location / {
    proxy_pass http://x.x.x.89;                       # this is a public ip, too
    proxy_redirect off;
  }
}

Mein netstat -tulpen-Snippet:

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       User       Inode       PID/Program name
...
tcp        0      0 x.x.x.84:80           0.0.0.0:*               LISTEN      0          8724        1187/nginx      
tcp        0      0 x.x.x.87:80           0.0.0.0:*               LISTEN      0          8723        1187/nginx      
tcp        0      0 x.x.x.84:443          0.0.0.0:*               LISTEN      0          8726        1187/nginx      
tcp        0      0 x.x.x.87:443          0.0.0.0:*               LISTEN      0          8725        1187/nginx      
...

Eigentlich dachte ich, das müsste reichen, um mehrere Domains mit SSL auf dem gleichen Server zu hosten. Aber nginx stellt bei jeder Anfrage das gleiche Zertifikat bereit. Das Ergebnis ist ein SSL-Fehler.

Und es gibt noch ein weiteres unerwartetes Verhalten. Während des Debuggens habe ich versucht, die Websites mit Telnet als Client zu erreichen. Diese Anfrage:

user@host:~$ telnet x.x.x.84 80
Trying x.x.x.84...
Connected to x.x.x.84.
Escape character is '^]'.
GET / HTTP/1.1
Host: firstdomain.com

gehört zu dieser Antwort:

HTTP/1.1 302 Moved Temporarily
...
Location: https://firstdomain.com/

Mmh, das ist in Ordnung ... aber diese Anfrage [dieselbe Domäne (siehe 'Host:'-Header), aber die IP ist nicht richtig]:

user@host:~$ telnet x.x.x.87 80
Trying x.x.x.87...
Connected to x.x.x.87.
Escape character is '^]'.
GET / HTTP/1.1
Host: firstdomain.com

... führt zur Auslieferung der von mir angefragten Website. Ich habe also die Website über den Proxy erhalten, obwohl ich die Anfrage an die falsche IP und ohne SSL gesendet habe. Das ist genau das, was ich verhindern wollte!

Vielen Dank für eure Ideen!

Antwort1

Ihre erste Konfiguration sollte so aussehen.

server {
  listen x.x.x.84:80;
  server_name firstdomain.com;

  access_log /var/log/nginx/access.log proxy;
  error_log  /var/log/nginx/error.log;

  return https://$server_name$request_uri;
}

server {
  listen x.x.x.84:443 ssl;
  server_name firstdomain.com;
  root ????;

  ssl_certificate      /etc/nginx/ssl/combined.firstdomain.com.crt;
  ssl_certificate_key  /etc/nginx/ssl/wildcard.firstdomain.com.key;

  access_log /var/log/nginx/access.log proxy;
  error_log  /var/log/nginx/error.log;

  location / {
    # Do not proxy everything to the backend, deliver static files
    # right away!
    try_files $uri @proxy;
  }

  location @proxy {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Client-IP $remote_addr;
    proxy_set_header X-Host $host;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_redirect off;
    # The backend MUST be SSL enabled as well!
    proxy_pass https://x.x.x.85;
  }
}

Ihre zweite Konfiguration sollte so aussehen.

server {
  listen x.x.x.87:80;
  server_name anotherdomain.org;

  access_log /var/log/nginx/access.log proxy;
  error_log  /var/log/nginx/error.log;

  return https://$server_name$request_uri;
}

server {
  listen x.x.x.87:443 ssl;
  server_name anotherdomain.org;
  root ????;

  ssl_certificate      /etc/nginx/ssl/combined.anotherdomain.org.crt;
  ssl_certificate_key  /etc/nginx/ssl/wildcard.anotherdomain.org.key;

  access_log /var/log/nginx/access.log proxy;
  error_log  /var/log/nginx/error.log;

  location / {
    # Do not proxy everything to the backend, deliver static files
    # right away!
    try_files $uri @proxy;
  }

  location @proxy {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Client-IP $remote_addr;
    proxy_set_header X-Host $host;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_redirect off;
    # The backend MUST be SSL enabled as well!
    proxy_pass https://x.x.x.85;
  }
}

Bitte lassen Sie mich wissen, ob dies hilft, damit wir die Konfiguration weiter neu definieren können.

verwandte Informationen