在只有一个公网  IP  的情况下托管多个  HTTPS  站点,并为每个站点使用不同的  SSL  证书,这是典型的单  IP  多域名  SSL  场景。该方案依赖于  SNI(Server  Name  Indication)  扩展,它允许服务器在  TLS  握手阶段根据客户端发送的域名来选择对应的证书。Nginx  对  SNI  的支持非常完善,配置也十分简单。下面是一套完整的  Nginx  配置方案,包含站点隔离、证书指定、HTTP  强跳  HTTPS  以及性能优化建议。

1.  前提条件

-  Nginx  版本  ≥  0.8.21(SNI  功能从该版本开始稳定)。

-  编译  Nginx  时已开启  SNI  支持(可通过  `nginx  -V`  检查输出中是否有  `TLS  SNI  support  enabled`)。

-  已为每个域名申请好  SSL  证书(通常包含  `.crt`  证书文件和  `.key`  私钥文件)。

2.  基本配置结构

在  Nginx  的配置文件中(例如  `/etc/nginx/nginx.conf`  或  `/etc/nginx/sites-enabled/`  下的文件),为每个  HTTPS  站点定义一个  `server`  块,均监听  `443  ssl`,并通过  `server_name`  区分不同域名。

nginx

全局  SSL  配置(可放在  http  块内,作为默认值)

ssl_protocols  TLSv1.2  TLSv1.3;

ssl_ciphers  HIGH:!aNULL:!MD5;

ssl_prefer_server_ciphers  on;

ssl_session_cache  shared:SSL:10m;

ssl_session_timeout  10m;

站点  A

server  {

        listen  443  ssl;

        server_name  www.example.com  example.com;

        ssl_certificate          /path/to/example.com/fullchain.pem;      #  证书文件(含中间证书)

        ssl_certificate_key  /path/to/example.com/privkey.pem;            #  私钥文件

      其他站点配置(根目录、日志等)

        root  /var/www/example;

        index  index.html;

}

站点  B

server  {

        listen  443  ssl;

        server_name  www.anotherexample.com  anotherexample.com;

        ssl_certificate          /path/to/anotherexample.com/fullchain.pem;

        ssl_certificate_key  /path/to/anotherexample.com/privkey.pem;

        root  /var/www/anotherexample;

        index  index.html;

}

关键点:

-  每个  `server`  块独立指定  `ssl_certificate`  和  `ssl_certificate_key`。

-  多个  `server`  块共享同一个  IP  的  `443`  端口,Nginx  会根据  `server_name`  自动选择匹配的证书。

3.  将  HTTP  请求重定向到  HTTPS

为了让用户访问  `http://`  时自动跳转到  `https://`,需要为每个站点额外添加一个监听  `80`  端口的  `server`  块,并返回  301  重定向。

nginx

HTTP  重定向(可以统一写一个  server  块匹配所有域名,也可以为每个域名单独写)

server  {

        listen  80;

        server_name  www.example.com  example.com  www.anotherexample.com  anotherexample.com;

      统一重定向到  HTTPS  相同域名

        return  301  https://$host$request_uri;

}

或者为了更清晰,也可以为每个站点分别写:

nginx

server  {

        listen  80;

        server_name  www.example.com  example.com;

        return  301  https://$host$request_uri;

}


server  {

        listen  80;

        server_name  www.anotherexample.com  anotherexample.com;

        return  301  https://$host$request_uri;

}

4.  优化与注意事项

4.1  SSL  会话缓存复用

在  `http`  块中设置的  `ssl_session_cache`  可以让所有站点共享  SSL  会话缓存,提高  TLS  握手性能。建议配置如下:

```nginx

ssl_session_cache  shared:SSL:50m;      #  大小根据站点数量调整

ssl_session_timeout  4h;

4.2  使用  HSTS(可选)

如果希望强制浏览器始终使用  HTTPS,可以在  HTTPS  站点中添加  HSTS  头:

```nginx

add_header  Strict-Transport-Security  "max-age=63072000;  includeSubDomains;  preload"  always;

4.3  证书路径与权限

-  确保证书文件和私钥文件对  Nginx  进程(如  `www-data`  或  `nginx`  用户)可读。

-  私钥文件权限建议设置为  `600`。

4.4  证书链完整

推荐使用包含完整中间证书的  `fullchain.pem`(由  Let's  Encrypt  或其他  CA  提供),避免某些客户端因缺少中间证书而报错。

4.5  SNI  客户端兼容性

目前几乎所有现代浏览器和操作系统都支持  SNI,只有极少数老旧客户端(如  Windows  XP  上的  IE)可能无法访问。如果必须兼容这类客户端,则需要为所有域名使用同一张多域名证书(SAN  证书),或者使用同一个  IP  的不同端口。

4.6  使用多域名证书简化配置

如果你有多个域名需要共用同一个  IP,也可以购买或申请一张包含多个域名的证书(例如  `www.example.com`、`www.anotherexample.com`  都列在证书的  Subject  Alternative  Names  中)。这样只需一个  `server`  块监听  443,并为所有域名配置同一张证书:

```nginx

server  {

        listen  443  ssl;

        server_name  www.example.com  www.anotherexample.com;    #  多个域名

        ssl_certificate          /path/to/multi-domain/fullchain.pem;

        ssl_certificate_key  /path/to/multi-domain/privkey.pem;

        ...

}

但题目要求的是“单IP多站点SSL证书”,一般理解为每个站点独立证书,因此上述方案更符合原意。

5.  完整配置示例

以下是一个整合了所有要素的  `/etc/nginx/sites-available/example`  文件内容:

nginx

server  {

        listen  80;

        server_name  www.example.com  example.com;

        return  301  https://$host$request_uri;

}


server  {

        listen  80;

        server_name  www.anotherexample.com  anotherexample.com;

        return  301  https://$host$request_uri;

}

server  {

        listen  443  ssl;

        server_name  www.example.com  example.com;

        ssl_certificate          /etc/letsencrypt/live/example.com/fullchain.pem;

        ssl_certificate_key  /etc/letsencrypt/live/example.com/privkey.pem;

        root  /var/www/example;

        index  index.html;

        access_log  /var/log/nginx/example_access.log;

        error_log    /var/log/nginx/example_error.log;

        可选  HSTS

        add_header  Strict-Transport-Security  "max-age=63072000"  always;

}

server  {

        listen  443  ssl;

        server_name  www.anotherexample.com  anotherexample.com;

        ssl_certificate          /etc/letsencrypt/live/anotherexample.com/fullchain.pem;

        ssl_certificate_key  /etc/letsencrypt/live/anotherexample.com/privkey.pem;

        root  /var/www/anotherexample;

        index  index.html;

        access_log  /var/log/nginx/anotherexample_access.log;

        error_log    /var/log/nginx/anotherexample_error.log;

        add_header  Strict-Transport-Security  "max-age=63072000"  always;

}

然后在  `/etc/nginx/sites-enabled/`  下创建软链接启用该配置,并执行  `nginx  -t`  测试配置,无误后重载  Nginx:

bash

ln  -s  /etc/nginx/sites-available/example  /etc/nginx/sites-enabled/

nginx  -t

systemctl  reload  nginx      #  或  nginx  -s  reload

6.  验证配置

可以使用  `openssl`  命令检查  SNI  是否正常工作:

```bash

openssl  s_client  -connect  your_server_ip:443  -servername  www.example.com      #  应返回  example.com  的证书

openssl  s_client  -connect  your_server_ip:443  -servername  www.anotherexample.com    #  应返回  anotherexample.com  的证书

如果返回的证书分别对应各自域名,说明配置成功。

通过以上配置,就可以在一个  IP  上托管多个  HTTPS  站点,并为每个站点使用独立的  SSL  证书。