十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
本篇内容介绍了“nginx怎么实现keyless”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
简介
创新互联建站成都网站建设按需设计网站,是成都网站营销公司,为白乌鱼提供网站建设服务,有成熟的网站定制合作流程,提供网站定制设计服务:原型图制作、网站创意设计、前端HTML5制作、后台程序开发等。成都网站改版热线:13518219792
当企业把业务迁移到云WAF/边缘节点上,需向云厂商提供业务的私钥安全性不能得到保证,且若业务私钥证书发生变化或频繁修改需要受限于人。风险:一旦服务端的私钥泄露会导致恶意攻击者伪造虚假的和客户端通信,通信内容也存在被劫持和解密的风险。keyless源于clouldflare,采用keyless方案私钥部署在客户自己的服务器,无需向把业务私钥部署在云/CDN边缘节点上。clouldflare keyless项目地址:
https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/cloudflare keyless开源项目地址:
https://github.com/cloudflare/keyless相关基础知识介绍:加解密套件知识普及
MAC(Message authentication code):消息认证码
PRF(pseudorandom function):伪随机函数
SHA (Secure Hash Algorithm):安全散列算法
对称密码:
DES:是以64比特的明文为一个单位来进行加密的,密钥长度是64比特
三重DES: 就是将DES重复3次,有3个密钥
AES(Advanced Encryption Standard):是一种新标准的对称密码算法,已取代DES
分组长度128比特,密钥长度128、192、256三种规格
分组密码模式 :
ECB(Electronic CodeBook):将明文分组加密之后的结果将直接成为密文分组
CBC(Cipher Block Chaining):密文分组链接的模式
CFB(Cipher FeedBack):密文反馈模式
OFB(Output-Feedback):输入反馈模式
CTR(CounTeR):计数器模式
GCM(Galois Counter Mode):Galois/计数器模式
填充模式:对当明文长度不为分组长度的整数倍时,需要在最后一个分组中填充一些数据使其填满一个分组长度,攻击者会利用这个利用这个在最后一个分组填充一些数据。
单向散列函数
输入的是消息输出的是散列值,任意长度的消息计算出固定长度的散列值,消息不同散列值也不同
应用:MD4、MD5;SHA-2系列(SHA-256,SHA-384,SHA-512,数字表示计算后的散列值长度)
密钥交换算法
RSA本质上是为了解决密钥配送的问题,密钥配送的是配送的是运算对称密钥的关键信息,并不是对称密钥
RSA:这是一个标准的密钥交换算法,在ClientKeyExchange阶段客户端生成预主秘钥,不支持向前保密,并以服务器公钥加密传送给服务器
DHE_RSA:临时Diffie-Hellman(ephemeral Diffie-Hellman, DHE),支持向前保密,缺点是执行缓慢,DHE是一种秘钥协定算法,进行协商的团体都对密钥生成产生作用,并对公共密钥产生作用
ECDHE_RSA和ECDHE_ECDSA:
临时椭圆曲线Diffe-Hellman(ephemeral elliptic curve Diffie-Hellman, ECDHE)密钥交换建立在椭圆曲线加密的基础之上。执行很快而且提供了向前保密,和DHE类似
过滤了一台设备上一天的数据
TLS握手中使用的密码技术
TLS记录协议位于TLS协议的下层,是负责使用对称密码对消息进行加密通信(对消息压缩、加密以及数据的认证)的部分
TLS握手协议中使用的密码技术
公钥密码:加密预主秘钥用的
单向散列函数:构成伪随机数生成器
数字签名:验证证书用的(单向散列函数计算公钥密码的散列值,加密后得到)
伪随机书生成器:生成预主秘钥
生成初始化向量(可以使用对称密码,单向散列函数来构建)?
根据主密钥生成密钥(密码参数)?
TLS记录协议中使用的密码技术
对称密码(CBC模式):确保片段的机密性
消息认证码:确保片段的完整性并进行认证(单向散列函数和密钥组合而成,也可以通过对称密码生成,应用单向散列函数计算密钥+消息构成的)
认证加密(AEAD,Authenticated-Encryption with Associated-Data用于关联数据的认证加密):确保片段的完整性和机密性并进行认证?HTTPS中所用到的密码技术
证书:公钥、数字签名和指纹组合而成,一般讲是基于指纹的数字签名,一堆的东西就认证公钥,为了保证不可否认行、认证、完整性Keyless原理
总体架构
密钥交换算法类
client random 是第1个随机数R1(公开),对应wireshark抓包里“Client Hello”的Random
server random 是第2个随机数R2(公开),对应wireshark抓包里“Server Hello”的Random
premaster 是第3个随机数R3(私密),该随机数是由客户端创建,然后客户端用服务端传来的证书对premaster secret进行加密,生成premaster secret用来实际传输,对应抓包里的“Client Key Exchange”
服务端用私钥对premaster secret解密,得到premaster,这样只有客户端和服务端知道premaster
最终,客户端和服务端用公开的随机数R1、R2、双方私密的premaster(R3)组合起来,通过预定的算法生成一个hash值,作为之后的对话密钥(session key)
RSA密钥交换算法主密钥计算
Client Random和Server Random明文传输,中间人可以直接查看,客户端生成于中Premaster Secret后,如果有证书私钥就可以直接通过这三个参数解得主密钥
标准RSAkeyless握手方案
工作在:Server端的ChangeCipherSpec阶段
基于DH的完整握手主密钥的计算
从密钥交换流程来说,DH算法和ECDHE一样,二者的主要区别见该页备注里的注意点1~3
client random 是第1个随机数R1(公开),对应wireshark抓包里“Client Hello”的Random ②a、server random 是第2个随机数R2(公开),对应wireshark抓包里“Server Hello”的Random
服务端自己创建一个随机数或者 直接从证书中拿公钥信息(图例是拿公钥信息),记为R3 ,结合上面的两个公开的随机数,通过DH算法算出来服务端DH参数=(R1 * R2 * R3) ,对应wireshark抓包里“Server Key Exchange”的Pubkey。
服务端用私钥,对两个公开随机数R1、R2和服务端的DH参数进行签名,对应wireshark抓包里“Server Key Exchange”的Signature
客户端用证书公钥验证Signature,验证服务端确实拥有私钥后,客户端就创建一个随机数,记为R4,通过DH算法算出来客户端DH参数=(R1 * R2 * R4) ,对应wireshark抓包里“Client Key Exchange”的Pubkey 。 这样,客户端和服务端用对方发来的DH参数,结合各自的私有随机数R3或R4,分别计算得到相同的premaster = (R1 * R2 * R3 * R4) ,且只有客户端和服务端知道premaster 最终,客户端和服务端用公开的随机数1、随机数2、双方私密的premaster组合起来,通过预定的算法生成一个hash值,作为之后的对话密钥(session key)
Server DH Parameter 是用证书私钥签名的,客户端使用证书公钥就可以验证服务端合法性,相比 RSA 密钥交换,DH 由传递 Premaster Scret 变成了传递 DH 算法所需的 Parameter,然后双方各自算出 Premaster Secret。由于 Premaster Secret 无需交换,中间人就算有私钥也无法获得 Premaster Secret 和 Master Secret。
ServerKeyExchange
基于DH的keyless的完整握手
工作在:Server端的ServerKeyExchange阶段
开源项目做了什么keyless server安装和配置
存储给定的私钥。
使用加速卡(EXAR)进行解密,签名操作。
状态信息统计。开源项目地址:
https://github.com/cloudflare/keyless
需要进行二次开发,开源版本很多细节处理的不好。
On Centos:
sudo yum install gcc automake libtool
sudo yum install rpm-build rubybgems ruby-devel # only required for packages
sudo gem install fpm --no-ri --no-rdoc # only required for packages
安装 make即可,make test测试
参数说明 --port keyless server端的监听端口
--ip keyless server端监听的ip
--server-cert和--server-key签发的证书
--private-key-directory 用户证书对应的私钥存放文件夹
--ca-file生成的根证书
--pid-file pid文件
--num-workers 线程数
--verbose打印日志
--daemon守护进程开启nginx于keyless server交互
在SSL_do_handshake解密和签名处理过程中增加一个keyless状态。
PREPARE REQUEST状态,封装keyless请求报文,然后将状态设置为SEND REQUEST,SSL_do_handshake函数返回,nginx将keyless_connection的wev放到epoll里;
SEND REQUEST状态发送keyless请求,成功后将状态设置为RECEIVE RESPONSE,SSL_do_handshake函数返回,nginx将keyless_connection的rev放到epoll里;
RECEIVE RESPONSE状态读请求,全部读完将状态设置为FINISH;如果未读完数据SSL_do_handshake函数返回,nginx将keyless_connection的rev放到epoll里;
FINISH 继续由openssl原有的逻辑处理。
如果rev和wev超时,则关闭ssl_connection。
nginx 处理https握手
ngx_http_init_connection中recv→handler设置为ngx_http_ssl_handshake,把这个读时间加入到epoll中,重点看handshake这个函数
第一次收到client hello之后,完成初始化后调用ngx_ssl_handshake,其调用openssl的ssl_do_handshake
调用keyless模块的init函数先是获取coremodule的main conf,然后获取到servers,遍历这些servers的上下文中的srv conf配置,然后把sscf→ssl.ctx设置cert_cb为keyless_cert_handler,这个函数在api使用证书的时候会调用。
cert handler做了了很多事情,初始化了很多nginx keyless相关的参数,核心在于这个函数新建了一条通向keyserver的连接。
do handshake的时候调用的是openssl的async job的库,相当于新开一个函数栈
ASYNC JOB
先做初始化get下context,malloc一个stack,这个堆栈创建完成后把函数放进去,使用makecontext来创建一旦调用就会运行该函数,async_start_func本身使用当前job中的func,函数也是传进来的参数
Pause job最关键的是swapcontext,这个在func中一旦被调用的话,就可以立即切换栈信息,切回start_job的主函数,根据job→status=ASYNC_JOB_PAUSING来返回
切回主函数之后,因为start job是for死循环,所以会根据job的状态进行返回
返回的这个状态码,在nginx里面接到就是SSL_ERROR_WANT_ASYNC
关键就是调用async_pause_job交还给nginx来做keyless处理,以及将与keyserver的状态调整为presend。
这里处理完交还给nginx,之后nginx 就可以做原本由openssl实现的加解密。
重写engine重写两个关键函数
重写的两个函数是sign和priv_dec
调用pause时最重要逻辑是async_fibre_swapcontext,这个函数是用于切换的核心,同时进行初始化操作,把函数放到新开辟栈里运行。