NGINX配置https

2019-06-30 0 条评论 782 次阅读 0 人点赞

在以往看到的博客中对于NGINX支持HTTPS,大多数还只是配置证书相关的内容,当我把自己的博客升级支持https的时候,发现了很多问题,在这里一并做一个分享

加密技术的简单介绍

目前来说, 主要的加密方式有两种,一种是对称加密一种是非对称加密,但是每一种加密方式的具体算法又有很多种,这里不会赘述

对称加密:就是我们日常中体会的比较多的那种,加密数据和解密数据使用的是相同的秘钥

非对称加密:他有一个公钥和一个私钥,使用公钥加密的数据只能由其对应的私钥进行加密,同样,使用私钥进行加密的数据只能由其对应的公钥进行解密,这样的好处是可以对对端进行认证,如果不是和自己成对的秘钥就无法解开数据,有效的避免了流量的劫持,保证数据完整,可靠的传输给发起方想传送到的对方,其具体的数学算法是利用了一个大质数,具体的过程,我自己也没整明白,这里就不献丑了

当然还有一种,单项加密,这种也不能算是加密,他只是一种数据完整性校验的算法,使用这种算法 可以将一段数据计算成一个固定长度的特征码,不论在任何时候,任何地点,只要数据不变,都可以使用相同的算法得到相同的结果,当然只要数据一旦变化,其特征码会进行翻天覆地的变化.

HTTPS简单介绍

HTTPS,相较于HTTP协议,是在HTTP协议下的一层加入了一个ssl层,利用了非对称加密的形式将http协议的内容进行了加密,这样服务器发送的数据就只有相应的客户端能解密,而客户端发送的数据就只有服务器可以解密,

谈到https会经常听到一个词叫CA,CA就是给网站颁发证书的机构,他可以认证这个证书到底是不是CA自己签发的证书,说白了他要认证这个网站是不是这个网站,在服务端将自己的公钥证书发送给浏览器之后,浏览器会用CA的公钥证书去解密这个公钥证书,解密成功并且拿到相应的内容,那么就认为这个公钥证书是真正这个网站发送过来的的,也就证明了服务器的真实性

有些人会有误解认为自己的网站使用了https之后网站就百毒不侵了(当然,这么认为的好像也并不多),其实不然,https主要保证的是,发送方和接收方都是我们要进行对话的双方,它可以比较有效的避免流量的劫持,当然对于https还有很多的方法去进行流量的劫持,所谓道高一尺魔高一丈,事物总是在不断的持衡的过程中而相互发展壮大的

由于非对称加密不论是加密还是解密的过程其速度都是比较慢的,所以在真正的数据传输时都不是直接通过非对称加密去加密整个数据的,而是先将整个数据通过对称加密(也就是我们传统的加密技术,加密解密使用同一段密文),而后将密码进行非对称加密,将加密的结果放在数据包的后面,服务端拿到数据包后,先将数据包后面的若干长度的数据提取出来,使用自己的私钥进行解密,得出数据的密码,使用这个密码解密整个数据,最后看到真实的数据

以上这段内容只是非常粗略的描述了一下,里面还会涉及到很多的细致的内容,这里就不具体阐述了(好多我自己也没整明白呢)

证书申请过程

说到证书申请必须要提到一个词就是CA(Certificate Authority),也就是证书的颁发机构,其工作过程大概是,客户端(注意此时的客户端是网站对应的服务器)自己生成一个私钥,而后再通过这个私钥生成一个请求文件,当然这个文件里会包含客户端的一些信息,比如自己的公钥,地址,公司名,网站主机名等,然后将这个文件,提交给证书颁发机构,证书的颁发机构,利用其自己的私钥将这个文件进行加密,而后返回给客户端,这样服务器就有了他自己的公钥和私钥,这样在其提供服务的时候就可以将自己的证书发送给客户端,客户端保存了CA的公钥,并利用这个公钥对证书进行解密,如果得到了正确的结果,那么就证明通信的对端是可信的,否则就是不可信的

编译支持HTTPS的NGINX

NGINX早已支持了TLSv1.3,而OpenSSL在1.1.1版本才开始支持TLSv1.3,而目前大部分的Linux发行版自带的OpenSSL还是1.0.x版本,因此我们这里需要先下载OpenSSL1.1.1版本的源码,注意这里不用编译OpenSSL,nginx可以使用--with-openssl=/path/to/openssl_source直接指定OpenSSL源码进行编译,点击下载地址可以到OpenSSL的GitHub仓库进行下载,这里说一下,TLSv1.3相比于之前的版本无论在安全性还是性能方面都有了很大的提升,

根据PCI DSS合规标准的规定,服务器不应该继续支持TLSv1.0协议或者更早的协议,这样做可能会不兼容一些低版本的浏览器,比如IE8以下的版本

这里提供一个我自己编译时的一些参数

./configure \
--prefix=/path/to/nginx \
--user=nginx--group=nginx \
--with-select_module \
--with-poll_module \
--with-threads \
--with-file-aio \
--with-http_ssl_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_v2_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_auth_request_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module \
--with-stream_ssl_preread_module \
--with-http_stub_status_module \
--with-openssl=/usr/local/src/openssl-OpenSSL_1_1_1c \
--with-pcre=/usr/local/src/pcre-8.43 \
--with-zlib=/usr/local/src/zlib-1.2.11 \

由于是升级为https,相信大部分人应该是从旧的nginx版本进行升级,而不是部署新的环境,nginx虽然提供了热升级的方案,但是有一个坑需要注意,那就是,之前在启动nginx时,必须使用带有绝对路径的nginx命令进行升级,否则nginx没有办法找到现在nginx进程对应的二进制文件的路径,这样是没有反应的,因此这里强烈建议,在安装完nginx后做一个命令别名

alias nginx=/path/to/nginx/sbin/nginx
echo 'alias nginx=/path/to/nginx/sbin/nginx' >> ~/.bashrc

当然热升级过程官方文档也有说明,这里记录一下,方便使用

mv /path/to/nginx/sbin/{nginx,nginx.oldbin} # 备份旧的nginx二进制文件    
cp objs/nginx /path/to/nginx/sbin/ # 拷贝新版本的二进制文件到sbin目录 
kill -USR2 `cat /path/to/nginx/nginx.pid` # 向nginx进程发送USR2信号,使新的二进制文件启动进程
kill -WINCH `cat /path/to/nginx/nginx.pid.oldbin` # 使旧的worker进程优雅关闭   
kill -QUIT `cat /path/to/nginx/nginx.pid.oldbin` #如果没有问题可以将旧的nginx进程关闭了   
kill -HUP `cat /path/to/nginx/nginx.pid.oldbin` # 如果有问题可以使用-HUP信号重启旧的进程

https关键配置项:

listen 443 ssl http2;                # 指定监听端口,启用ssl,启用http2
ssl_certificate ssl/fullchain.pem;   # 指定证书文件
ssl_certificate_key ssl/privkey.pem; # 指定私钥文件
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; # 指定服务器支持的协议
ssl_ciphers # 应该是支持的加密算法,可以使用openssl ciphers命令查看
ssl_early_data on; # 开启TLSv1.3的early data特性,有助于提高ssl握手的速度具体可查看rfc8446#section-2.3

配置http重定向到https

server {
        listen 80;
        server_name example.com;
        if ( $scheme = "http" ) {
                return 301 https://$host$request_uri;
        }
        access_log logs/80-access.log main;
}

支持HSTS

hsts配置起来很简单,只是加一个http头就可以了,其作用是,第一次浏览器访问网站时会强制浏览器记住自己的站点支持https,这样下次访问时浏览器自动会使用https去访问网站,不论你的URL输入的是http还是https,浏览器也会记录公钥证书,当有链路劫持时,即使是第一次访问,浏览器也可以判定服务端证书是否合法

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

DNS CAA

感觉目前对这个的支持并不多,DNS有一个CAA(Certificate Authority Authorization)的记录类型即证书颁发机构授权,就是当一个权威的证书颁发机构在签发证书时会先查询该域名的CAA记录,如果其记录对应的不是自己,那么它不会为该域名颁发证书,在一定程度上能避免证书的伪造,当然证书颁发机构如果不遵守这个规定,那你也没办法,对于CAA记录的详细说明可查看rfc6844文档,感觉这项技术,浏览器应该去支持,每次都去检查一下证书的颁发机构,是否对应,也不知道浏览器支不支持

著名的DNS服务软件BIND从9.9.6版本之后开始支持CAA记录,目前国内的DNS提供商对CAA记录支持的并不是特别多,具体软件的支持情况和服务商的支持情况可以到https://sslmate.com/caa/support这个站点查询,另外,具体的配置方式也可以到https://sslmate.com/caa/这个URL进行查询,输入自己的域名,选择证书颁发机构,会自动生成相关配置

OCSP Stapling

正式名称为TLS证书状态查询扩展,可代替在线证书状态协议(OCSP)来查询X.509证书的状态。服务器在TLS握手时发送事先缓存的OCSP响应,用户只需验证该响应的有效性而不用再向数字证书认证机构(CA)发送请求。

大概意思就是,每次建立连接时,浏览器都需要向证书颁发机构发起请求查询证书合法性,是否过期,是否被吊销,配置了OCSP的服务端程序会主动获取证书状态,与其他信息一并发送给客户端,一定程度上加速了网站的加载时间

相关配置:

ssl_stapling on;        # 启用 OCSP
ssl_stapling_verify on; # 启用服务器对OCSP响应的验证
ssl_trusted_certificate ssl/chain.pem; # 指定中间证书

对网站的评估

有两个网站,可以对站点的情况进行打分,评估

https://www.ssllabs.com/ssltest/analyze.html

https://myssl.com/

可以输入你自己的域名进行检测

HTTPS绝对不是配置好证书就完事的,还有很多需要做的工作,我这里目前只知道这些了,以后学的多了再做分享,以下图片是我的博客在sslabs的得分,里面还有好多我搞不懂的东西,以后再看吧
_2019-06-30_013743.png

bighero

这个人太懒什么东西都没留下

文章评论(0)