关于tls:TLS-加速技术Intel-QuickAssist-TechnologyQAT解决方案

作者:vivo 互联网服务器团队- Ye Feng本文介绍了 Intel QAT 技术计划,通过Multi-Buffer技术和QAT硬件加速卡的两种形式实现对TLS的减速 一、背景以后 TLS 曾经成为了互联网安全的次要传输协定,TLS带来更高的安全性的同时,也带来了更多的性能开销。特地是在建连握手阶段,TLS的CPU开销,绝对于TCP要大很多。 业界在优化TLS性能上曾经做了很多软件和协定层面的优化,包含:Session 复用、OCSP Stapling、TLS1.3等。然而在摩尔定律"生效"的今日,软件层面的优化很难满足日益增长的流量,应用专用的硬件技术卸载CPU计算成为目前通用的解决方案。本文将介绍Intel在TLS减速畛域提供的QAT技术计划。 二、Intel QuickAssist Technology(QAT)技术计划Intel 提供了TLS异步减速的残缺解决方案: Intel QuickAssist Technology(QAT),简称Intel QAT技术。 如下图所示,QAT 反对减速的明码算法笼罩了TLS的整个流程,包含:握手阶段的签名、秘钥替换算法,数据传输的AES加解密算法等。 图1. QAT 对TLS流程的明码算法的反对(图片起源) QAT提供了对称与非对称两类明码算法的反对,次要包含: 非对称加密算法:RSA, ECDSA, ECDHE对称加密算法:AES-GCM(128,192,256)注:QAT减速的劣势次要体现在非对称加密上,从官网的整体性能数据看,非对称算法性能晋升1.6~2倍,对称算法性能晋升10%~15% 2.1 QAT Engine 软件栈QAT Engine 是QAT技术计划的外围模块,次要的作用是作为应用程序和硬件之间的中间层,负责 “加解密操作的输入输出数据” 在用户应用程序与硬件卡之间进行传递,次要操作就是IO的读写。 QAT Engine 是以 OpenSSL 第三方插件的形式提供给用户,这个象征用户能够应用 OpenSSL 规范的API,就能够实现对TLS的减速,只须要对原有代码做OpenSSL异步革新,就能够享受QAT技术带来的TLS性能减速,业务侵入性较小。 图2. Intel QAT Engine 软件栈(图片起源) 如上图所示,QAT  Engine 反对两种减速形式: 软件减速(qat_sw):应用 Multi-Buffer (SIMD)技术,对明码算法进行并行处理优化。硬件加速(qat_hw):应用QAT硬件加速卡,将明码算法计算从CPU OffLoad到硬件加速卡。上面将介绍软件和硬件两种减速门路的实现形式。 三、软件减速:采纳 Intel Multi-Buffer 技术Intel 从 whitely 平台开始退出了新的指令集,联合intel Multi-Buffer技术,实现对明码算法的SIMD优化计划。 3.1 Intel Multi-Buffer 技术Intel Multi-buffer 基本原理就是应用CPU的SIMD机制,通过 AVX-512 指令集并行处理数据,来晋升RSA/ECDSA算法性能。 ...

May 22, 2023 · 2 min · jiezi

关于tls:TLSSSLCA-证书公钥私钥今天捋一捋

松哥最近在和小伙伴们连载 gRPC,如何确保 gRPC 通信的安全性?这就波及到 TSL 了,然而思考到可能有小伙伴对加密连贯这一整套计划比拟生疏,因而咱们明天先用一篇文章跟大家捋分明这些概念,概念搞明确了,再来看 TSL+gRPC 就很容易了。 1. HTTP 的问题HTTP 协定是超文本传输协定(Hyper Text Transfer Protocol)的缩写,它是从 WEB 服务器传输超文本标记语言 HTML 到本地浏览器的传送协定。HTTP 设计之初是为了提供一种公布和接管 HTML 页面的办法,时至今日,它的作用曾经不仅仅于此了。 对于咱们 Java 工程师而言,HTTP 应该算是再相熟不过的货色了,目前 HTTP 有多个版本,应用较多的是 HTTP/1.1 版本。 然而 HTTP 协定有一个缺点那就是它是通过明文传输数据的,用户通过 HTTP 协定传输的内容很容易被歹意拦挡,并且黑客能够伪装成服务端,向用户传送谬误的信息,并且能轻易获取用户的隐衷信息,而这些操作用户是齐全无感知的。 因为存在这样的安全隐患,当初小伙伴们见到的大部分网站都在逐渐转为 HTTPS,HTTP 网站会越来越少了。 2. HTTPSHTTPS(HyperText Transfer Protocol Secure)中文译作超文本传输平安协定,这是一种通过计算机网络进行平安通信的传输协定。 HTTPS 实质上还是由 HTTP 进行通信,只是在 HTTP 协定和 TCP 层之间减少了一个 SSL 的平安传输协定。整个传输的加密过程都在新的平安层 SSL/TLS 中实现,而原来的 HTTP 层的传输流程放弃不变,这样就很好地兼容了旧的 HTTP 协定,也因循了 TCP/IP 协定族的分层思维。 通过 HTTPS,客户端能够确认服务端的身份,保证数据在传输过程中不被篡改,当咱们在本人的浏览器上与某一个网站建设 HTTPS 连贯的时候,满足如下状况能够示意这个服务端能够被信赖: 首先咱们的操作系统中装置了正确且受信赖的证书。咱们在 cmd 命令行中执行 certmgr.msc 命令,能够查看操作系统曾经装置的证书列表。 ...

March 23, 2023 · 2 min · jiezi

关于tls:TLS详解

TLS全称是Transport Layer Security,是用来代替SSL的,是一种明码协定,用来提供计算机之间交互的平安通信。次要用于https通信,也用于email,即便通信等。 TLS握手TLS握手通常分为2种形式,一种是根本的握手(具体可参照下图),另一种是客户端服务端握手(因为这种用的少,就不细讲) 通过上图可知,咱们这里说的TLS握手次要讲的是最根本的TLS握手,即只应用服务器的证书来进行加密,具体步骤如下:1.客户端与服务器之间通过3次握手建设连贯2.协商阶段a. client发送一个ClientHello音讯给server,这个音讯蕴含了client反对的最高的TLS协定版本,一个随机数,以后client反对的明码组列表和倡议的压缩算法b.server发送一个ServerHello音讯给client,这个音讯蕴含了TLS协定版本,一个服务器随机数,依据客户端反对的明码组列表最终抉择的明码和最终抉择的压缩算法。c.server发送Certificate(证书)音讯d.server发送ServerKeyExchange音讯e.server发送ServerHelloDone音讯,表明握手协商曾经实现f.client发送ClientKeyExchange音讯,这个音讯蕴含了PreMasterSecret(这个值是依据server发送的Certificate外面的public key通过加密生成的)和 public key。(留神在发送音讯之前,client会对server发送的Certificate进行验证–可参考上面的数字证书,如果验证失败,则握手失败)g.client和server依据client的随机数,server端的随机数和PreMasterSecret计算出一个独特的明码,这个独特的明码叫做master secret) 3.client发送ChangeCipherSpec记录,通知server我前面发送的所有音讯都会是加密的了a.client发送一个已验证并且加密的Finished音讯。蕴含了对之前音讯的hash和macb.server对接管的Finished音讯进行解密并验证hash和mac,如果验证失败,则握手失败 4.server发送ChangeCipherSpec音讯,通知client我前面发送的所有音讯都会是加密的了a.server发送一个已验证并且加密的Finished音讯。蕴含了对之前音讯的hash和macb.client 对接管的Finished音讯进行解密并验证hash和mac,如果验证失败,则握手失败 5.利用阶段:此阶段阐明TLS握手曾经实现,前面所有发送的音讯都会是加密的 数字证书数字证书提供的subjectName(主题名称)设置以后证书的所有权,将以后拜访的地址与证书所有权的地址进行比照,如果一样,则证书无效,如果不一样,则证书有效。同时也会对证书及其父类证书已晓得根证书有效期进行比照,如果不在有效期内,则证书有效参考链接:https://sslhow.com/ssl-tls-ha...

June 28, 2022 · 1 min · jiezi

关于tls:我们应该使用-TLS13-吗

概述SSL(Socket Layer Security)和 TLS(Transport Layer Security) 都是属于平安协定,次要作用是保障客户端和服务端之间能平安通信。SSL是较早的协定,TLS 是 SSL的替代者。 SSL 版本 1.0、2.0 和 3.0,TLS 版本 1.0、1.2 和 1.3。SSL协定和TLS1.0 因为已过期被禁用,目前TLS 1.3 是互联网上部署最多的平安协定,它是TLS最新版本 ,它加强了过期的安全性,并减少了更多的触控性。通过上面几点能够有个简略意识: 最新 TLS1.3 的长处什么向前窃密为什么抉择 GCM 加密TLS 1.3古代浏览器反对 TLS 1.2 和 TLS 1.3 协定,但 1.3 版本要好得多。 TLS 1.3 对晚期版本进行了多项改良,最显著的是简化了TLS握手操作,使得握手工夫变短、网站性能得以晋升、改善了用户体验,另外反对的明码套件更平安和简略。 明码套件 TLS/SSL 应用一种或多种明码套件。 明码套件是身份验证、加密和音讯身份验证的算法组合。TLS 1.2 版应用的算法存在一些弱点和安全漏洞。在 TLS 1.3 中删除了这些算法: SHA-1RC4DES3DESAES-CBCMD5另外一个很重要的更新是TLS1.3 反对 perfect-forward-secrecy (PFS)算法。 向前窃密向前窃密(PFS)是特定密钥协商协定的一项性能,如果一个长周期的会话密钥被泄露,黑客就会截获大量数据,咱们能够为每个会话生成惟一的会话密钥,单个会话密钥的泄露不会影响该会话之外的任何数据。 TLS在晚期版本的握手期间能够应用两种机制之一替换密钥:动态 RSA密钥和 Diffie-Hellman 密钥。 在 TLS1.3 中,RSA 以及所有动态(非 PFS)密钥替换已被删除,只保留了DHE、ECDHE 长期 Diffie-Hellman (DHE)长期椭圆曲线 Diffie-Hellman (ECDHE)能够查看网站的平安详情来确认它是否应用"ECDHE"或"DHE"。 ...

May 16, 2022 · 2 min · jiezi

关于tls:TLSv13-Support主流-Web-客户端和服务端对-TLSv13-的支持情况

请拜访原文链接:https://sysin.org/blog/tlsv1-...,查看最新版。原创作品,转载请保留出处。 作者:gc(at)sysin.org,主页:www.sysin.org 2021 年 8 月公布的 Windows Server 2022 正式反对 QUIC 和 TLS 1.3 相干个性。至此,主流产品曾经全副反对 TLSv1.3 协定。 TLS 1.3 由 IETF 于 2018 年 8 月正式公布。 1. 为什么要应用 TLSv1.3SSL:Secure Sockets Layer 安全套接字层。 TLS:Transport Layer Security,传输层平安。 TLS 是 IETF 在 SSL3.0 根底上设计的协定,实际上相当于 SSL 的后续版本。 TLS(Transport Layer Security)是一种加密协议,旨在通过 IP 网络提供平安通信。它是当今十分常见的协定,用于爱护 Web 浏览器和 Web 服务器之间的 HTTP 通信。当应用 TLS 爱护 HTTP 时,它通常被称为 HTTPS(HTTP Secure)。TLS/SSL 是平安传输层协定,是介于 TCP 和 HTTP 之间的一层平安协定,不影响原有的 TCP 协定和 HTTP 协定。 ...

December 15, 2021 · 5 min · jiezi

阿里云环境中TLSSSL握手失败的场景分析

TLS/SSL握手是一个相对复杂的过程,在阿里云环境中结合产品,安全等特性,可能会让TLS/SSL握手过程的不定性更多。本文来总结下各种握手失败的场景。 一次TLS/SSL握手的过程本文不详细介绍TLS/SSL基础知识,相关介绍可以参考文章。下面3张图描述了3种TLS/SSL握手的全过程。 服务器验证的完全握手 (Full Handshake with Mutual Authentication)这种是互联网大部分HTTPS流量使用的验证模式。证书在服务器上,客户端通过证书来验证服务器是否可靠。 双向验证的完全握手 (Full Handshake with Server Authentication) 这种是对客户端安全性有要求的验证模式。除了客户端要验证服务器外,服务器对客户端也需要进行验证,所以需要双向验证。和上面的步骤相比,多了客户端向服务器传输证书的过程。 简单握手 (Abbreviated Handshake) 完全握手需要2个RTT并交互很多消息,在会话复用的场景下,可以让握手简化到1个RTT完成。过程如下: 常规TLS/SSL握手失败TLS/SSL版本不匹配自从TLS 1.2版本在2008年发布以来,绝大部分HTTPS流量都跑在TLS 1.2上。服务器处于安全性考虑通常也只支持较高版本TLS,比如TLS1.0及以上。但是仍然有一些版本比较旧的操作系统和浏览器存在,如果这些客户端用低版本TLS/SSL向服务器发起握手,会因为服务器不支持而直接失败。 比如淘宝网只支持TLS 1.0及以上版本,用openssl发起SSL 3版本的握手,就会出现handshake failure。 # openssl s_client -connect www.taobao.com:443 -ssl3 -msgCONNECTED(00000003)>>> ??? [length 0005] 16 03 00 00 8f>>> SSL 3.0 Handshake [length 008f], ClientHello 01 00 00 8b 03 00 2a a0 d3 c5 10 b0 0a c0 0b ea fc e7 49 8f d1 66 cd 2a 51 c1 ab f4 ab b7 63 e1 a7 3e e0 d7 14 9b 00 00 64 c0 14 c0 0a 00 39 00 38 00 37 00 36 00 88 00 87 00 86 00 85 c0 0f c0 05 00 35 00 84 c0 13 c0 09 00 33 00 32 00 31 00 30 00 9a 00 99 00 98 00 97 00 45 00 44 00 43 00 42 c0 0e c0 04 00 2f 00 96 00 41 c0 12 c0 08 00 16 00 13 00 10 00 0d c0 0d c0 03 00 0a 00 07 c0 11 c0 07 c0 0c c0 02 00 05 00 04 00 ff 01 00<<< ??? [length 0005] 15 03 00 00 02<<< SSL 3.0 Alert [length 0002], fatal handshake_failure 02 28140191222585232:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:s3_pkt.c:1493:SSL alert number 40140191222585232:error:1409E0E5:SSL routines:ssl3_write_bytes:ssl handshake failure:s3_pkt.c:659:---no peer certificate available---No client certificate CA names sentTLS/SSL cipher suite不匹配在握手的前两个ClientHello和ServerHello包中有一个重要的任务就是协商cipher。客户端在ClientHello中会带上所有支持的cipher suite, 服务器在收到ClientHello中的cipher suite后,会和自己支持的cipher suite一一匹配,如果没有可以匹配的就会握手失败。 ...

July 10, 2019 · 3 min · jiezi

网络之HTTPHTTPS

前言大学老师曾经说过,计算机界有三本天书,分别是:数据结构、计算机组成原理、计算机网络。所以网络也是我们从事计算机开发必须了解且掌握的一门技术 网络七层模型应用层 访问网络服务的端口,如HTTP传输 ‘hello,world’表示层 提供数据格式转换会话层 建立端连接并提供访问验证 如SSL/TLS认证传输层 UDP/TCP + ‘hello,world’网络层 IP + UDP/TCP + ‘hello,world’数据链路层 MAC地址 + IP + UDP/TCP + ‘hello,world’ + 帧尾物理层 传输二进制 01010101001HTTP请求/相应报文 **请求报文包括:** 请求方法 URL 协议版本HTTP1.0 首部字段名 请求体 (POST请求) **响应报文包括:** 版本 状态码 短语 首部字段名 响应实体请求方法GET: 代表获取资源 特点: 安全:不应该引起Server端的任何状态变化 幂等:请求多次的结果一样 可缓存:代理服务器可以缓存POST: 代表处理资源 特点: 不安全 不幂等 不可缓存HEADOPTIONPUT 状态码200: 请求成功300: 请求重定向400: 由于客户端请求地址和参数引用的失败500: 服务端原因 连接接建立流程TCP: 三次握手、四次挥手HTTP特点无连接: 每次请求都需要建立TCP连接无状态 ...

July 8, 2019 · 1 min · jiezi

httpssegmentfaultcoma1190000014740303

https://segmentfault.com/a/11...

May 29, 2019 · 1 min · jiezi

关闭-Apache-2418-TLSSSLProtocolApachesslconfTLS

本教学使用环境介绍伺服器端:Ubuntu 18.04 LTS资料库:Mariadb 10.1.34Apache:2.4.18语言版本:php 7.3本机端:MacOS High Sierra 前往 ssl.conf $ nano /etc/apache2/mods-available/ssl.conf这是 Apache 预设的设定 SSLProtocol all -SSLv3加入 -TLSv1 如以下代表關閉 TLS 1.0還有 -TLSv1.1, -TLSv1.2, -TLSv1.3 SSLProtocol all -SSLv3 -TLSv1重启 Apache $ service apache2 restart参考:https://blog.ijun.org/2017/10... 欢迎加QQ交流,在我个人档案

May 23, 2019 · 1 min · jiezi

X509PKCS文件格式介绍

ASN.1 - 数据结构描述语言引用自Wiki: ASN.1 is a standard interface description language for defining data structures that can be serialized and deserialized in a cross-platform way.也就是说ASN.1是一种用来定义数据结构的接口描述语言,它不是二进制,也不是文件格式,看下面的例子你就会明白了: FooQuestion ::= SEQUENCE { trackingNumber INTEGER, question IA5String}这段代码定义了FooQuestion的数据结构,下面是FooQuestion这个数据接口的某个具体的数据: myQuestion FooQuestion ::= SEQUENCE { trackingNumber 5, question "Anybody there?"}ASN.1用在很多地方比如下面要讲的X.509和PKCS group of cryptography standards。 文件编码格式DER编码格式引用自Wiki: ASN.1 is closely associated with a set of encoding rules that specify how to represent a data structure as a series of bytes意思是ASN.1有一套关联的编码规则,这些编码规则用来规定如何用二进制来表示数据结构,DER是其中一种。 ...

April 27, 2019 · 3 min · jiezi

???? 如何用 wireshark 抓包 TLS 封包

此前一篇文章用 wireshark 这个抓包工具调试了一下 HTTP 请求和响应。详细阐述了 TCP 连接和断开的整个过程。这篇文章尝试使用 wireshark 来抓取 TLS 封包,了解一下 HTTPS 请求和响应的整个过程。 ????懒得看全文的直接拉到最下看 TLS 流程的图片解释首先准备好 curl 和 wireshark,这些谷歌一下怎么安装。 ????HTTPS 是基于 TLS 之上的,如果没有目标的私钥是没办法解密的,如果直接使用 wireshark 是看不到 TLS 层加密的信息的。打开 wireshark 并开启抓包,在 curl 中发送一个请求:再 wireshark 输入 tls 过滤请求,疑似 ip 地址为目标网站输入该 ip 地址,确认是目标网站 httpbin,然后尝试查看返回的数据信息,因为 TLS 加密是看不到返回的 JSON 数据的因 TLS 使用的是迪菲 - 赫尔曼密钥交换生成对称密钥的加密算法,因此需要获取到一系列生成密钥的必要信息后才可生成密钥解密数据。先不着急怎么解决这个问题,首先回顾一下几个知识点,大概了解一下加密算法和 CA 数字证书和 TLS 加密流程:必要的几个知识点 ????加密算法 ????远古以前用的是对称加密,这种加密和解密的密钥是同一个,因此极为不安全,一旦其中一个密钥泄露,那么就会导致加密文件被破解后来发明了非对称加密,这种加密方式的逻辑就是公钥用来加密,私钥用来解密,一方使用另一方的公钥进行加密,传输密文给另一方,另一方再用私钥进行解密,这样没有拿到私钥就无法解密密文。但这种加密解密效率较低,后来就衍生出了混合加密,这种加密方式综合了非对称加密和对称加密。混合加密首先使用非对称加密生成对称密钥,然后再使用对称密钥进行数据安全传输,这样加密解密的效率要高得多了。TLS 用到的迪菲 - 赫尔曼就是其中的一种关于迪菲 - 赫尔曼密钥交换算法,这里简单提一下,这种算法有几个特点:密钥可以合成但不能分解合成后的密钥可以继续再合成合成后的密钥结果与合成顺序无关本质上是一种生成密钥算法这个算法的加密流程是这样的:A 和 B 想要交换并生成对称密钥A 将 P 发送给 BA 使用 P 和自己的私钥 SA 合成 PSAB 使用 P 和自己的私钥 SB 合成 PSB双方交换 PSA 和 PSBA 使用私钥 SA 与 PSB 合成 PSBSAB 使用私钥 SB 与 PSA 合成 PSASB这样对称密钥 PSASB 和 PSBSA 就合成完毕了,双方就可以使用这个对称密钥对传输的数据进行加密 ????⚠️ 问题是 A 将 P 发送给 B,B 如何确认 P 就是真的来自 A 的呢,而不是受到中间人攻击篡改了 P,这就需要使用 CA 认证了,只要有 CA 认证后的数字签名并且通过 CA 的公钥能够验证那么就可以确认 P 就是来自 A 的。数字证书 ????因此这里提一下 CA 证书也简单提一下原理:一个网站 A 想要获取数字证书,那么要走如下流程:A 将网站信息和公钥 PA 发送给 CA 认证机构CA 认证机构验证网站信息并用自己的私钥 SCA 加密生成数字签名,并回传给 AA 收到的数字签名中就包含了 A 的公钥 PA,那么其他人只需要通过 CA 认证机构的公钥即可认证解密数字签名,获取数字签名中的公钥 PA 了那么其他人就可以确定 PA 确实是来自 A 的这样 A 的公钥 PA 就可以被认为确实是来自 A 的,因为有 CA 签发的数字证书认证和背书。 ????⚠️ 还有一个问题是 CA 的公钥谁来认证呢?要是 CA 的公钥也被恶意替换了怎么办?那么就需要 CA 的 CA 来认证了,那么 CA 的 CA 的公钥谁来认证?根据这个逻辑,最后有一个 root CA,这个 CA 用来做最后的权威鉴定。TLS 加密流程 ????最后来回顾一下 TLS 的加密流程TLS 是建立在 TCP 基础上的,因此必定需要先三次 TCP 握手建立 TCP 连接,然后再是建立 TLSClient HelloClient Hello 报文:客户端对加密算法的支持度不同,因此需要向服务端发送客户端支持的 加密套件(Cipher Suite) ,同时还要生成一个 随机数 同时保存在客户端和发送给服务Server HelloServerCertificate 报文:服务端收到 Client Hello 之后,向客户端发送 CA 认证的数字证书,用来鉴别服务端身份信息,同时还要生成一个 随机数 同时保存在服务端和发送给客户端Server Hello Done 报文:表示服务端宣告第一阶段的客户端服务端握手协商结束可选:Certificate Request 报文:必要情况下,要求客户端发送证书验证身份可选:Server Key Exchange 报文:如果 CA 认证的数字证书提供的信息不够,服务端还可发送提供补充信息Client FinishClient Key Exchange 报文:客户端收到 CA 数字证书并通过验证,然后通过 CA 公钥解密获取到 服务端公钥。Client Key Exchange 报文包括有一个随机数,这个随机数被称为 Pre-master key/secret;一个表示随后的信息使用双方协商好的加密方法和密钥发送的 通知 ;还有一个通过协商好的 HASH 算法对前面所有信息内容的 HASH 计算值,用来提供服务端校验。这些信息都通过服务端公钥加密传送给服务端ClientCipherSpec 报文:该报文通知服务端,此后的通信都将使用协商好的加密算法计算对称密钥进行加密通信(也就是使用两个随机数以及第三个 Pre-master key/secret 随机数一起算出一个对称密钥 session key/secret)Finished 报文:该报文包括连接至此的所有报文的校验值,使用服务端公钥进行加密可选:ClientCertificate 报文:如果服务端请求,客户端需要发送 CA 数字证书可选:CertificateVerify 报文:服务端如果要求 CA 数字证书,那么需要通过 HASH 算法计算一个服务端发送来的信息摘要Server Finish服务端最后对客户端发送过来的 Finished 报文使用服务端私钥进行解密校验ClientCipherSpec 报文:报文通知服务端,此后的通信都将使用协商好的加密算法计算对称密钥 session key/secret 进行加密通信Finished 报文:标志 TLS 连接建立成功TLS 握手成功此后通过对称密钥 session key/secret 加密通信以上,我们看到生成的两个随机数和 Pre-master key 一起计算生成 session key 就是通过上文中提到过的迪菲 - 赫尔曼密钥交换算法实现的。客户端收到 CA 数字证书获取到服务端公钥进行加密,也符合上文中提到的 CA 认证流程。服务端私钥解密客户端使用服务端公钥加密,在上文中的非对称密钥部分也进行了讲解。因此 TLS 是一个运用到多种认证、加密的安全传输技术。除此之外,上文中没有提到的使用 HASH 计算的目的则是为了防止数据遭到篡改,这跟我们大家在网上下载软件,计算 md5 校验是一个原理。⚠️ 如有不正确的地方,各位请在评论区指正谢谢最后抓包验证上述加密流程 ????首先上文提到过 wireshark 直接抓取 TLS 的封包是没办法看到解密后的数据的,那么我们需要通过一些手段获取到解密后的数据那么如何才能解密获取数据呢,这里有篇文章可以看看 https://jimshaver.net/2015/02...It turns out that Firefox and Chrome both support logging the symmetric session key used to encrypt TLS traffic to a file. You can then point Wireshark at said file and presto! decrypted TLS traffic.原理是浏览器会在系统中存在名为 SSLKEYLOGFILE 的环境变量已经设置的情况下,将每个 HTTPS 连接产生的客户端或服务端的随机数、preMasterSecret、MasterSecret 全部获取到并保存在这个环境变量指定的文件中。配置环境变量 ????开始动手实操,这里用的是 windows 系统,我们配置环境变量:配置完成,这样浏览器就会写入密钥信息到指定路径的文件中至于 macOS/Linux 自己谷歌一下如何设置环境变量,很简单不再赘述配置 wireshark ????打开 wireshark,点击配置信息指定 TLS 的 Pre-master key 路径为环境变量指定的那个文件路径这样配置就算完成了,我们尝试一下打开 chrome 浏览器访问一个 https 网址:这里访问了百度的首页,可以看到 wireshark 展现的已经是解密后的数据了开始抓包分析 TLS 握手流程 ????然后打开终端使用 curl 发送一个 https 请求还是以 httpbin 为例,过滤 http 查看 wireshark 的结果:右键 follow 一下这就是整个 TCP 建立到 TLS 握手再到 HTTP 请求响应以及 TCP 断开的整个过程,我们逐一分析一下:TCP 的此前文章已经说过了,这里也不再提了,直接看 TLS 部分:Client HelloClient Hello 阶段,客户端给服务端发送一个随机数,以及 Cipher Suites 客户端支持的所有加密套件Server HelloServer Hello 阶段,服务端给客户端发送一个随机数,以及选中的 Cipher Suite 加密套件然后服务端继续发送给客户端 CA 数字证书以及 Server Key Exchange 和 Hello done 信息完成第一阶段的握手:这个是证书:这个是 Server Key Exchange,可以看到协商了一种加密算法:这个是 Server Hello Done:Client Finish客户端发送一个 Client Key Exchange,Change Cipher Spec 和 Finished 报文Finished Verify Data 包括至此连接的所有报文的校验信息,用服务端提供的公钥加密客户端准备好切换为对称密钥加密Server Finish最后服务端返回一个 Change Cipher Spec 和 Server Finish服务端准备好切换为对称密钥加密TLS 握手成功至此,TLS 握手成功,在 wireshark 中就可以看到接下来就是 HTTP 的请求响应封包了:图片解释 ????最后画了个简化版的脑图方便理解:⚠️ 如有不正确的地方,各位请在评论区指正谢谢请关注我的订阅号,不定期推送有关 JS 的技术文章,只谈技术不谈八卦 ???? ...

April 2, 2019 · 2 min · jiezi

如何在Tomcat中做TLS客户端认证

常见的https网站做的是服务端认证(server authentication),浏览器通过证书判断你所访问的https://baidu.com是否真的是百度,而不是其他人伪造的网站。同时还对流量加密,防止别人窃听你的流量。tls还可以做客户端认证(client authentication),即服务端判断客户端是否为其所信任的客户端。由此可见,客户端认证用于那些需要受控访问服务端。在数据中心中,有些服务是非常敏感的,那么我们要做到:客户端和我的流量是加密的,防止别人监听客户端能够确认所访问的服务端的确是我们提供的服务端,而不是别人伪造的服务端只有我信任的客户端可以访问我,防止恶意请求所以很明显,前两个问题可以通过服务端认证解决,最后一个问题可以通过客户端认证解决。顺便一提,如果要使用客户端认证就必须使用服务端认证。先来讲讲概念然后举个tomcat的例子讲讲怎么做。概念服务端认证不论是做Server authentication还是Client authentication都需要证书。证书的来源有两种:由权威CA签发,一般都是去购买。也可以使用let’s encrypt申请免费证书。自己签发在一切可能的情况下都应该使用权威CA签发的证书,为什么这么建议?因为这里牵涉到一个信任问题,浏览器、编程语言SDK和某些工具都维护了一个信任CA证书清单,只要是由这些CA签发的证书那就信任,否则就不信任。而这个链条是可以多级的,这里就不展开了。你只需要知道由信任CA签发的所有证书都是可信的。比如JDK自带的信任CA证书可以通过下面命令看到:keytool -list -keystore $JAVA_HOME/jre/lib/security/cacertsverisignclass2g2ca [jdk], 2016-8-25, trustedCertEntry,证书指纹 (SHA1): B3:EA:C4:47:76:C9:C8:1C:EA:F2:9D:95:B6:CC:A0:08:1B:67:EC:9Ddigicertassuredidg3 [jdk], 2016-8-25, trustedCertEntry,证书指纹 (SHA1): F5:17:A2:4F:9A:48:C6:C9:F8:A2:00:26:9F:DC:0F:48:2C:AB:30:89verisignuniversalrootca [jdk], 2016-8-25, trustedCertEntry,…让你输密码的时候输入changeit。如果这个证书不是由信任CA签发的(比如自己签发)会发生什么?浏览器、编程语言SDK、你所使用的工具会报告以下错误:curl:curl: (60) SSL certificate problem: self signed certificate in certificate chainJava:Exception in thread “main” javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1964) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:328) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:322) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1614)…浏览器:这个错误实际上就是在告诉你这个证书不可信任,可能是一个伪造站点,让你小心点儿。如果这个证书由权威CA签发,那么就没有这个问题了。但是权威CA签发的证书要求申请人拥有域名,如果你这个服务是内部使用的没有域名,那就只能自己签发了。那么如何解决上面的问题呢?你得把自己签发的证书加入到信任CA证书清单里。下图是权威CA签发证书的示例:可以看到客户端有一个truststore,这个就是存放信任CA证书的地方,服务端有一个keystore,存放的自己的证书及对应的私钥。下图是自签发证书的示例:在上面可以看到我们自己成为了一个Root CA,把它放到客户端的truststore里。客户端认证前面讲过客户端认证是服务端来验证客户端是否可信的机制,其实做法和服务端认证类似只不过方向相反。客户端认证大多数情况下只能是自签发的(因为没有域名),虽然不是不可以从权威CA签发但是存在一些问题。下面解释为什么,假设权威CA是let’s encrypt,然后服务端信任它签发的所有证书。但是let’s encrypt是阿猫阿狗都可以申请的,现在有一个黑客申请了这个证书,然后请求你的服务端,服务端就认可了。上面这个问题可以用这个方法解决:比如你用let’s encrypt申请了A证书,黑客用let’s encrypt申请了B证书,你的服务端的truststore只信任A证书,那么黑客用B证书访问你的时候就会被拒绝。但是这就带来另一个问题,比如你在开发的时候客户端证书有这么几套:生产用、调试用、开发用,那么每次客户端签发一个证书都要更新到你的服务器的truststore里,这也太麻烦了。所以结合安全性和便利性,我们把自己变成Root CA,然后服务端信任它,这样一来服务端就可以在开发的时候把Client Root CA内置进去,大大减轻了维护truststore的工作量,看下图:用Tomcat举个例子下面举一个Tomcat做客户端认证的例子,因为是测试用,所以服务端认证也是用的自签发证书。我们用了cfssl这个工具来生成证书。服务端先弄一套目录:# 放自签发的服务端CA根证书server-secrets/ca# 放自签发的服务端的证书server-secrets/cert# 放服务端的keystore和truststoreserver-secrets/jks生成自签名CA证书新建文件:server-secrets/ca/server-root-ca-csr.json内容如下:{ “key”: { “algo”: “rsa”, “size”: 2048 }, “names”: [ { “O”: “Company”, “OU”: “Datacenter”, “L”: “Shanghai”, “ST”: “Shanghai”, “C”: “CN” } ], “CN”: “server-root-ca”}运行下面命令生成Server ROOT CA证书:cfssl gencert –initca=true ./server-root-ca-csr.json | cfssljson –bare server-root-ca会得到下面几个文件:server-secrets/ca/├── server-root-ca-key.pem├── server-root-ca.csr└── server-root-ca.pem用下面命令验证证书:openssl x509 -in ./server-root-ca.pem -text -nooutCertificate: Data: Version: 3 (0x2) Serial Number: 0c:8a:1a:ca:da:fa:4c:17:6c:1f:42:40:4c:f1:90:f4:fd:1d:fe:58 Signature Algorithm: sha256WithRSAEncryption Issuer: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=server-root-ca Validity Not Before: Mar 27 05:14:00 2019 GMT Not After : Mar 25 05:14:00 2024 GMT Subject: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=server-root-ca可以看到签发人和被签发人是同一个。生成自签发证书新建文件 server-secrets/cert/server-gencert.json,内容如下:{ “signing”: { “default”: { “usages”: [ “signing”, “key encipherment”, “server auth” ], “expiry”: “87600h” } }}可以看到我们会生成用来做server auth的证书。新建文件 server-secrets/cert/demo-csr.json,内容如下:{ “key”: { “algo”: “rsa”, “size”: 2048 }, “names”: [ { “O”: “Company”, “OU”: “Datacenter”, “L”: “Shanghai”, “ST”: “Shanghai”, “C”: “CN” } ], “CN”: “server-demo”, “hosts”: [ “127.0.0.1”, “localhost” ]}看上面的hosts,你可以根据自己的需要填写域名或IP,这里因为是本地演示所以是127.0.0.1和localhost。运行下面命令生成证书cfssl gencert \ –ca ../ca/server-root-ca.pem \ –ca-key ../ca/server-root-ca-key.pem \ –config ./server-gencert.json \ ./demo-csr.json | cfssljson –bare ./demo得到文件:server-secrets/cert/├── demo-key.pem├── demo.csr└── demo.pem验证结果:openssl x509 -in ./demo.pem -text -nooutCertificate: Data: Version: 3 (0x2) Serial Number: 1d:d0:51:97:6c:ce:ea:29:2a:f4:3b:3c:48:a3:69:b0:ef:f3:26:7b Signature Algorithm: sha256WithRSAEncryption Issuer: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=server-root-ca Validity Not Before: Mar 27 05:17:00 2019 GMT Not After : Mar 24 05:17:00 2029 GMT Subject: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=server-demo可以看到签发者是server-root-ca,Subject是server-demo。将证书导入keystore到 server-secrets/jks,执行下面命令生成pkcs12格式的keystore(JDK识别这个格式)openssl pkcs12 -export \ -in ../cert/demo.pem \ -inkey ../cert/demo-key.pem \ -out server-demo.keystore \ -name server-demo \ -CAfile ../ca/server-root-ca.pem \ -caname root -chain过程中会让你输入密码,你就输入:server-demo-ks。得到文件:server-secrets/jks/└── server-demo.keystore用JDK提供的keytool看看里面的内容:keytool -list -keystore server-demo.keystoreserver-demo, 2019-3-27, PrivateKeyEntry,证书指纹 (SHA1): B2:E5:46:63:BB:00:E7:82:48:A4:2F:EC:01:41:CE:B4:4B:CE:68:7A让你输入密码的时候就输入:server-demo-ks。客户端先弄一套目录:# 放自签发的客户端CA根证书client-secrets/ca# 放自签发的客户端的证书client-secrets/cert# 放客户端的keystore和truststoreclient-secrets/jks生成自签名CA证书新建文件 client-secrets/ca/client-root-ca-csr.json:{ “key”: { “algo”: “rsa”, “size”: 2048 }, “names”: [ { “O”: “Company”, “OU”: “Datacenter”, “L”: “Shanghai”, “ST”: “Shanghai”, “C”: “CN” } ], “CN”: “client-root-ca”}运行下面命令生成Client ROOT CA证书:cfssl gencert –initca=true ./client-root-ca-csr.json | cfssljson –bare client-root-ca会得到下面几个文件:client-secrets/ca/├── client-root-ca-key.pem├── client-root-ca.csr└── client-root-ca.pem用下面命令验证证书:openssl x509 -in ./client-root-ca.pem -text -nooutCertificate: Data: Version: 3 (0x2) Serial Number: 7e:fc:f3:53:07:1a:17:ae:24:34:d5:1d:00:02:d6:e4:24:09:92:12 Signature Algorithm: sha256WithRSAEncryption Issuer: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=client-root-ca Validity Not Before: Mar 27 05:20:00 2019 GMT Not After : Mar 25 05:20:00 2024 GMT Subject: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=client-root-ca可以看到签发人和被签发人是同一个。生成自签发证书新建文件 client-secrets/cert/client-gencert.json,内容如下:{ “signing”: { “default”: { “usages”: [ “signing”, “key encipherment”, “client auth” ], “expiry”: “87600h” } }}可以看到我们会生成用来做client auth的证书。新建文件 client-secrets/cert/demo-csr.json,内容如下:{ “key”: { “algo”: “rsa”, “size”: 2048 }, “names”: [ { “O”: “Company”, “OU”: “Datacenter”, “L”: “Shanghai”, “ST”: “Shanghai”, “C”: “CN” } ], “CN”: “client-demo”}这里没有hosts,这是因为我们不需要用这个证书来做服务端认证。运行下面命令生成证书cfssl gencert \ –ca ../ca/client-root-ca.pem \ –ca-key ../ca/client-root-ca-key.pem \ –config ./client-gencert.json \ ./demo-csr.json | cfssljson –bare ./demo得到文件:client-secrets/cert/├── demo-key.pem├── demo.csr└── demo.pem验证结果:openssl x509 -in ./demo.pem -text -nooutCertificate: Data: Version: 3 (0x2) Serial Number: 6e:50:e2:2c:02:bb:ef:fd:03:d9:2c:0a:8f:ba:90:65:fb:c4:b5:75 Signature Algorithm: sha256WithRSAEncryption Issuer: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=client-root-ca Validity Not Before: Mar 27 05:21:00 2019 GMT Not After : Mar 24 05:21:00 2029 GMT Subject: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=client-demo可以看到签发者是client-root-ca,Subject是client-demo。将证书导入keystore到 client-secrets/jks,执行下面命令生成pkcs12格式的keystore(JDK识别这个格式)openssl pkcs12 -export \ -in ../cert/demo.pem \ -inkey ../cert/demo-key.pem \ -out client-demo.keystore \ -name client-demo \ -CAfile ../ca/client-root-ca.pem \ -caname root -chain过程中会让你输入密码,你就输入:client-demo-ks。得到文件:client-secrets/jks/└── client-demo.keystore用JDK提供的keytool看看里面的内容:keytool -list -keystore client-demo.keystoreclient-demo, 2019-3-27, PrivateKeyEntry,证书指纹 (SHA1): 83:AE:0E:5E:0C:CE:86:C9:D1:84:D7:6F:87:F3:76:1F:B4:3E:46:31让你输入密码的时候就输入:client-demo-ks。两端互信好了,到此为止server和client的证书都已经生成了,接下来只需要将各自的root-ca添加到彼此都truststore中。把server-root-ca导入到client的truststore中cd client-secrets/jkskeytool -importcert \ -alias server-root-ca \ -storetype pkcs12 \ -keystore client.truststore \ -storepass client-ts \ -file ../../server-secrets/ca/server-root-ca.pem -noprompt注意上面的-storepass参数,这个是trustore的密码:client-ts。得到文件:client-secrets/jks/└── client.truststore用JDK提供的keytool看看里面的内容:keytool -list -keystore client.truststoreserver-root-ca, 2019-3-27, trustedCertEntry,证书指纹 (SHA1): 75:E3:78:97:85:B2:29:38:25:3C:FD:EC:68:97:9B:78:A0:5F:BB:9D让你输入密码的时候就输入:client-ts。把client-root-ca导入到server的truststore中cd server-secrets/jkskeytool -importcert \ -alias client-root-ca \ -storetype pkcs12 \ -keystore server.truststore \ -storepass server-ts \ -file ../../client-secrets/ca/client-root-ca.pem -noprompt注意上面的-storepass参数,这个是trustore的密码:server-ts。得到文件:server-secrets/jks/└── server.truststore用JDK提供的keytool看看里面的内容:keytool -list -keystore server.truststoreclient-root-ca, 2019-3-27, trustedCertEntry,证书指纹 (SHA1): 1E:95:2C:12:AA:7E:6D:E7:74:F1:83:C2:B8:73:6F:EE:57:FB:CA:46让你输入密码的时候就输入:server-ts。配置Tomcat好了,我们现在client和server都有了自己证书放在了自己的keystore中,而且把彼此的root-ca证书放到了自己的truststore里。现在我们弄一个tomcat作为server,然后为他配置SSL。修改tomcat/conf/server.xml,添加如下Connector:<Connector port=“8443” protocol=“org.apache.coyote.http11.Http11NioProtocol” maxThreads=“150” SSLEnabled=“true”> <SSLHostConfig certificateVerification=“required” truststoreFile="/path/to/server-secrets/jks/server.truststore" truststorePassword=“server-ts” truststoreType=“PKCS12”> <Certificate certificateKeyAlias=“server-demo” certificateKeystoreFile="/path/to/server-secrets/demo-jks/server-demo.keystore" certificateKeystoreType=“PKCS12” certificateKeystorePassword=“server-demo-ks” type=“RSA” /> </SSLHostConfig></Connector>可以看到我们开启了客户端认证certificateVerification=“required”,也开启了服务端认证<Certificate>。记得修改上面的keystore和truststore的路径。修改tomcat/conf/web.xml,添加如下元素:<security-constraint> <web-resource-collection> <web-resource-name>Automatic Forward to HTTPS/SSL</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint></security-constraint>这个作用是当访问8080端口时,都跳转到8443端口,强制走HTTPS。启动tomcat:tomcat/bin/catalina.sh run用curl测试好了,我们现在用curl来测试访问一下:curl https://localhost:8443/curl: (60) SSL certificate problem: self signed certificate in certificate chain…看到curl说服务端用的是一个自签发的证书,不可信,也就是说服务端认证失败。添加–insecure试试:curl –insecure https://localhost:8443/curl: (35) error:1401E412:SSL routines:CONNECT_CR_FINISHED:sslv3 alert bad certificate这里就说明客户端认证失败。所以如果要正确访问得像下面这样,指定server-root-ca证书,以及客户端自己签发的证书及private key:curl –cacert server-secrets/ca/server-root-ca.pem \ –key client-secrets/cert/demo-key.pem \ –cert client-secrets/cert/demo.pem \ https://localhost:8443/<!DOCTYPE html><html lang=“en”>…Httpclient测试我们现在用Httpclient来访问看看。pom.xml中添加依赖:<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.7</version></dependency>Java代码,记得把文件路径改掉:import org.apache.http.HttpEntity;import org.apache.http.HttpException;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.conn.ssl.SSLConnectionSocketFactory;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.ssl.SSLContexts;import org.apache.http.util.EntityUtils;import javax.net.ssl.SSLContext;import java.io.File;import java.io.IOException;public class Client { public static void main(String[] args) throws Exception { SSLContext sslcontext = SSLContexts.custom() .loadTrustMaterial( new File("/path/to/client-secrets/demo-jks/client.truststore"), “client-ts”.toCharArray() ) .loadKeyMaterial( new File("/path/to/client-secrets/demo-jks/client-demo.keystore"), “client-demo-ks”.toCharArray(), “client-demo-ks”.toCharArray()) .build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslcontext, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); CloseableHttpClient httpclient = HttpClients.custom() .setSSLSocketFactory(sslsf) .build(); HttpGet httpGet = new HttpGet(“https://localhost:8443”); CloseableHttpResponse response = httpclient.execute(httpGet); try { System.out.println(response.getStatusLine()); HttpEntity entity = response.getEntity(); System.out.println(EntityUtils.toString(entity)); } finally { response.close(); } }}安全性考虑所有private key都很重要!如果它被泄漏了,就要回收它所对应都证书。如果CA的private key泄漏了,那么用它签发的所有证书都要被回收。keystore和truststore的密码设置的要复杂一些。关于反向代理因为服务端认证所需要的证书直接配置在Tomcat上的,因此在做反向代理的时候不能使用SSL Termination模式,而是得使用SSL Passthrough模式。其他语言、SDK、工具上面讲的方法不是只适用于Tomcat和Httpclient的,TLS的服务端认证与客户端认证应该在绝大部分的语言、SDK、类库都有支持,请自行参阅文档实践。文中的keystore和truststore是Java特有的,不过不必迷惑,因为它们仅仅起到一个存放证书和private key的保险箱,有些语言或工具则是直接使用证书和private key,比如前面提到的curl。参考资料cfsslSSL/TLS Configuration HOW-TOSSL SupportCONFIGURING TOMCAT SSL CLIENT/SERVER AUTHENTICATION,这篇文章有点古老了,server.xml的配置方式已经不一样了,仅供参考。ClientCustomSSL.javaJSSE Reference Guide一些基础概念:Basics of Digital Certificates and Certificate Authority,基础概念,挺重要Create Your Own Certificate and CA,这篇文章挺重要的,主要讲了如何使用keytool和openssl来生成证书的过程Introducing TLS with Client AuthenticationThe magic of TLS, X509 and mutual authentication explained其他运用客户端认证的软件的相关文档,很有启发:Etcd - Play etcd TLS部分Etcd - Example 2: Client-to-server authentication with HTTPS client certificatesCoreos - Generate self-signed certificates ...

March 28, 2019 · 4 min · jiezi

使用SPIRE(自动)提供TLS证书给Envoy以进行更强大的身份验证

作者:Andrew Harding你好!这是来自Scytale的Andrew Harding。如果你目前正在使用Envoy提供安全的服务到服务通信,我想向你展示如何利用开源SPIRE项目,通过基于多个因子工作负载认证,自动交付和轮换密钥和证书来显着提高你的身份验证安全性。Envoy和SPIRE已经存在了一段时间,但我们最近才在SPIRE中增加了对Envoy SDS API的支持,这使得设置起来更加容易。我们来探讨一下。背景Envoy是一个流行的开源服务代理,除其他外,广泛用于在服务之间提供抽象、安全、经过身份验证和加密的通信。Envoy享有丰富的配置系统,允许灵活的第三方交互。该配置系统的一个组件是秘密发现服务协议或SDS(Secret Discovery Service)。Envoy使用SDS从SDS供应商处检索并维护更新的“秘密”。在身份验证的意思来说,这些秘密是Envoy用于在服务之间提供安全TLS通信的TLS证书、私钥和可信CA证书。短暂的秘密是安全的一个重要方面,因为它们减少了对撤销列表基础设施的需求,这削弱了安全性并导致攻击面增加。旋转短寿命秘密经常涉及手动审计和部署,并且通常对操作员来说非常麻烦。SDS供应商向Envoy提供更新秘密的能力,是简化秘密管理和为Envoy提供最新服务标识的有用步骤。SPIRE(SPIFFE运行时环境)是一个工具链,用于在各种平台上建立软件系统之间的信任。SPIRE支持容器化和弹性扩展环境,例如Kubernetes、托管基础架构如Azure、AWS和GCP,以及内部裸机部署。这些环境中的服务可以利用SPIRE以X.509证书(X509-SVID)的形式,获取具有关联私钥的服务标识,以及服务可用于验证其他身份的一组可信CA证书。当服务与SPIRE接合时,它会经历一个称为证明(attestation)的过程,其中SPIRE宣称(assert)有关服务及其环境的特征。这些宣称与运营商定义的政策相匹配,以决定应该为服务提供哪个服务标识。(有关证明的更多详细信息,请参阅此视频。)SPIRE根据运营商定义的政策自动轮换服务的X.509证书和密钥。换句话说,Envoy可以通过SDS动态消费服务标识,SPIRE可以动态提供服务标识。听起来很棒!这个怎样运作当Envoy连接到SDS服务器时,SPIRE代理会证明Envoy并确定它应该通过SDS向Envoy提供哪些服务身份和CA证书。随着服务标识和CA证书的轮换,更新将流式传输回Envoy,Envoy可立即将它们应用于新连接,而不会中断或停机,也无需私钥触及磁盘。换句话说,SPIRE丰富的定义和证明服务的方法可用于定位Envoy流程,为其定义身份,并为其提供Xv09证书和Envoy可用于TLS通信的信任信息。在两个服务之间的两个Envoy代理,使用SPIRE代理作为SDS的实现,以获取相互认证的TLS通信的秘密配置SPIRE在SPIRE中设置SDS支持就像在SPIRE代理配置中设置enable_sds = true配置值一样简单。配置EnvoySPIRE代理群集必须将Envoy配置为与SPIRE代理通信,通过配置集群指向SPIRE代理提供的Unix域套接字(domain socket)。例如:clusters: - name: spire_agent connect_timeout: 0.25s http2_protocol_options: {} hosts: - pipe: path: /tmp/agent.sockconnect_timeout会影响Envoy在启动Envoy时SPIRE代理未运行或者如果重启SPIRE代理时能够响应的速度。TLS证书要从SPIRE获取TLS证书和私钥,你可以在TLS上下文中设置SDS配置。例如:tls_context: common_tls_context: tls_certificate_sds_secret_configs: - name: “spiffe://example.org/backend” sds_config: api_config_source: api_type: GRPC grpc_services: envoy_grpc: cluster_name: spire_agentTLS证书的名称是Envoy充当代理服务的SPIFFE ID。验证上下文(Validation Context)Envoy使用可信CA证书来验证对等证书。验证上下文提供这些可信CA证书。SPIRE可以为每个信任域提供验证上下文。要获取信任域的验证上下文,可以在TLS上下文的SDS配置中配置验证上下文,将验证上下文的名称设置为信任域的SPIFFE ID。例如:tls_context: common_tls_context: validation_context_sds_secret_config: name: “spiffe://example.org” sds_config: api_config_source: api_type: GRPC grpc_services: envoy_grpc: cluster_name: spire_agentSPIFFE和SPIRE专注于促进安全认证作为授权的构建块,而不是授权本身,因此对验证上下文中的授权相关字段(例如verify_subject_alt_name)的支持超出范围。相反,我们建议你利用Envoy广泛的过滤器框架来执行授权。此外,你可以将Envoy配置为将客户端证书详细信息转发到目标服务,从而允许它执行自己的授权步骤,例如使用嵌入在客户端X.509 SVID的URI SAN中的SPIFFE ID。试试看!这就是你使用SPIRE改善服务到服务通信中的身份验证安全性的方法!尝试一下,让我们知道你的试用是怎么回事!你可以通过SPIFFE slack与我们联系。计划进行未来的改进,你的经验对于塑造SPIRE对Envoy的支持非常有价值。我要感谢Scytale公司自己的Marcos Yacob和Marcos Yedro,他们的努力有助于SPIRE SDS实施的原型设计和开发。KubeCon + CloudNativeCon和Open Source Summit大会日期:会议日程通告日期:2019 年 4 月 10 日会议活动举办日期:2019 年 6 月 24 至 26 日KubeCon + CloudNativeCon和Open Source Summit赞助方案KubeCon + CloudNativeCon和Open Source Summit多元化奖学金现正接受申请KubeCon + CloudNativeCon和Open Source Summit即将首次合体落地中国KubeCon + CloudNativeCon和Open Source Summit购票窗口,立即购票! ...

March 8, 2019 · 1 min · jiezi

SSL/TLS 握手协议概述

SSL/TLS 握手协议使客户端和服务端能够安全协商出同一份通信密钥,本文隐藏了一些细节上的内容,对这一握手过程进行了简要说明,如有错误还请指出SSL/TLS 握手协议(0) Client 与 Server 之前建立 (TCP) 连接(1) Client 向 Server 发送 “client hello” 消息,里面包含了安全相关的信息,例如 SSL/TLS 版本号,Client 支持的加密套件 (CipherSuite)。“client hello” 消息还包含了一个随机数client random,用于通信密钥的计算。SSL/TLS 协议还允许 “client hello” 消息包含 Client 所支持的压缩算法 (可选项)(2) Server 回复一条 “server hello” 消息,里面包含了加密套件 (Server 从 “client hello” 消息的 CipherSuites 列表中选择其中一个),session id 和 另一个随机数server random。Server 还会在消息中附带自己的数字证书。(可选) 如果 Server 需要 Client 的数字证书进行客户端认证,会向 Client 发送 “client certificate request” 请求消息,里面包含了 Server 所支持的证书类型和认可的证书颁发机构 CA(3) Client 收到 “server hello”,验证 Server 端的数字证书,并得到证书中 Server 端的公钥,读者可自行查阅更多数字证书的知识(4) Client 向 Server 发送第三个随机数pre-master secret。与之前不同,这次的随机数使用了 Server 的公钥加密 (非对称加密)。现在双方同时拥有这三个随机数client random,server random,premaster secret,可以用来计算生成共同的通信密钥 master secret 用于加密后面传输的业务数据。(5 - 可选) 如果收到 Server 端发来的 “client certificate request” 请求消息,Client 会向 Server 发送一个使用 Client 自己的私钥加密过的随机数 (暂时记作 secret-A),附带 Client 的数字证书。或者发送一个 “no digital certificate alert” 无证书警告,这种情况下基本可以认为 SSL/TLS 握手失败。(6 - 可选) Server 验证 Client 发送过来的数字证书,并得到证书中公钥对 Client 进行身份认证 (通过公钥解密上面那个 secret-A)。(7) Client 向 Server 发送 “finished” 消息,使用第 4 步中计算出来的密钥进行加密传输 (对称加密),这表示 Client 端握手阶段已经完成。(8) Server 也向 Client 发送 “finished” 消息,使用第 4 步中计算出来的密钥进行加密传输 (对称加密),这表示 Server 端握手阶段完成。(9) SSL/TLS 握手阶段完成,接下来双方通信的消息都会使用协商出来的密钥进行加密 (对称加密)Java 代码演示服务端 (全局 SSL 配置)public static void main(String[] args) throws IOException { System.setProperty(“javax.net.debug”, “SSL,handshake”); System.setProperty(“javax.net.ssl.keyStore”, “./keystore/TEST.p12”); System.setProperty(“javax.net.ssl.keyStorePassword”, “TEST”); SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); SSLServerSocket serverSocket = (SSLServerSocket) factory.createServerSocket(8001); // serverSocket.setNeedClientAuth(true); 需求客户端认证,可选 while (true) { try { SSLSocket socket = (SSLSocket) serverSocket.accept(); InputStream in = socket.getInputStream(); String message = IOUtils.toString(in); System.out.println(message); in.close(); socket.close(); } catch (Exception e) { e.printStackTrace(); } }}客户端public static void main(String[] args) throws UnknownHostException, IOException { System.setProperty(“javax.net.debug”, “SSL,handshake”); System.setProperty(“javax.net.ssl.trustStore”, “./keystore/TEST.p12”); System.setProperty(“javax.net.ssl.trustStorePassword”, “TEST”); SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); SSLSocket socket = (SSLSocket) factory.createSocket(“localhost”, 8001); socket.startHandshake(); OutputStream out = socket.getOutputStream(); out.write(“hello”.getBytes()); out.close(); socket.close();}因测试需要,Server 的数字证书是自签名的,而非权威的 CA 所颁发,于是客户端使用了全局的 TrustStore 配置,引入 Server 的数字证书,否则会有以下错误Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141) at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280) at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382) … 14 more 现在我们分别启动 Server 和 Client,并分析 SSL debug 日志Client Hello*** ClientHello, TLSv1.2RandomCookie: GMT: 1545722559 bytes = { 221, 47, 184, 101, 75, 18, 171, 225, 219, 236, 80, 229, 222, 114, 155, 14, 110, 144, 168, 163, 85, 252, 110, 180, 127, 37, 247, 50 }Session ID: {}Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]Compression Methods: { 0 }Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}Extension ec_point_formats, formats: [uncompressed]Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA首先是 Client 发起 SSL 握手,发送 “client hello” 消息ClientHello, TLSv1.2 得知 Client 支持的版本号RandomCookie,客户端生成的随机数 (client random),使用 4 个字节的当前时间加上 28 个随机字节Cipher Suites 列表,表示 Client 所支持的加密套件Server HelloServer 收到 “client hello”,即来自 Client 的握手请求,回复 “server hello” ServerHello, TLSv1.2RandomCookie: GMT: 1545722559 bytes = { 230, 234, 216, 95, 222, 185, 10, 245, 211, 122, 11, 47, 116, 109, 51, 164, 52, 92, 165, 72, 58, 222, 7, 19, 230, 32, 247, 99 }Session ID: {92, 34, 219, 191, 186, 218, 195, 78, 237, 222, 208, 62, 165, 14, 115, 106, 29, 243, 81, 152, 79, 45, 199, 0, 141, 231, 199, 100, 242, 152, 101, 13}Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256Compression Method: 0Extension renegotiation_info, renegotiated_connection: <empty>Cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 Certificate chainchain [0] = [[ Version: V3 Subject: CN=fwks, OU=ACL, O=ACL, L=ZHA, ST=ASIA, C=CN, EMAILADDRESS=ACL@GMAIL.COM Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11…………ServerHello, TLSv1.2,Server 使用的版本号RandomCookie,Server 生成的随机数 (server random),4 个字节的当前时间加上 28 个随机字节Session ID,凭借 session id,会话双方可以缓存并使用 SSL/TLS 握手阶段生成的密钥,而不需要再频繁地进行 SSL/TLS 握手Cipher suite,Server 从 “client hello” 的加密套件列表中选择的其中一个Certificate chain,是从 CA 到 Server 的数字证书链列表。因为这里是测试用的自签名证书,所以证书链中只有 Server 自己的数字证书Client 收到 “server hello” 后对 Server 的证书进行验证,成功后打出如下日志 (测试需要,Server 的自签名证书已经配置在 Client 的 TurstStore/TrustManager 中)Found trusted certificate:[[ Version: V3 Subject: CN=fwks, OU=ACL, O=ACL, L=ZHA, ST=ASIA, C=CN, EMAILADDRESS=ACL@GMAIL.COM Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11…………“server hello” 中还有一段消息 ServerKeyExchange,告诉 Client 使用的密钥交换算法是什么 (例中使用 ECDH 算法),即如何使用 client random, server random, premaster-secret 生成通信密钥 (不了解 ECDH,这里可能会有误)。*** ECDH ServerKeyExchangeSignature Algorithm SHA512withRSAServer key: Sun EC public key, 256 bits public x coord: 80178198866764561576110018839724135146035097258288090685496480316896017800231 public y coord: 21879990761153492368331320937448674839810402545614808541518903129245252068750 parameters: secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)ClientKeyExchangeClient 使用 Server 的公钥加密第三个随机数 pre-master secret,并发送给 Server。只有 Server 能使用自己的私钥解出这个 pre-master secret*** ECDHClientKeyExchangeECDH Public value: { 4, 159, 152, 225, 34, 111, 12, 18, 196, 101, 247, 201, 137, 231, 252, 89, 48, 157, 66, 201, 181, 25, 159, 10, 12, 202, 18, 190, 64, 58, 12, 220, 204, 49, 251, 95, 11, 40, 251, 46, 204, 69, 48, 238, 166, 116, 134, 140, 172, 186, 106, 85, 34, 105, 169, 185, 87, 101, 80, 133, 214, 130, 56, 132, 64 }main, WRITE: TLSv1.2 Handshake, length = 70现在通信双方都掌握了足够的信息去生成通信密钥 (master secret)SESSION KEYGEN:PreMaster Secret:0000: 03 01 84 54 F5 D6 EB F5 A8 08 BA FA 7A 22 61 2D …T……..z"a-0010: 75 DC 40 E8 98 F9 0E B2 87 80 B8 1A 8F 68 25 B8 u.@……….h%.0020: 51 D0 54 45 61 8A 50 C9 BB 0E 39 53 45 78 BE 79 Q.TEa.P…9SEx.yCONNECTION KEYGEN:Client Nonce:0000: 40 FC 30 AE 2D 63 84 BB C5 4B 27 FD 58 21 CA 90 @.0.-c…K’.X!..0010: 05 F6 A7 7B 37 BB 72 E1 FC 1D 1B 6A F5 1C C8 9F ….7.r….j….Server Nonce:0000: 40 FC 31 10 79 AB 17 66 FA 8B 3F AA FD 5E 48 23 @.1.y..f..?..^H#0010: FA 90 31 D8 3C B9 A3 2C 8C F5 E9 81 9B A2 63 6C ..1.<..,……clClient Nonce,就是第一个随机数 client randomServer Nonce,就是第二个随机数 server randomPreMaster Secret,第三个随机数生成的通信密钥如下。除了 Master Secret 的其他几个,笔者也不是特别了解Master Secret:0000: 2C 31 A6 EC A7 75 D0 DC E9 3E 23 1D B4 B7 50 87 ,1…u…>#…P.0010: 48 41 18 7D 29 D4 DB 8A 7D A5 F3 D5 15 08 A4 50 HA..)……….P0020: 5A 4A 50 7D 08 C3 E5 A5 CB ED 4C 40 80 C3 B8 B2 ZJP…….L@….Client MAC write Secret:0000: 1C C1 5F 82 CB CD AB 6B 77 C7 7B D8 66 48 6F A4 ..….kw…fHo.0010: C2 30 59 4D 91 1A 36 82 A4 C2 EF 9B 42 B5 98 7F .0YM..6…..B…Server MAC write Secret:0000: 7D D6 D2 3C 6F 61 AE 15 1F 62 46 4E A5 68 59 66 …<oa…bFN.hYf0010: 72 50 81 0D 12 07 41 B4 8E 83 1F 5D EF 85 D0 12 rP….A….]….Client write key:0000: B0 50 53 C9 FF 10 4E 71 0B 5F 29 63 9C 47 82 77 .PS…Nq.)c.G.wServer write key:0000: 65 67 22 93 A2 45 74 18 D0 F7 B9 F2 78 19 61 07 eg"..Et…..x.a.Finish 消息现在通信双方都计算同一份密钥 Master Secret,可以用于加密并发送 finish 消息了。但在此之前 Client 还会发送了一条 “Change Cipher Spec”,用于告诉对方接下来的通信使用新的密钥加密消息。SSL 日志也会打出下面这一条:main, WRITE: TLSv1.2 Change Cipher Spec, length = 1接下来才是使用新密钥加密发送 finish 消息*** Finishedverify_data: { 5, 73, 52, 104, 95, 23, 44, 252, 228, 173, 15, 129 }main, WRITE: TLSv1.2 Handshake, length = 80Server 收到来自 Client 的 “Change Cipher Spec” 和 “finish” 消息后,也会向 Client 发送 “Change Cipher Spec” 和 “finish” 消息main, READ: TLSv1.2 Change Cipher Spec, length = 1main, READ: TLSv1.2 Handshake, length = 80 Finishedverify_data: { 5, 73, 52, 104, 95, 23, 44, 252, 228, 173, 15, 129 }main, WRITE: TLSv1.2 Change Cipher Spec, length = 1 Finishedverify_data: { 169, 120, 73, 97, 72, 13, 37, 157, 77, 249, 0, 7 }***main, WRITE: TLSv1.2 Handshake, length = 80至此,SSL/TLS 握手阶段完成,通信双方使用新协商的密钥加/解密业务数据main, READ: TLSv1.2 Application Data, length = 64hello关于 HTTPS到这是否豁然开朗了?HTTPS 就是 HTTP over SSL/TLS,同样先进行 SSL/TLS 握手协商通信密钥,再使用通信密钥加密 HTTP 请求/响应报文。如果你在浏览器输入 https://localhost:8001/ 访问上面的 SSL Server,浏览器会给出如下警告浏览器在验证 Server 证书的时候已经失败了,原因是:证书不可信,因为它是自签名的 (The certificate is not trusted because it is self-signed)证书的内容和域名 “localhost” 不匹配 (The certificate is not valid for the name localhost)附录A:加密套件 CipherSuite加密算法套件是一组密码算法的集合,SSL/TLS 通信过程会使用到这一组算法,他们包括密钥交换算法 (key exchange algorithm),主要有 RSA, DH, ECDH, ECDHE认证算法,规定服务端认证和客户端认证 (可选) 使用的算法,主要有 RSA, DSA, ECDSA 这一类非对称加密算法数据加密算法,规定在实际的数据传输中使用的对称加密算法,有 AES, DES, 3DES 这一类对称加密算法消息验证算法 (MAC algorithm),规定数据完整性验证算法 (验证数据在传输中是否受到噪声干扰和其它非人为的破坏),SHA, MD5 这一类散列算法可作为 MAC分割线上方的算法在 SSL/TLS 握手阶段使用,下方两类算法在实际数据传输时使用到回顾之前测试中使用到的加密套件Cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256TLS: 协议名字ECDHE: 密钥交换算法RSA: 认证算法 (RSA 非对称加密算法)WITH: 分割线AES_128_CBC: 数据加密算法 (AES 对称加密算法)SHA256: MAC 算法 (SHA 散列算法/哈希算法) ...

December 26, 2018 · 6 min · jiezi