我很乐意使用nginx为一个拥有多个域名和SSL的网站提供服务:
这是否可能在一个虚拟主机中完成,还是需要设置两个虚拟主机?
- webmail.example.com
- webmail.beispiel.de
这是否可能在一个虚拟主机中完成,还是需要设置两个虚拟主机?
2014年11月修改:初始答案不正确且不完整; 需要更新!以下是正确的内容。
基本上,有两种情况
在这种情况下,您可以使用几个 vhosts 监听相同的IP地址/https端口,并且两个 vhosts 使用相同的证书(监听所有接口),例如:
server {
listen 443;
server_name webmail.example.com;
root /var/www/html/docs/sslexampledata;
ssl on;
ssl_certificate /var/www/ssl/samecertif.crt;
ssl_certificate_key /var/www/ssl/samecertif.key;
...
}
server {
listen 443;
server_name webmail.beispiel.de;
root /var/www/html/docs/sslbeispieldata;
ssl on;
ssl_certificate /var/www/ssl/samecertif.crt;
ssl_certificate_key /var/www/ssl/samecertif.key;
...
}
或者在你的特定情况下,让两个域名由同一数据服务。
server {
listen 443;
server_name webmail.example.com webmail.beispiel.de; # <== 2 domains
root /var/www/html/docs/sslbeispieldata;
ssl on;
ssl_certificate /var/www/ssl/samecertif.crt;
ssl_certificate_key /var/www/ssl/samecertif.key;
...
}
如果您拥有上述情况(所有证书使用同一个IP地址),现代浏览器仍可通过Server Name Indication工作。SNI使客户端(浏览器)在请求头中发送其要访问的主机,使服务器(nginx)能够在处理证书之前处理虚拟主机(vhosts)。配置与上面相同,只是每个虚拟主机都有特定的证书、crt和key。
(nginx从0.9.8f开始支持SNI,请检查您的nginx服务器是否符合SNI标准)
(此外,SF也讨论了SNI和浏览器支持)
否则,如果您还希望覆盖旧版浏览器,则需要使用多个监听不同IP地址/https端口的虚拟主机(vhosts),例如:
server {
listen 1.2.3.4:443; # <== IP 1.2.3.4
server_name webmail.example.com;
root /var/www/html/docs/sslexampledata;
ssl on;
ssl_certificate /var/www/ssl/certifIP1example.crt;
ssl_certificate_key /var/www/ssl/certifIP1example.key;
...
}
server {
listen 101.102.103:443; <== different IP
server_name webmail.beispiel.de;
root /var/www/html/docs/sslbeispieldata;
ssl on;
ssl_certificate /var/www/ssl/certifIP2beispiel.crt;
ssl_certificate_key /var/www/ssl/certifIP2beispiel.key;
...
}
原因在这里解释得很清楚。
使用TLS SNI: SNI允许浏览器在SSL握手期间传递请求的服务器名称
检查Nginx是否启用了TLS SNI
$ nginx -V
...
TLS SNI support enabled
...
error_log
,确保没有出现以下警告信息:
Nginx HTTPS 文档 中有更详细的介绍。nginx 编译时开启了 SNI 支持,但是现在它与一个不支持 tlsext 的 OpenSSL 库动态链接,因此 SNI 不可用。
# Create the self signed certificate
openssl req -x509 -newkey rsa -nodes -keyout default.key -days 36500 -out default.crt -subj "/CN=example.org"
openssl req -x509 -newkey rsa -nodes -keyout a.key -days 36500 -out a.crt -subj "/CN=a.example.org"
openssl req -x509 -newkey rsa -nodes -keyout b.key -days 36500 -out b.crt -subj "/CN=b.example.org"
server {
listen 443 ssl default_server;
server_name "";
ssl_certificate default.crt;
ssl_certificate_key default.key;
add_header "Content-Type" "text/plain";
return 200 "default page";
}
server {
listen 443 ssl;
server_name a.example.org;
ssl_certificate a.crt;
ssl_certificate_key a.key;
add_header "Content-Type" "text/plain";
return 200 "a.example.org page";
}
server {
listen 443 ssl;
server_name b.example.org;
ssl_certificate b.crt;
ssl_certificate_key b.key;
add_header "Content-Type" "text/plain";
return 200 "b.example.org page";
}
# Add -v to verify the certificate
$ curl --insecure --resolve "a.example.org:443:127.0.0.1" https://a.example.org
a.example.org page
$ curl --insecure --resolve "b.example.org:443:127.0.0.1" https://b.example.org
b.example.org page
$ curl --insecure https://127.0.0.1
default page
如果Nginx禁用了TLS SNI:Nginx会为所有请求使用默认的server
证书。
这是由SSL协议行为引起的。浏览器发送HTTP请求之前建立SSL连接,nginx不知道所请求的服务器名称。因此,它只能提供默认服务器的证书。
/etc/nginx/sites-include
目录,其中放置了所有我的包含文件...),然后在每个块中执行公共部分的包含、server_name 和添加特定的证书指令。 - Déjà vu