여러 도메인과 각각의 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;
}
}
구성을 추가로 재정의할 수 있도록 이 정보가 도움이 되는지 알려주시기 바랍니다.