nginx - 使用 ssl 支持设置多个 server_name

问题描述 投票:0回答:2

我很想使用 nginx 来为具有多个域名和 SSL 的网站提供服务:

  • webmail.example.com
  • webmail.beispiel.de

两者都使用相同的虚拟主机,因此我只设置 server_name 两次。 问题是,我需要 nginx 为每个域名提供正确的 ssl 证书。

这可以使用一个虚拟主机还是我需要设置两个虚拟主机?

ssl nginx ssl-certificate vhosts
2个回答
112
投票

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)仍然可以通过服务器名称指示与现代浏览器配合使用。 SNI 让客户端(浏览器)在请求标头中发送它想要到达的主机,从而允许服务器(nginx)在处理证书之前处理vhosts。配置与上面相同,只是每个vhost都有一个特定的证书,crtkey

nginx从0.9.8f开始支持SNI,请检查你的nginx服务器是否兼容SNI
还有SF讲SNI和浏览器支持

否则,如果您也想访问较旧的浏览器,则需要多个 vhosts 分别侦听 不同 IP 地址/https 端口,例如

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

原因很好解释在这里


3
投票

使用 TLS SNI

SNI 允许浏览器在 SSL 握手期间传递请求的服务器名称

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

检查Nginx是否启用了TLS SNI

$ nginx -V
...
TLS SNI support enabled
...

并检查

error_log
是否存在此警告:

nginx 是使用 SNI 支持构建的,但是现在它已链接 动态地连接到不支持 tlsext 的 OpenSSL 库, 因此 SNI 不可用

Nginx HTTPS 文档 有更多详细信息。

测试

创建自签名证书用于测试

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"
# Add -v to show 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 禁用 TLS SNI:Nginx 将为所有请求使用默认的

server
证书。

Nginx 文档

这是由 SSL 协议行为引起的。 SSL 连接是在浏览器发送 HTTP 请求之前建立的,并且 nginx 不知道请求的服务器的名称。因此,它可能只提供默认服务器的证书。

© www.soinside.com 2019 - 2024. All rights reserved.