여러 IP 및 SSL을 사용하여 nginx를 역방향 프록시로 사용하는 방법은 무엇입니까?

여러 IP 및 SSL을 사용하여 nginx를 역방향 프록시로 사용하는 방법은 무엇입니까?

여러 도메인과 각각의 IP가 서로 다른 SSL 인증서를 사용하도록 nginx 리버스 프록시를 설정하고 싶습니다. KVM/Qemu VM에 설치된 OS로 Ubuntu를 실행합니다.

내가 이해하는 nginx는 하나의 IP를 통해 하나의 도메인(및 이에 속한 하위 도메인)을 제공할 수 있어야 합니다. 그런데 실행이 안되네요...

내 nginx 구성은 다음과 같습니다.

/etc/nginx/sites-enabled/my_first_domain

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

내 생각에 이 구성은 매우 단순하다. 포트 80의 모든 요청은 포트 443으로 리디렉션되어야 합니다. 두 번째 도메인의 구성은 매우 유사합니다.

/etc/nginx/sites-enabled/다른도메인

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

내 netstat -tulpen 조각:

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

실제로 나는 동일한 서버에서 SSL을 사용하여 여러 도메인을 호스팅하기에 충분하다고 생각했습니다. 그러나 nginx는 각 요청마다 동일한 인증서를 제공합니다. 결과는 SSL 오류입니다.

그리고 또 다른 예상치 못한 행동이 있습니다. 디버깅하는 동안 텔넷을 클라이언트로 사용하여 웹사이트를 얻으려고 했습니다. 이 요청:

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

이 응답에 속합니다:

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

음, 괜찮습니다... 그런데 이 요청은 [동일한 도메인('호스트:'-헤더 참조)이지만 현재 IP가 아닙니다]:

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

... 내가 요청하는 웹사이트가 제공됩니다. 그래서 SSL 없이 잘못된 IP로 요청을 보냈음에도 불구하고 프록시를 통해 웹사이트를 얻었습니다. 내가 막고 싶었던 건 바로 그것이다!

귀하의 아이디어에 감사드립니다!

답변1

첫 번째 구성은 다음과 같습니다.

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

두 번째 구성은 다음과 같습니다.

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

구성을 추가로 재정의할 수 있도록 이 정보가 도움이 되는지 알려주시기 바랍니다.

관련 정보