Linux Nginx服务器搭建SSL/TLS(https+http/2)
首先,SSL/TLS是什么?
比如:https://www.awaimai.com/,前面是https,表明这个是https协议。
https就是http+SSL/TLS,在http外面套一个加密层,让第三方难以得到传输的明文数据。
如果用chrome访问这个站,在这个URL旁边会显示一个绿色的锁,表明这个连接是安全的。
另外,境外的https还有一个附加效果,就是抵御关键字的审查,同时Google也更喜欢收录https的站点。
其实以上是在说废话,看这文章的乃萌肯定是知道此为何物才会找到这里来的啦,所以就不废话了。
由于这里主要讲搭建步骤,去CA机构注册什么的就不介绍了,个人小站推荐StartSSL和AlphaSSL,前者可以得到免费证书。
1生成证书签署请求文件
新建一个目录,并在这个目录中生成密钥文件(.key)和证书签署请求文件(.csr):
$mkdir/etc/nginx/ssl $cd/etc/nginx/ssl $opensslreq-new-newkeyrsa:2048-sha256-nodes-outwww.awaimai.com.csr-keyoutwww.awaimai.com.key
其中,
- req:表示指定证书类型,后面一般跟-new或者-x509选项。-new说明要生成证书请求,x509说明要生成自签名证书。
- -newkey:表示在生成证书请求或者自签名证书时自动生成密钥,本例要求生成2048位的rsa密钥。
- -sha256:表示签名算法使用sha256。openssl默认采用sha1加密,而现代已将sha1加密方式认定为非安全,故使用sha2。
- -nodes:表示认证过程不需要输入密码。
- -out:指定证书名称。
- -keyout:指定密钥名称。
然后会要求你输入一些信息,具体如下,从EmailAddress开始不要填写:
CountryName(2lettercode)[AU]:CN StateorProvinceName(fullname)[Some-State]:Guangdong LocalityName(eg,city)[]:Shenzhen OrganizationName(eg,company)[InternetWidgitsPtyLtd]:AwaimaiInc. OrganizationalUnitName(eg,section)[]:WebSecurity CommonName(eg,YOURname)[]:www.awaimai.com EmailAddress[]: Achallengepassword[]: Anoptionalcompanyname[]:
CommonName填写你要SSL支持的域名,如www.awaimai.com,泛域名证书填*.awaimai.com。
填写完毕后,就会生成 www.awaimai.com.csr请求文件和www.awaimai.com.key密钥文件。
上面的信息也可以在openssl命令后加上-subj参数指定,省去证书信息的录入过程:
$opensslreq-new-newkeyrsa:2048-sha256-nodes-outwww.awaimai.com.csr-keyoutwww.awaimai.com.key-subj"/C=CN/ST=Guangdong/L=Shenzhen/O=AwaimaiInc./OU=WebSecurity/CN=www.awaimai.com"
这样第一步就完成了。
2签发一个crt证书
使用编辑器打开刚才生成的csr文件,会看到类似如下的内容:
-----BEGINCERTIFICATEREQUEST----- MIICrjCCAZYCAQAwaTELMAkGA1UEBhMCR0IxDzANBgNVBAgMBkxvbmRvbjEPMA0G ...... -----ENDCERTIFICATEREQUEST-----
复制里面全部内容,然后在CA机构网站上,提交csr内容的地方粘贴。
如下是Let'sEncrypt和AlphaSSL的网站地址。
- Let'sEncrypt(免费) :https://letsencrypt.org/
- AlphaSSL:http://www.alphassl.com/
签发成功后,就能下载回来一个.crt文件,可能通过网页上下载,也可能通过邮件方式发送给你。
如果是邮件方式的话,最好是使用Gmail邮箱。
邮件方式的话需要自行复制里面crt文件的部分自行保存为crt文件。
crt文件类似以下的格式:
-----BEGINCERTIFICATE----- MIIETTCCAzWgAwIBAgILBAAAAAABRE7wNjEwDQYJKoZIhvcNAQELBQAwVzELMAkG ... -----ENDCERTIFICATE-----
保存好了后,第二步就完成了。
3配置证书链
这一步在某些情况下不是必需的,建议先跳过这一步。
如果Chrome访问网站提示网站不可信,再配置证书链。如果已经提示安全,则不需要配置证书链。
前面推荐的两家机构所签发的证书没有直接返回证书链,需要自行配置。
用Chrome访问网站,按F12进入调试模式,选Security标签,点击ViewCertificate按钮查看证书。
如上,我的网站与根证书中间差了一级,上上一级才是根证书DSTRootCAX3。
而浏览器和操作系统里面保存的均是可信任的根证书,中间那一层Let'sEncrptAuthorityX3很可能是没有的。
直接使用CA机构提供的crt证书,可能导致浏览器提示这是不可信的网站。
那如何配置证书链?其实配置这个证书链非常的简单。
首先,选择父级证书,点击【查看证书】,选【详细信息】,【复制到文件】,到处格式用“base64编码X.509(.CER)”,然后导出父级证书。
同理,导出父级的父级证书。
使用文本编辑器打开crt证书,然后父级crt证书的内容粘贴到后面,像这样子:
-----BEGINCERTIFICATE----- 自己的crt证书 -----ENDCERTIFICATE----- -----BEGINCERTIFICATE----- 父级的crt证书 -----ENDCERTIFICATE----- -----BEGINCERTIFICATE----- 父级的父级crt证书 -----ENDCERTIFICATE-----
有多少层就做多少层(除了根证书那一层),然后保存为新的crt文件,如cert_chain.crt。
就完成了证书链的配置了。
4Nginx配置
文本编辑器打开nginx配置文件,找到相应域名。
删除对80端口的监听:
listen80;
加入如下配置:
server{ #... #监听443端口 listen443ssl; #开启ssl sslon; #指定域名 server_namewww.awaimai.com; #指定证书 ssl_certificate/etc/nginx/ssl/cert_chain.crt; #指定密钥 ssl_certificate_key/etc/nginx/ssl/www.awaimai.com.key; #使用HSTS(HTTPStrictTransportSecurity)策略,强制浏览器总是使用HTTPS连接, #这样攻击者在用戶与服务器通讯过程中便难以拦截、篡改信息以及冒充身份变 add_headerStrict-Transport-Securitymax-age=31536000; #... }
然后再加一个server块,监听80端口,301跳转到https:
server{ listen80; server_namewww.awaimai.comawaimai.com; add_headerStrict-Transport-Securitymax-age=31536000; return301https://www.awaimai.com$request_uri; }
重启服务即可。
5使用赫尔曼密钥(可选)
为了更安全,可以考虑使用迪菲-赫尔曼密钥交换。
在Shell命令行:
$cd/etc/nginx/ssl $openssldhparam-outdhparam.pem2048#生成迪菲-赫尔曼密钥
然后在nginxssl配置的后面,加上下面的配置:
server{ #... #设置服务器加密方式优先于客户端 ssl_prefer_server_cipherson; #指定迪菲-赫尔曼密钥位置 ssl_dhparam/etc/nginx/ssl/dhparam.pem; #使用安全协议,禁止其他不安全的SSL协议 ssl_protocolsTLSv1TLSv1.1TLSv1.2; #禁止已经不安全的加密算法 ssl_ciphers"EECDH+ECDSA+AESGCMEECDH+aRSA+AESGCMEECDH+ECDSA+SHA384EECDH+ECDSA+SHA256EECDH+aRSA+SHA384EECDH+aRSA+SHA256EECDH+aRSA+RC4EECDHEDH+aRSA!aNULL!eNULL!LOW!3DES!MD5!EXP!PSK!SRP!DSS!RC4"; #... }
SSL的运行计算需要消耗额外的CPU资源,其中SSL通讯过程中『握手』阶段的运算最占用CPU资源。
有两个方法可以减少每台客户端的运算量:
- 激活keepalive长连接,一个连接发送更多个请求
- 配置ssl_session_cache,复用SSL会话参数,在并发的连接数中避免进行多次SSL『握手』
这样,session会存储在一个SSL会话缓存里面。
1M的ssl_session_cache大概包含4000个会话。
然后利用客戶端在『握手』阶段使用的seesionid去查询服务端的sessioncache,简化『握手』阶段。
另外,还可以使用ssl_session_timeout 配置缓存超时时间,默认5分钟。
配置范例:
server{ #... #配置共享会话缓存大小 ssl_session_cacheshared:SSL:10m; #配置会话超时时间 ssl_session_timeout10m; #设置长连接 keepalive_timeout70; #... }
一般情況下,还可以加上以下几个命令,增强安全性:
#减少点击劫持 add_headerX-Frame-OptionsDENY; #禁止服务器自动解析资源类型 add_headerX-Content-Type-Optionsnosniff; #防XSS攻击 add_headerX-Xss-Protection1;
7配置HTTP/2(可选)
HTTP/2于2015年5月作为互联网标准正式发布。
它基于Google制定的SPDY协议,由IETFHTTPbis小组制定维护。
并且Google表示将放弃SPDY转而全力支持HTTP/2。
HTTP/2与HTTP/1.x的主要区别:
- 基于二进制而不是文本的
- 完全多路复用,代替原来的排序和阻塞机制
- 在一条连接中并行处理多个请求
- 压缩头部减少开销
- 允许服务器主动推送响应到客户端的缓存中
配置HTTP/2之前,我们要确保:
- openssl版本为1.0.2+,因为HTTP/2需要openssl支持ALPN
- Nginx版本为1.9.5+,因为这个版本默认编入了--with-http_v2_module
$opensslversion#openssl必须为1.0.2或以上版本 $nginx-V#1.9.5或以上版本,低于这个版本需要自行编译加入--with-http_v2_module
如果版本不满足要求,则需要重新编译,编译之前需要安装一些依赖工具和库:
$yuminstallgcc-c++pcre-develzlib-develmakewgetopenssl-devellibxml2-devellibxslt-develgd-develperl-ExtUtils-EmbedGeoIP-develgperftools-devel
7.1更新openssl
openssl更新步骤:
$wgethttps://www.openssl.org/source/openssl-1.0.2-latest.tar.gz $tar-zxfopenssl-1.0.2-latest.tar.gz $cdopenssl-1.0.2k $./config $makedepend $make $makeinstall
完成之后,如果还是显示原来版本,则:
$mv/usr/bin/openssl~#备份原来的文件 $ln-s/usr/local/ssl/bin/openssl/usr/bin/openssl#新的bin文件软链到系统/usr/bin目录下
7.2重新编译nginx
用nginx-V命令可以看到nginx编入的openssl版本,我的是OpenSSL1.0.1e-fips,明显不满足要求。
我们需要编入为openssl 1.0.2 或以上版本,所以要重新编译一遍nginx。
$wgethttp://nginx.org/download/nginx-1.10.3.tar.gz $tarzxfnginx-1.10.3.tar.gz $cdnginx-1.10.3 $./configure... $make $makeinstall
./configure后面的配置项请自行加上,也可以直接拷贝nginx-V命令输出的配置参数。
7.3配置http2
在端口监听处加上http2就可以了:
server{ #... listen443sslhttp2; #... }
7 总结
最后嘛,为啥窝会想到弄成https呢?
因为窝知道很多路由器可以开启网站访问log,会记录下访问者IP、所访问的url、以及get/post参数内容。这表示什么吗?
这表示如果你通过这个路由器上网,然后在普通http网页上做登陆操作,那么路由器的管理员可以通过查log得到你对应网站的登陆信息。
这是非常危险的。
因为绝大多数的网站在传输登陆信息的时候,均使用明文发送密码,这样你的帐号密码就被看得一清二楚了。
但是https的话,路由器根本无法知道你所访问的url是什么,更别说具体的参数内容了,只能知道访问者的IP和目标IP,安全性自然大大提高。
比如你在麦当劳用免费wifi,那么那边的路由管理员就知道你的帐号密码了。
或者电信联通什么的也会知道,因为它们在政策下必须保留至少3个月的路由数据,而你的帐号密码就在那里保存至少三个月。
想要抓你只要把你的登陆记录找到,然后登陆你的帐号,查你的个人信息就知道你到底是谁了。
也就是说,任何非https连接下做登陆或其它敏感操作是非常危险的,所有的操作被完整的记录了下来。
本文除了介绍SSL/TLS的配置外,还简要的介绍了一下其必要性,科普一下网络安全方面的东西。
如对这方面还有疑问,欢迎留言或mail窝。
参考资料:
- HowToCreateanSSLCertificateonNginxforUbuntu14.04
- Nginx配置HTTPS服务器
- Nginx配置SSL证书+搭建HTTPS网站
- openssl证书请求和自签名命令req详解
- 使用openssl生成sha256自签名证书
- 或许是Nginx上配置HTTP2最实在的教程了
- OpenSourceNGINX1.9.5ReleasedwithHTTP/2Support
- HowtoupgradeOpenSSLinCentOS6.5/Linux/Unixfromsource?
- HowtoupgradeOpenSSLonCentos7orRHEL7
- HTTP/2一定要先升级到HTTPS么?
- 配置Nginx,开启HTTP/2
- HowtogetalreadyinstalledNGINXtouseOpenSSL1.0.2forALPN?