TLS原理与实践
原文来自:https://www.cnblogs.com/informatics/p/17433116.html
背景
我们在访问网站的时候经常会碰到以下两种情况:
-
网站1:
-
网站2:
从图中可以看到:网站1地址前面显示不安全
字样,网站2前面显示🔐
的字样,这两种网站本质区别在于有没有使用TLS协议
进行通信保护。
浏览器正是通过这种方式提醒用户访问的网站是否安全
,通信消息是否会被窃听。
注:上图使用的浏览器为chrome浏览器
,其他浏览器可能稍有差别。
发展历程
TLS协议:(Transport Layer Security)是用来保证网络通信安全
的密码学协议
。被广泛应用在电子邮件、即时通信、VoIP以及HTTPS协议中,其中HTTPS
最为常见。TLS协议能够保证通信消息的隐私性、消息完整性以及通信实体的身份鉴别
TLS协议(前身SSL)从1986左右开始,经过了多个版本的发展(以下图片来自维基百科):
- SSL协议作为TLS的前身,由于存在诸多安全漏洞,已经在2015全部被废弃.
- TLS协议也经过了多个版本的迭代,其中TLS1.0和TLS1.1由于在协议中使用了MD5、SHA-1等因素,在2021年相继被废弃
- TLS1.2解决了之前版本的安全问题。已成为使用最广泛的TLS协议,据统计99%以上的网站支持了TLS1.2
- TLS1.3移除了不安全的密码算法,并在
密码算法支持
和握手效率
上等方面进行了显著优化。
协议原理
网络通信模型
在介绍TLS协议原理前,我们首先了解下,网络安全通信模型
:
-
无TLS协议保护
-
有TLS协议保护
从上图中我们可以看到,在网络通信过程中,如果未使用tls保护,会存在通信消息被窃听
、篡改
的风险,同时攻击者可以伪造身份
进行通信;而使用了TLS协议,能够保证消息的隐私性
、完整性
和通信实体身份实体的真实性
。
注:在访问网站的场景中,这里的Alice
、Bob
和Eve
可以理解为浏览器
、Web网站
和网络攻击者
TLS协议原理
TLS协议包含多个子协议
:
- 应用数据协议(
Application Data Protocol
): 用于密文传输 - 告警协议(
Alert Protocol
):在TLS连接中,如果发生了错误或异常情况,TLS协议会使用Alert Protocol发送警报信息,以通知对方发生了什么问题。 - 握手协议(
Handshake Protocol
):用于密钥协商 - 更改密码规范协议(
Change Cipher Spec Protocol
): 在TLS连接中通知对方加密算法已经切换 - 记录协议(
Record Protocol
): 在TLS连接中对数据进行分段、压缩、加密和认证。上面4个子协议的数据都会通过Record Protocol进行处理,然后再通过网络传输。
TLS握手协议
,握手流程如下:
TLS握手过程中客户端和服务端会进行多轮交互
,交互过程中会发送握手协议包
(下文描述中我们称为xx消息
)
上图中标*
的部分根据场景为可选
,如:
- 在
双向认证
中,server发送CertificateRequest
消息, 客户端响应Certificate
消息和CertificateVerify
消息(服务端使用这两个消息验证客户端身份) - 在
会话恢复
(非首次建立TLS链接)中,图中标*
的消息不参与握手流程 - 标
[]
的ChangeCipherSpec
协议不属于握手协议,而是Change Cipher Spec Protocol
子协议。
wireshark抓包解析
下面我们以服务器单向认证
为例, 并结合wireshark抓包,分析TLS握手协议详细流程:
TLS协议流程
。
从图一抓包结果我们可以了解到:
- 使用的TLS版本为TLSv1.2
- 握手过程中的关键字有:
- Client Hello
- Server Hello
- Certificate, Server Key Exchange, Server Hello Done
- Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message
- New Session Ticket, Change Cipher Spec, Encrypted Handshake Message
- Application Data
- 握手协议消息类型为
Client Hello
- 客户端支持的TLS版本为
TLS 1.2 (0x0303)
, 其中0x0303
为内部版本号,如TLS1.3为0x0304
。 - 客户端生成的32字节
随机数
- 客户端支持的
加密套件
,优先级从上到下。
从上图可以看到:
- 握手协议消息类型为
Server Hello
- 服务端确定的TLS版本为
TLS 1.2
- 服务端生成的32字节
随机数
- 服务端确定的
加密套件
为TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
,该加密套件各字段用途如下:
从上图可以了解到,本次通信tcp包携带了3个tls握手协议包:
- Certificate消息: 这边我是用curl的=== 所以没有博主的。。。
- 1.1服务端证书,
id-at-commonName=*.pku.edu.cn"
表示为北京大学服务器网站 - 1.2证书链,该证书链包含根证书
id-at-commonName=DigiCert Global Root CA
, 该根CA为知名签发机构(隶属于美国) - Server Key Exchange消息:
- 2.1 服务端DH参数,参与生成主密钥
- 2.2 服务端签名,用于验证消息有效性
- Server Hello Done消息:通知客户端加密套件协商结束
从上图可以了解到,本次通信tcp包携带了3个tls协议包:
- New Session Ticket消息: 服务器在TLS握手过程中生成一个新的会话票据(Session Ticket),并将其发送给客户端。客户端可以在后续的TLS握手中使用该会话票据来恢复之前的会话状态,从而避免了重新进行完整的TLS握手流程,提高了握手的效率和安全性。
- Change Cipher Spec消息:通知客户端,服务端已准备好进行密文通信
- Encrypted Handshake Message消息:同Finished消息(密文形式)
从上图可以看到:
- 该消息不属于TLS握手协议,属于
Application Data Protocol
,是TLS协议的另一个子协议。 - Encrypted Application Data: 所有应用数据都被加密传输。
结论
本文主要介绍了TLS协议发展历程、TLS握手流程等,并结合wireshark对TLS1.2服务端单项认证进行了详细的抓包分析。
TLS协议
在网络安全通信中具有重要应用,可以说网络安全
离不开TLS协议的支持,理解TLS协议原理对于建设安全网站
,编写安全网络程序
以及防止数据泄露
等方面具有重要意义。
TLS协议广泛应用于互联网中,以便保护通信实体信息交换的安全性。 TLS在网络协议
中的位置:
TLS协议工作在传输层
和应用层
之间,从上图中我们也可以了解到。TLS协议一种常见的应用就是:
HTTPS = HTTP + TLS #用于保护http请求和响应的数据安全性
此外,在gRPC中的应用,我们称之为gRPCs
HTTPS网路通信抓包分析
下面我们通过示例代码
和wireshark抓包分析
来展示tls协议是如何保护http数据安全性的。
在以下示例中,涉及到的工具有:
- tcpdump: 网络抓包软件,官网: http://www.tcpdump.org
- wireshark: 网络抓包和分析软件,官网: https://www.wireshark.org
- practical-crypto: 用于模拟https服务和客户端,github仓库 https://github.com/warm3snow/practical-crypto.git
practical-crypto介绍
# 下载示例代码
➜ practical-crypto git:(master) git clone https://github.com/warm3snow/practical-crypto.git
# 查看示例代码目录结构
➜ practical-crypto git:(master) tree tls
tls
├── gmtls #国密tls示例
├── notls #无tls保护http服务
│ └── notls.go
├── readme.md #帮助文档
├── tls1.2 # 使用tls1.2协议的http服务
│ └── tls1_2.go
├── tls1.3 # 使用tls1.3协议的http服务
│ └── tls1.3.go
└── tlsclient.go # http客户端,可以发起http或https请求
这里我没有跟着博主操作
抓包软件启动
# 使用tcpdump进行抓包
# -i 指定网卡, lo0是本地回环网卡
# -w 指定输出文件
# port 指定端口, 以下端口号为8443对应我们http服务的监听端口
➜ sudo tcpdump -i lo0 -w capture.pcap port 8443
服务端启动
以启动tls1.2的https服务
为例,如下:
# 切换到对应目录下
➜ cd tls/tls1.2
# 启动https服务
➜ go run tls1_2.go
客户端
以运行tls1.2的https客户端
发送请求为例,如下:
# 切换到客户端目录下
➜ cd tls
# 编译客户端程序
➜ go build -o tlsclient tlsclient.go
# 查看客户端help文档
➜ ./tlsclient -h
Usage of ./tlsclient:
-addr string
addr (default "https://localhost:8443")
-skipVerify
skipVerify (default true)
-tlsVersion string
specified tls version (default "1.2")
# 通过客户端发送tls1.2请求
➜ tlsClient -addr https://localhost:8443 -tlsVersion 1.2 -skipVerify true
无TLS的HTTP网络通信
捕获网络数据
首先我们看下在没有tls保护的情况下,http请求数据是如何在网络上传递的。打开三个命令行终端
,分别运行:
- 抓包软件
- http服务端,程序位置
tls/notls/notls.go
- http客户端, 程序位置
tls/tlsclient.go
其中,在抓包过程中需要注意:
- tcpdump不会自动结束,当客户端返回成功后,需要使用
ctrl + c
来强制终止 - tcpdump会将抓包的数据存储到xxx.pcap文件中,图中,我们制定了
capture.pcap
文件
wireshark分析
下面我们打开wirshark网络协议分析工具,并将得到的capture.pcap文件拖入wireshark:
分析结果:HOLY SHIT !!!
, 从图中我们可以清晰的看到服务端返回的Hello, world!
消息,数据以明文形式
在网络上裸奔。
使用TLS1.2的HTTPS网络通信
捕获网络数据
我们接着看下在有tls保护的情况下,http请求数据是如何传递的。同样打开三个命令行终端
并运行相关程序:
- 抓包软件
- http服务端,程序位置
tls/tls1.2/tls_12.go
- http客户端, 程序位置
tls/tlsclient.go
运行程序需要注意:
- tcpdump的运行和终止无变化,与上文相同
- 运行客户端时,addr参数指定的地址需要使用https协议,tlsVersion需要指定为
1.2
(代表此次握手使用了tls1.2协议)
wireshark分析
同样我们将刚才tcpdump捕获的数据导入wireshark:
分析结果
从图中我们可以看到:
- 客户端和服务端进行了完整的tls1.2握手流程
- 客户端的请求以密文形式发送(包括请求体和请求头)
- 服务端相应的数据以密文形式返回
结论
本文我们通过实际的例子,来对比分析了访问http和https服务的网络通信数据保护,通过分析结果我们可以看到访问http服务
时,数据以明文
形式传输,无安全性可言; 而采用了https
的服务,在对外提供服务时,数据以密文
形式传输,保证了通信数据的隐私性。
在实际应用中,我们应尽量使用https服务,降低数据泄漏的风险。
引言
tls1.2作为主流的网路安全协议,被广泛应用,但tls1.2仍存在一些安全隐患和性能问题,如:
- MD5、SHA-1算法已被破解,不再安全
- RSA密钥协商存在安全隐患,不支持前向安全
- 加密模式CBC存在Padding Oracle攻击的潜在风险
- tls1.2在进行密钥协商时,需要
2-RTT
,效率较低等
注:RTT = Round Trip Time,表示交互次数。
为了解决tls1.2存在的问题,tls1.3
协议应运而生,tls1.3废弃
了一些存在安全隐患的加密套件,并新增了一些安全级别较高
的加密套件。同时在性能上,TLS1.3能够实现1-RTT
密钥协商,以及0-RTT
连接恢复(tls1.2连接恢复需要1-RTT
),握手效率提升了1倍左右。
引言
tls1.2作为主流的网路安全协议,被广泛应用,但tls1.2仍存在一些安全隐患和性能问题,如:
- MD5、SHA-1算法已被破解,不再安全
- RSA密钥协商存在安全隐患,不支持前向安全
- 加密模式CBC存在Padding Oracle攻击的潜在风险
- tls1.2在进行密钥协商时,需要
2-RTT
,效率较低等
注:RTT = Round Trip Time,表示交互次数。
为了解决tls1.2存在的问题,tls1.3
协议应运而生,tls1.3废弃
了一些存在安全隐患的加密套件,并新增了一些安全级别较高
的加密套件。同时在性能上,TLS1.3能够实现1-RTT
密钥协商,以及0-RTT
连接恢复(tls1.2连接恢复需要1-RTT
),握手效率提升了1倍左右。
本文的主要内容
组织如下:
- TLS1.3加密套件介绍
- TLS1.3握手协议
- TLS1.3协议wireshark抓包分析
TLS1.3协议
TLS1.3加密套件
TLS1.3支持的加密套件如下:
- TLS_AES_128_GCM_SHA256
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
从加密套件上看,与tls1.2相比(如:tls_ecdhe_ecdsa_with_aes_128_gcm_sha256
), tls1.3协议支持的加密套件不再包含密钥协商算法
和签名算法
,仅包含加密和摘要算法,这是因为在TLS 1.3中:
- 所有密钥协商默认使用
ECDHE算法
,这意味着在握手过程中,客户端和服务器都使用椭圆曲线密钥协商
来生成共享的对称密钥。椭圆曲线Diffie-Hellman密钥交换提供了强大的安全性
和前向保密性
,可以抵抗主动攻击和被动监听。 - TLS1.3
允许
客户端和服务器选择适当的签名算法
,以实现身份验证和握手完整性的保护。这种灵活性
和可扩展性
是TLS 1.3设计的一部分,以提供更安全和可靠的通信。 - TLS1.3仅支持AEAD带认证的加密算法,不再支持CBC模式的加密算法,提高了加密数据的安全性
注:需要注意的是,尽管TLS1.3
默认使用ECDHE
作为密钥协商算法,但仍然可以通过配置选择
其他密钥交换算法,如基于RSA的密钥交换(RSA Key Exchange)。然而,在TLS 1.3中,推荐使用ECDHE来获得更高的安全性和性能。
TLS1.3握手协议
TLS1.3协议握手流程如下 (来源 rfc8446)
注:
+
表示在先前提到的消息中发送的值得注意的扩展。*
表示可选或情境依赖的消息/扩展,不一定总是发送。{}
表示使用从 [sender]_handshake_traffic_secret 导出的密钥保护的消息。[]
表示使用从 [sender]_application_traffic_secret_N 导出的密钥保护的消息。
从上图可以看到,握手可以看作有三个阶段(如上图所示):
- 密钥交换(Key Exchange):建立共享的密钥材料并
选择加密参数
。此阶段之后的所有内容都是加密的。 - 服务器参数(Server Parameters):
建立其他握手参数
(如客户端是否经过身份验证、应用层协议支持等)。 - 身份验证(Authentication):对服务器(以及可选地对客户端)进行
身份验证
,并提供密钥确认
和握手完整性
。
密钥交换(Key Exchange)
在密钥交换
阶段,客户端发送ClientHello消息,其中包含:
- 随机的nonce(ClientHello.random);
- 所提供的协议版本;
- 一组对称密码算法/HKDF哈希对;
- Diffie-Hellman共享密钥(在"key_share"扩展中)、预共享密钥标签集合(在"pre_shared_key"扩展中), 或两者都有;
- 可能的其他扩展。
服务器处理ClientHello并确定适当的加密参数。然后通过ServerHello响应,指示协商的连接参数。ClientHello和ServerHello的组合确定了共享密钥。
- 如果使用了(EC)DHE密钥协商,则ServerHello包含服务器临时生成DH公钥的
key_share
扩展。 - 如果使用PSK密钥协商,则ServerHello包含一个
pre_shared_key
扩展,指示选择了客户端提供的PSK中的哪一个。 - 请注意,实现可以同时使用(EC)DHE和PSK,在这种情况下ServerHello将提供两个扩展。
服务器参数(Sever Parameters)
然后,服务器发送两个消息以建立服务器参数:
- EncryptedExtensions:对于不需要确定密码参数的ClientHello扩展的响应。
- CertificateRequest:如果需要客户端身份证书验证,则为该证书的所需参数。如果不需要客户端身份验证,则省略此消息。
身份验证(Authentication)
最后,客户端和服务器交换身份验证消息。具体来说:
- Certificate:
服务端证书
和证书相关的扩展。如果不使用证书进行身份验证,则服务器会省略此消息;如果使用原始公钥[RFC7250]或缓存的信息扩展[RFC7924],则此消息将不包含证书,而是包含与服务器的长期密钥对应的其他信息。 - CertificateVerify:使用Certificate消息中公钥对应的私钥对整个
握手消息
进行签名
。如果不通过证书进行身份验证,则省略此消息。 - Finished:对应整个握手的
消息认证码MAC
。此消息提供密钥确认,将客户端/服务端的身份与交换的密钥绑定,并在PSK模式下还进行握手身份验证。
收到服务器的消息后,客户端通过其身份验证消息(即Certificate和CertificateVerify(如果有请求)和Finished)做出响应。
此时,握手过程完成,客户端和服务器生成了记录层所需的密钥材料
,以通过加密来交换应用层数据。在发送Finished消息之前,不得发送应用数据。
TLS1.3协议wireshark抓包分析
在TLS原理与实践(二) 中,我们使用tcpdump
对TLS1.2协议
的demo程序进行了抓包,并使用wireshark
进行了分析。 我们使用同样的方法,对TLS1.3进行抓包分析,(注:在我们的demo程序中,仅模拟了服务器单项认证的场景), 抓包过程如下:
说明:
- 启动抓包程序:我们使用tcpdump进行抓包
- 启动tls服务:该demo程序服务端仅支持TLS1.3协议
- 启动tls客户端:该demo程序客户端支持多种版本TLS协议,我们通过
tlsVersion 1.3
指定仅使用TLS1.3 - 结束抓包程序:当客户端控制台打印
hello world
时,表明握手和传输应用数据完成。我们通过ctrl + c
手动关闭tcpdump抓包程序,抓包程序会将捕获的网络数据保存到capture.pcap
文件中。
下面我们将capture.pcap
导入或拖入wireshark
程序,对TLS1.3协议进行分析:
概览页
从概览图中我们可以看到,TLS1.3握手协议8个记录被封装到3个tcp协议包中完成:
- Client Hello
- Server Hello,Change Cipher Spec, Application Data,Application Data,Application Data,Application Data
- Change Cipher Spec, Application Data
说明:
- Change Cipher Spec这个记录用于较早版本TLS中,在TLS1.3不再需要。在
中间盒兼容模式
中,发送这个记录可以帮助伪装会话为TLS 1.2会话。 - 在第2个协议包中包含4个
Application Data
实质代表的是被加密的握手协议记录
,分别对应EncryptedExtensions
,Certificate
,CertificateVerify
和Finished
- 在第3个协议中包含的
Application Data
实质为应用层数据,这里代表客户端请求的数据(密文形式)
“中间盒兼容模式”: 在TLS 1.3中,引入了"中间盒兼容模式"(middlebox compatibility mode)的概念,这是为了解决某些网络中存在的中间设备(如防火墙、代理服务器等)可能不支持或不理解TLS 1.3协议的情况。由于TLS 1.3在协议设计和加密套件选择方面与TLS 1.2有很大的差异,一些网络设备可能无法正确解析或处理TLS 1.3的通信。为了绕过这些设备的限制,TLS 1.3引入了中间盒兼容模式。在中间盒兼容模式下,TLS 1.3的客户端会发送一个伪装为TLS 1.2的记录(record)。这个伪装的记录可以欺骗中间设备,使其认为通信是基于TLS 1.2协议进行的,从而绕过了对TLS 1.3的限制。需要注意的是,中间盒兼容模式只是一种临时解决方案,旨在帮助过渡期内的网络设备与TLS 1.3兼容。随着时间的推移,网络设备应该升级并支持TLS 1.3以享受其更强大的安全性和性能优势。
Client Hello消息
消息发送:客户端 -> 服务端
我们按照图中的序号进行分析:
- 表明该握手协议发送的为Client Hello消息
- 伪装的TLS协议版本,在TLS1.3
中间盒兼容模式
中,此处的版本号仅用于兼容TLS1.2模式,用于欺骗中间设备,绕过对TLS1.3协议的限制(这里的中间设备目前支持的最高TLS版本为TLS1.2) - 客户端随机数,tls1.3协议Client Hello中的Random作用与TLS1.2相同,充当随机数种子
- 支持的加密套件。从图中可以看出客户端支持的加密套件(Cipher Suites)列表一共有19个。
- TLS1.3协议支持的加密套件。TLS1.3废弃了不安全或存在安全隐患的加密套件(16个),新增了3个更加安全的加密套件(本文开头已介绍,不在赘述)
在TLS1.3中,扩展字段发挥了重要作用,Client Hello消息包含的主要扩展字段(如上图) 有:
- 客户端支持的椭圆曲线算法
Supported Groups
列表,这里的EC算法主要用于密钥协商,按照优先级排列 - 客户端支持的签名算法
signature_algorithms
列表,用于身份认证 - 客户端支持的TLS版本,这里的版本为实际支持的TLS版本,由于我们在demo里,通过tlsVersion设置了TLS协议版本为
1.3
,所以这里显示客户端支持的TLS版本列表为TLS1.3
- 客户端选用的椭圆曲线算法,客户端使用了
x25519
椭圆曲线算法来生成了预备主密钥
的客户端部分。
Server Hello消息
消息发送: 服务端 -> 客户端
Server Hello消息与Change Cipher Spec, Application Data,Application Data,Application Data,Application Data消息在同一个TCP包中发送。
基于上图,我们按照序号分析:
- 表明发送的握手协议包为
ServerHello消息
(伴随了其他握手消息的密文,在同一个TCP包中发送) - 服务端随机数,tls1.3协议Server Hello中的Random作用与TLS1.2相同,用作随机数种子
- 协商的加密套件,从上图中我们可以看到,客户端/服务端最终协商使用的加密套件为
TLS_AES_128_GCM_SHA256
- 协商的tls协议版本,为TLS1.3
- 协商使用的
密钥协商
用到的椭圆曲线算法,从图中可以看到为x25519
,这也是Client Hello中客户端优先选用的算法。在Key Exchange
字段携带了服务端生成的共享密钥 - 此消息
Change Cipher Spec
在TLS1.3中不使用,仅用于兼容(本文前言部分已介绍,不在赘述) - Application Data消息一共有4个,这里为密文形式,从这里我们可以了解到,与TLS1.2相比,TLS1.3提供了更强大的保密能力。 这里被加密的消息,与TLS1.2中的消息类似,主要用于客户端/服务端身份验证,不在赘述。
Change Cipher Spec
消息发送: 客户端 -> 服务端
Change Cipher Spec消息Application Data消息在同一个TCP包中发送。
说明:
- Change Cipher Spec消息:略
- Application Data: 客户端请求数据的密文形式
结论
本文详细介绍了TLS1.3协议的握手流程,通过wireshark抓包分析,我们可以看到与TLS1.2相比,TLS1.3在握手效率、消息保密性上具有更大的优势。应用系统接入TLS1.3也将是一种未来趋势。