介绍
HTTPS(HyperText Transfer Protocol Secure,超文本传输安全协议)。
Nginx的HTTPS协议服务是通过ngx_http_ssl_module模块实现的,在配置编译参数时要添加—with-http-ssl_module参数启用该功能。
可以通过ssllabs.com对HTTPS的配置进行安全性检测,并按照测试结果针对性地进行优化。
HTTPS原理
完整流程:
- 客户端Client Hello发送包含协议版本号、客户端随机数(Client Random)、支持加密套件列表的请求给服务端。
- 服务端获得客户端HTTPS请求后,将包含网站信息及网站证书公钥的证书、服务端随机数(Server Random)及随机选择的客户端支持加密套件返回给客户端,若需要验证客户端身份,也会再此时发送相关信息到客户端。
- 客户端通过操作系统中的CA公钥解密证书获取网站证书公钥并进行网站证书的合法性、有效期及是否被吊销的验证。
- 客户端用网站证书公钥将新生成的客户端随机数加密后发送给服务端,同时使用3个随机数生成会话秘钥。
- 服务端使用网站证书私钥解密客户端数据获取客户端随机数(Pre-master),使用3个随机数生成会话秘钥。
服务端与客户端使用一致的会话秘钥和加密算法完成传输数据的加密交互。
存在会话缓存的流程:
客户端Client Hello的时候会携带会话凭证请求服务端。
- 服务端通过会话凭证复用会话,如果服务端在缓存中未找到会话,则转换成完整的TLS握手。
配置指令
指令名称 | 指令值格式 | 默认值 | 指令说明 |
---|---|---|---|
ssl | on 或 off | off | 启用SSL支持,建议使用 listen ssl on; |
ssl_protocols | [SSLv2][SSLv3] [TLSv1][TLSv2] [TLSv1.2][TLSv1.3 |
TLSv1 TLSv1.1 TLSv1.2 |
设置使用的SSL协议 |
ssl_buffer_size | size | 16k | 设置用于发送数据的缓存大小 |
ssl_certificate | file | - | PEM格式的网站证书文件,可自建或由CA机构颁发 |
ssl_certificate_key | file | - | PEM格式的网站证书私钥文件,可自建或由CA机构颁发 |
ssl_password_file | file | - | 存放网站证书私钥密码的文件,一个密码一行,有多个密码时,Nginx会依次尝试 |
ssl_ciphers | ciphers | HIGH: !aNULL: !MD5 |
设置HTTPS建立连接时用于协商使用的加密算法组合,也称密码套件,指令值内容为openssl的密码套件名称,多个套件名称可用”:”分隔 |
ssl_prefer_server_ciphers | on或off | off | 是否启用在SSLv3和TLSv1协议的HTTPS连接优先使用服务端设置的密码套件 |
ssl_dhparam | file | - | DH秘钥交换的Diffie-Hellman参数文件 |
ssl_ecdh_curve | curve | auto | 配置SSL加密时使用椭圆曲线DH秘钥交换的曲线参数,多个参数间使用”:”分隔。ecdh是Elliptic-Curve和Diffie-Hellman的缩写,指令值为auto时,配置的曲线参数是prime256v1 |
ssl_early_data | on或off | off | 是否启用TLS 1.3 0-RTT 支持 |
ssl_session_cache | off或none或 [builtin[:size]] [shared:name:size] |
none | HTTPS会话缓存设置,指令值请看下方相关说明 |
ssl_session_tickets | on或off | on | 是否启用会话凭证(Session Ticket)机制实现HTTPS会话缓存,当指令值为off时,使用会话编号(Session ID)机制 |
ssl_session_ticket_key | file | - | 指定会话凭证秘钥文件,用于在多台Nginx间实现会话凭证共享,否则Nginx会随机生成一个会话凭证密钥 |
ssl_session_timeout | time | 5m | 设置客户端可用会话缓存的超时时间 |
ssl_verify_client | on或off或 optional或 optional_no_ca |
off | 设置是否启用客户端证书验证功能。当值为on时启用验证;当值为optional时,如果接收到客户端证书则启用验证;当值为option_no_ca时,若接收到客户端证书则启用客户端证书验证,但不进行证书链校验。将验证结果存储在$ssl_client_verify变量 |
ssl_verify_depth | number | 1 | 设置客户端证书链验证深度 |
ssl_crl | file | - | 用于验证客户端证书有效性的证书吊销列表文件 |
ssl_client_certificate | file | - | 指定一个PEM格式的CA证书(根或中间证书)文件,该证书用作在线证书协议(OCSP)响应的证书验证或客户端证书验证,该证书列表会发送给客户端。 |
ssl_trusted_certificate | file | - | 指定一个PEM格式的CA证书(根或中间证书)文件,该证书用作在线证书协议(OCSP)响应的证书验证或客户端证书验证,该证书列表不会发送给客户端。 |
ssl_stapling | on或off | off | 是否启用在线证书协议结果缓存 |
ssl_stpling_file | file | - | 在线证书协议结果缓存文件 |
ssl_stapling_responder | url | - | 设置获取在线证书协议结果的URL,优先级低于ssl_stapling_file,仅支持HTTP协议,默认端口80 |
ssl_stapling_verify | on或off | off | 设置是否启用在线证书协议结果缓存证书校验 |
- 上述指令都可以编写在http、server指令域中。
- ssl_ciphers指令值的内容是OpenSSL参数ciphers的内容,可以通过如下命令查看
openssl ciphers # 列出OpenSSL支持的密码套件
openssl ciphers -v ‘ALL:eNULL’ # 列出指定密码套件详情
- 密码套件格式及说明可参见OpenSSL相关文档
- ssl_session_cache指令值参数如下
off: 禁止HTTPS会话缓存。
none: 启用伪会话缓存支持,Nginx告知客户端可进行会话重用,但服务端并未存储会话参数。
builtin: OpenSSL中内置的缓存;仅由一个工作进程使用,如果未指定大小,则等于20480个会话,使用内置缓存会导致内存碎片。
shared: 所有工作进程之间共享的缓存。缓存大小以字节为单位指定;1MB可以存储大约4000个会话。
两种缓存类型可以同时使用,例如:
ssl_session_cache builtin:1000 shared:SSL:10m;
Nginx配置
server {
listen 443 ssl;
server_name oyyh.cn;
charset utf-8;
root /home/www/oyyh;
index index.html index.htm;
ssl_certificate cert/www_oyyh_cn.pem; # HTTPS网站证书
ssl_certificate_key cert/www_oyyh_cn.key; # HTTPS网站证书私钥
ssl_password_file cert/www_oyyh_cn.pass; # HTTPS网站证书秘钥密码文件
}
OpenSSL自签证书
X.509证书包含三个文件:key,csr,crt。
- key是服务器上的私钥文件,用于对发送给客户端数据的加密,以及对从客户端接收到数据的解密
- csr是证书签名请求文件,用于提交给证书颁发机构(CA)对证书签名
- crt是由证书颁发机构(CA)签名后的证书,或者是开发者自签名的证书,包含证书持有人的信息,持有人的公钥,以及签署者的签名等信息
备注:在密码学中,X.509是一个标准,规范了公开秘钥认证、证书吊销列表、授权凭证、凭证路径验证算法等。
创建自签名证书
注意:以下步骤仅用于配置内部使用或测试需要的SSL证书。
一、生成私钥
$ openssl genrsa -des3 -out server.key 2048
需要输入大于4位数的密码。
说明:生成rsa私钥,des3算法,2048位强度,server.key是秘钥文件名。
二、生成CSR(证书签名请求)
生成秘钥之后,便可以创建csr文件了。
此时有两种选择:
- 可以将证书发送给证书颁发机构(CA),CA验证请求者信息之后,会出具签名证书(很贵)。
- 如果只是内部使用或测试,可以使用OpenSSL实现自签名,操作如下:
$ openssl req -new -key server.key -out server.csr -config openssl.cfg
说明:需要依次输入国家、地区、城市、组织、组织单位,Common Name和Email。其中Common Name可以写自己的名字或域名,如果需要支持https,Comman Name应该与域名保持一致,否则会引起浏览器警告。
三、删除私钥中的密码
在第一步创建私钥过程中,需要指定一个密码,但是有时这个密码会存在副作用,比如apache每次启动Web服务时,都需要输入密码。
删除私钥中的密码:
$ openssl rsa -in server.key -out server.key
四、生成自签名证书
如果使用自签名的临时证书,浏览器会提示证书的颁发机构是未知的。
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
说明:crt上有证书持有人的信息,持有人的公钥,以及签署者的签名等信息。
五、安装私钥和证书
将证书复制到你想存放的目录,并在nginx.conf中做相关配置
HTTPS会话缓存
会话缓存机制有两种实现方式:会话编号(Session ID)和会话凭证(Session Ticket)。