我有一个带有 14 个域的 VPS,我设置了 letskencrypt 以自动检索每个域(包括所有子域)的单独证书。所以,我有 14 个证书。显然,将所有域放在一个证书中不是一个选择,因为很快我就会达到 Letsencrypt 每个证书的最大 100 个域/子域。
因此,我很高兴了一个月,直到我发现 nginx 为所有域提供了错误的证书,除了一个域(它自动选择的域 - 或者,我将设置为端口 443 的默认服务器)。经过一番头疼之后,我发现每个 SSL 证书都必须有自己的 IP,而不是共享的 IP。然后我还发现 SNI 可以解决这个问题。
$ nginx -V
TLS SNI support enabled
长话短说,问题是无论我做什么,nginx 都会固执地提供错误的证书:
$ curl --insecure -v https://babaei.net 2>&1 | awk 'BEGIN { cert=0 } /^\* Server certificate:/ { cert=1 } /^\*/ { if (cert) print }'
* Server certificate:
* subject: CN=babaei.net
* start date: Aug 28 13:30:00 2016 GMT
* expire date: Nov 26 13:30:00 2016 GMT
* issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
* SSL certificate verify ok.
* Connection #0 to host babaei.net left intact
$ curl --insecure -v https://learnmyway.net 2>&1 | awk 'BEGIN { cert=0 } /^\* Server certificate:/ { cert=1 } /^\*/ { if (cert) print }'
* Server certificate:
* subject: CN=babaei.net
* start date: Aug 28 13:30:00 2016 GMT
* expire date: Nov 26 13:30:00 2016 GMT
* issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
* SSL certificate verify ok.
* Connection #0 to host learnmyway.net left intact
$ curl --insecure -v https://3rr0r.org 2>&1 | awk 'BEGIN { cert=0 } /^\* Server certificate:/ { cert=1 } /^\*/ { if (cert) print }'
* Server certificate:
* subject: CN=babaei.net
* start date: Aug 28 13:30:00 2016 GMT
* expire date: Nov 26 13:30:00 2016 GMT
* issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
* SSL certificate verify ok.
* Connection #0 to host 3rr0r.org left intact
而且,请不要误会我的意思,实际的证书应该是这样的:
$ openssl x509 -noout -subject -in /path/to/certs/babaei.net.pem
subject= /CN=babaei.net
$ openssl x509 -noout -subject -in /path/to/certs/learnmyway.net.pem
subject= /CN=learnmyway.net
$ openssl x509 -noout -subject -in /path/to/certs/3rr0r.org.pem
subject= /CN=3rr0r.org
假设我们有两个域名 alpha.com 和 omega.com。如何配置启用 SNI 的 nginx 来为每个域名提供正确的 SSL 证书?
server {
server_tokens off;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.alpha.com;
ssl on;
ssl_certificate /path/to/alpha.com/cert.pem;
ssl_certificate_key /path/to/alpha.com/key.pem;
}
server {
server_tokens off;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.omega.com;
ssl on;
ssl_certificate /path/to/omega.com/cert.pem;
ssl_certificate_key /path/to/omega.com/key.pem;
}
谢谢
更新:这是原始配置:
server {
server_tokens off;
listen 80;
listen [::]:80;
server_name learnmyway.net;
location / {
return 301 https://www.$server_name$request_uri; # enforce https / www
}
# Error Pages
include /path/to/snippets/error;
# Anti-DDoS
include /path/to/snippets/anti-ddos;
# letsencrypt acme challenges
include /path/to/snippets/letsencrypt-acme-challenge;
}
server {
server_tokens off;
listen 80;
listen [::]:80;
server_name *.learnmyway.net;
location / {
return 301 https://$host$request_uri; # enforce https
}
# Error Pages
include /path/to/snippets/error;
# Anti-DDoS
include /path/to/snippets/anti-ddos;
# letsencrypt acme challenges
include /path/to/snippets/letsencrypt-acme-challenge;
}
server {
server_tokens off;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.learnmyway.net;
# Hardened SSL
include /path/to/snippets/hardened-ssl;
ssl_certificate /path/to/certs/learnmyway.net.pem;
ssl_certificate_key /path/to/keys/learnmyway.net.pem;
ssl_trusted_certificate /path/to/certs/learnmyway.net.pem;
#error_log /path/to/learnmyway.net/log/www_error_log;
#access_log /path/to/learnmyway.net/log/www_access_log;
root /path/to/learnmyway.net/www/;
index index.html;
# Error Pages
include /path/to/snippets/error;
# Anti-DDoS
include /path/to/snippets/anti-ddos;
# letsencrypt acme challenges
include /path/to/snippets/letsencrypt-acme-challenge;
# Compression
include /path/to/snippets/compression;
# Static Resource Caching
include /path/to/snippets/static-resource-caching;
}
答案1
看来 @AlexeyTen 是对的。添加以下服务器块解决了该问题:
server {
server_tokens off;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name learnmyway.net;
# Hardened SSL
include /path/to/snippets/hardened-ssl;
ssl_certificate /path/to/certs/learnmyway.net.pem;
ssl_certificate_key /path/to/keys/learnmyway.net.pem;
ssl_trusted_certificate /path/to/certs/learnmyway.net.pem;
return 301 https://www.$server_name$request_uri; # enforce www
}
我的错误:由于 * 是通配符,我以为 *.learnmyway.net 也会解析 learnmyway.net。看来我错了。