wireshark抓取https包
背景
在自己的路由器上实现了自己签名的证书,可以搭建https的网站了.
但是还想用wireshark来具体看看效果.
方法总结
SSL握手过程中,客户端依靠服务器的公钥,服务器依靠自己的私钥,
会协商一个通信用的对称加密密钥,
想要明文查看https包,就需要提前将一些信息提供给wireshark,
然后让wireshark也监听到对称加密的密钥.
因此目前,网络上主要有两种方法
- 直接将服务器的私钥交给wireshark(即使可行也只适合自己搭建的网站)
- 将浏览器保存的sslkeylog交给wireshark
而wireshark官方也更倾向于推荐第二种方法.
私钥法
找来服务器的私钥,比如 server.key
.
在wireshark的设置(编辑->首选项->RSA密钥)中,添加新的私钥即可.
目前的问题
传统的协商一个对称密钥的方式其实有缺点,如果保存了所有数据包,
日后一旦获得私钥,那么数据就不再安全.
为了解决这个前向安全的问题,
有人提出服务器的私钥暂时只用来做身份认证,
协商对称密钥时用一个临时的数据,
即使服务器的私钥泄露也不会有数据安全的问题.
目前这种实践方式非常普遍,nginx默认也使用这种更加安全的方式.
因此即使将私钥交给wireshark,在默认的配置下也毫无用处.
如果更改了nginx的配置使用了较为不安全的key exchange方法,
网站本身会不安全,并且浏览器也会嫌弃等级太低而拒绝打开.
log法
-
配置sslkeylog
1
2
3
4
51. 配置环境变量
export SSLKEYLOGFILE=$HOME/sslkeylog.log
2. 为了让浏览器能够继承环境变量,在shell中启动之
chromium https://example.org
3. 在文件中会生成内容 -
配置wireshark
编辑->首选项->Protocols->TLS
在(Pre)-Master-Secret log filename处设置刚才的log文件
为了应对可能的问题,一并指定TLS debug file的路径. -
重新在shell中启动浏览器访问网站,即可抓包
- sslkeylog文件是会变动的,即使有了内容,也不能利用shell外部打开的浏览器来抓包
- 即使是通过shell打开浏览器也应确认在这之前该浏览器没有被打开
RSA,DH,DHE,ECDHE等
本身都是为了交换对称密钥时的一种方法.
RSA
C端使用S的公钥将预主密钥a加密并发送给S.(C发送一个Client key exchange报文)
S端使用S的私钥将预主密钥a解密.
问题:如果私钥泄露,就不再安全,成为前向(未来的某一天)不安全.
DHE
C端生成一个值Xa,却把q^Xa^ mod p的结果(起名Pa)发给S.(C发送Client key exchange)
S端生成一个值Xb,却也吧q^Xb^ mod p的结果(其名Pb)发给C.(S发送Server key exchange)
C端计算Sa=Pb^Xa^ mod p,S端计算Sb=Pa^Xb^ mod p,神奇的数学证明了Sa=Sb=a
优点:每条会话都有临时的Xa,Xb,一条会话被解密,其他会话还安全.
问题:计算量太过庞大,甚至比RSA还费事,耗费CPU是小事,网站卡顿是大事
ECDHE
不再使用大数的Xa^p^,转而使用一种性能更好的 椭圆曲线 的算法.
问题:由于比较新,暂时没有太多实践来验证与DHE有同等的安全能力
ECDH
E本身代表临时,
C端使用随机数Xa,计算成Pa发送给S端,(C发送一个Client key exchange报文)
S端省事直接使用公钥中作为Pb,自己的私钥作为Xb(S已经在certificate报文中发送过,不必)
C端计算Sa=f(Pb,Xa),S端计算Sb=f(Pa,Xb).
问题:由于需要直接将公钥作为Pb,公钥只能包含在ECC证书中.另外也依然有RSA泄露后就不再安全的问题.
nginx的配置
nginx可以配置的是 ssl_ciphers
字段,该字段翻译作加密套件,其实是众多过程中加密方法的组合.
使用
1 | openssl ciphers -V |column -t |
可以看到一些可用的加密套件
Kx = Key Exchange
Au = Authentication
Enc = Encrypt
Mac = Message Authentication Code
然而目前TLSv1.2的协议中,Kx=RSA的算法,浏览器认为安全性太差.
其他一些Kx=DH/RSA的拳法,浏览器有的还不支持.
因此修改 ssl_ciphers
字段并非一个好主意.不指定该字段以使用默认值就好.