複数のドメインと、それぞれに異なる SSL 証明書を使用するための IP を持つ nginx リバース プロキシを設定したいと思います。KVM/Qemu VM にインストールされている OS として Ubuntu を実行しています。
私が理解している限りでは、nginx は 1 つの IP 経由で 1 つのドメイン (およびそれに属するサブドメイン) を提供できるはずです。しかし、実行できません...
これが私の 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 にリダイレクトされる必要があります。2 番目のドメインの設定も非常に似ています。
/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 エラーが発生します。
また、予期しない動作がもう 1 つあります。デバッグ中に、クライアントとして Telnet を使用して Web サイトを取得しようとしました。この要求:
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/
うーん、それは問題ありません...しかし、このリクエスト[同じドメイン(「Host:」ヘッダーを参照)ですが、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
... 結果的に、私が求めている Web サイトが配信されます。つまり、間違った IP に SSL なしでリクエストを送信したにもかかわらず、プロキシ経由で Web サイトを取得できたのです。まさにこれを防ぎたかったのです。
ご意見ありがとうございます!
答え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;
}
}
2 番目の構成は次のようになります。
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;
}
}
これが役立つかどうかお知らせください。構成をさらに再定義できます。