Yefei.Blog

个人日记 WIKI

用户工具

站点工具


nginx:ssl

Nginx HTTPS 取不到 $host 问题

在实际项目中遇到一个问题,可以自动匹配任意站点访问并跳转到 https 地址, 在 http 层可以很好处理跳转问题,但是到了 https 层却无法访问站点,对应目录下面也放有证书,看起来像是取不到证书。 查看 nginx error.log 发现对应的变量 $server_name 为空,但是在 http 里面就可以取到。 被这个问题困扰,最后查询相关文档才醒悟过来,因为 ssl 加密从 tcp 握手开始,从哪以后 http 协议也被加密,无法解密也就无法取到所有通过 http 协议传过来的数据,包括主机名 为了解决这个问题 SSL 专门扩展了一个协议 SNI,用来预先告诉服务器所要访问的域名。

server {
  listen 80 default_server;
  include /etc/nginx/include/site-80.conf;
  location / {
    rewrite ^.*$ https://$server_name$request_uri permanent; # 这里可以取到 $server_name
  }
}
 
server {
  listen 443 ssl http2 default_server;
 
  # 错误的做法
  # ssl_certificate /data/site-ssl/$server_name/ssl.pem; # 因为 ssl 加密从 tcp 握手开始,从哪以后 http 协议也被加密,无法解密也就无法取到所有通过 http 协议传过来的数据,包括主机名
 
  ssl_certificate /data/site-ssl/$ssl_server_name/ssl.pem;     # 使用 $ssl_server_name 才能取到需要的主机名称,这是 SNI 协议特有
  ssl_certificate_key /data/site-ssl/$ssl_server_name/ssl.key;
 
  ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_prefer_server_ciphers on;
  ssl_session_cache shared:SSL:40m;
  ssl_session_timeout 180m;
  include /etc/nginx/include/locations.conf;
}
nginx/ssl.txt · 最后更改: 2020/11/10 17:07 由 yefei