Nginx 支持多个域名共用一个 443 端口,并为每个域名配置不同的 SSL 证书。这项功能依赖 SNI(Server Name Indication,服务器名称指示) 技术来实现。

简单来说,当客户端(如浏览器)发起 HTTPS 连接时,会在 TLS 握手阶段通过 SNI 扩展告诉 Nginx 它要访问的域名。Nginx 收到后,就能根据这个域名,从众多 `server` 块中匹配到正确的配置,并使用对应的证书。

核心配置思路是为每个域名创建一个独立的 `server` 块。以下是一个基础配置

1. 为每个域名配置独立的 server 块

```nginx

第一个域名:example.com

server {

    listen 443 ssl;

    server_name example.com www.example.com;

    # 指定该域名对应的证书和私钥

    ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem;

    ssl_certificate_key /etc/nginx/ssl/example.com/privkey.pem;

    # 网站根目录或其他配置

    root /var/www/example.com;

    # ... 其他 location 配置

}

第二个域名:another-site.com

server {

    listen 443 ssl;

    server_name another-site.com www.another-site.com;

    # 使用另一套独立的证书

    ssl_certificate /etc/nginx/ssl/another-site.com/fullchain.pem;

    ssl_certificate_key /etc/nginx/ssl/another-site.com/privkey.pem;


    root /var/www/another-site;

    # ... 其他 location 配置

}

```

2. 优化:提取公共 SSL 配置

如果多个域名的 SSL 参数(如协议版本、加密套件等)相同,可以将其提取到一个公共文件中,用 `include` 指令引入,使配置更简洁。

首先,创建一个公共配置文件,例如 `/etc/nginx/ssl-common.conf`:

```nginx

# /etc/nginx/ssl-common.conf

ssl_protocols TLSv1.2 TLSv1.3;

ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;

ssl_prefer_server_ciphers off;

ssl_session_cache shared:SSL:10m;

ssl_session_timeout 1d;

# ... 其他 SSL 相关配置

```

然后,在每个 `server` 块中引入它:

```nginx

server {

    listen 443 ssl;

    server_name example.com www.example.com;

    ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem;

    ssl_certificate_key /etc/nginx/ssl/example.com/privkey.pem;


    # 引入公共 SSL 配置

    include /etc/nginx/ssl-common.conf;

    root /var/www/example.com;

}

```

3. (可选)配置默认 server 块处理未匹配请求

建议配置一个默认的 `server` 块,用于处理那些无法通过 `server_name` 匹配的请求,例如直接通过 IP 访问。

```nginx

server {

    listen 443 ssl default_server;

    server_name _; # 匹配任何未指定的域名

    # 可以配置一个默认证书,或者直接拒绝连接

    ssl_certificate /etc/nginx/ssl/default/fullchain.pem;

    ssl_certificate_key /etc/nginx/ssl/default/privkey.pem;

    return 444; # 直接关闭连接,不返回任何响应

}

```

4. 验证与测试

配置完成后,务必按以下步骤验证,确保无误:

1.  检查配置文件语法:

    ```bash

    nginx -t

    ```

    如果显示 `syntax is ok` 和 `test is successful`,说明配置语法正确。

2.  重载 Nginx 配置:

    ```bash

    nginx -s reload

    ```

3.  测试证书是否匹配:

    使用 `openssl` 命令模拟带有 SNI 的请求,可以验证服务器是否返回了正确的证书。

    ```bash

    openssl s_client -connect example.com:443 -servername example.com

    ```

    检查输出中的证书信息,确认是否为 `example.com` 的证书。

重要注意事项

   证书要求:每个 `server` 块中 `server_name` 指定的域名,必须被该块中 `ssl_certificate` 对应的证书所覆盖(即证书的通用名称 `CN` 或使用者备用名称 `SAN` 中需包含该域名)。

   路径与权限:`ssl_certificate` 和 `ssl_certificate_key` 应使用绝对路径。确保证书文件(`.pem`/`.crt`)权限为 `644`,私钥文件(`.key`)权限为 `600`。

   SNI 兼容性:SNI 已被所有现代浏览器和操作系统广泛支持。对于极少数不支持 SNI 的旧客户端,Nginx 无法正确匹配域名,将回退到默认的 `server` 块。

   listen 指令:确保 `listen` 指令中包含 `ssl` 参数,这是启用 SSL 的现代写法。

   HTTP 跳转:别忘了为每个域名配置监听 80 端口的 `server` 块,将 HTTP 请求重定向到 HTTPS。