3、HTTP与HTTPS:从明文到加密的蜕变
说实话,我刚入行那会儿,对HTTPS的理解也就停留在「比HTTP安全」这个层面。直到有一次,我在一个咖啡厅做渗透测试,用Wireshark抓了个包——好家伙,隔壁桌小哥的登录密码、银行卡号,全在HTTP请求里躺着呢。那一刻我才真正意识到,HTTP就是裸奔,HTTPS才是穿了防弹衣。
这一章,咱们就把HTTPS的加密过程、HSTS策略、中间人攻击和证书固定这几个核心话题聊透。你想想看,每天几十亿次HTTPS握手,背后到底发生了什么?
3.1 HTTPS加密过程:一次完整的握手
HTTPS的核心,说白了就是HTTP + TLS(传输层安全协议)。TLS负责加密,HTTP负责传输。我习惯把TLS握手分成四个阶段来讲:
- TCP三次握手:客户端和服务器先建立TCP连接。
- 证书验证:服务器把数字证书发给客户端,客户端验证证书的合法性。
- 密钥交换:双方协商出一个对称加密密钥,用于后续数据传输。
- 加密通信:用协商好的密钥加密HTTP数据。
嗯,这里要注意,TLS 1.3相比1.2,把握手从2-RTT优化到了1-RTT,甚至0-RTT。我去年帮一家电商平台做性能优化,光是把TLS 1.2升级到1.3,首屏加载时间就降了30%。
核心要点:HTTPS不是「HTTP + SSL」这么简单。它涉及证书链验证、非对称加密交换密钥、对称加密传输数据,每一步都有安全考量。
咱们用一张图来理解整个流程:
3.2 数字证书与CA体系
你可能会问:客户端怎么知道服务器发来的证书是真的?这就涉及到CA(证书颁发机构)体系了。
我个人的理解是,CA就像数字世界的「公安局」。它给网站颁发身份证(证书),浏览器里预装了「公安局」的公钥。当服务器出示证书时,浏览器用CA的公钥验证签名,确认证书没被篡改。
| 证书类型 | 验证级别 | 适用场景 | 价格参考 |
|---|---|---|---|
| DV(域名验证) | 低 | 个人博客、小型网站 | 免费 ~ 几百元/年 |
| OV(组织验证) | 中 | 企业官网、电商平台 | 千元级/年 |
| EV(扩展验证) | 高 | 银行、金融、政府网站 | 数千元/年 |
我的建议:个人项目用Let's Encrypt免费证书就够了。企业项目至少用OV证书,EV证书虽然贵,但浏览器地址栏会显示公司名称,用户信任度更高。
3.3 HSTS策略:强制HTTPS的「铁腕手段」
HSTS(HTTP Strict Transport Security)是个好东西。它告诉浏览器:这个网站只能用HTTPS访问,别给我走HTTP。
我曾经遇到过一个案例:某银行网站虽然支持HTTPS,但用户输入网址时习惯打 http://,服务器会302重定向到HTTPS。这中间就有一次明文请求,中间人完全可以劫持这次重定向,把用户引到钓鱼网站。
HSTS的配置很简单,在服务器响应头里加一行:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
参数说明:
- max-age:告诉浏览器记住这个策略的时间(秒)。31536000秒就是1年。
- includeSubDomains:子域名也强制HTTPS。
- preload:申请加入浏览器内置的HSTS预加载列表。
注意:设置HSTS要谨慎。一旦浏览器记住了,在max-age过期前,你没法通过HTTP访问自己的网站。我曾经见过有人把max-age设成10年,结果证书过期了,网站直接瘫痪——因为浏览器拒绝HTTP连接,而HTTPS证书又无效。
3.4 中间人攻击:HTTPS最大的威胁
中间人攻击(MITM),说白了就是攻击者站在你和服务器之间,冒充你和服务器通信。HTTPS能防住普通的MITM,但有一种情况防不住——客户端没有验证证书。
常见的MITM手法:
- 伪造证书:攻击者用自己的证书替换服务器证书。如果用户点了「继续访问」,那就中招了。
- ARP欺骗:在局域网内伪造网关MAC地址,让流量经过攻击者机器。
- DNS劫持:把域名解析到攻击者的服务器。
- SSL剥离:把HTTPS降级成HTTP,用户完全不知情。
我记得有一次帮客户做安全审计,发现他们的移动App没有做证书固定。我在同一WiFi下用Fiddler抓包,直接就能看到所有HTTPS请求的明文内容——因为App信任了Fiddler的根证书。这就是典型的MITM场景。
3.5 证书固定:给HTTPS加把「指纹锁」
证书固定(Certificate Pinning)是解决MITM的终极方案。它让客户端只信任特定的证书或公钥,而不是信任所有CA签发的证书。
实现方式有两种:
| 方式 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 硬编码证书 | 把服务器证书的SHA-256指纹写死在代码里 | 最安全,无法绕过 | 证书更新时需要发版 |
| 公钥固定 | 固定证书的公钥,而非整个证书 | 证书更新但公钥不变时无需发版 | 实现稍复杂 |
以Android为例,用OkHttp实现证书固定:
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add("example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.build();
OkHttpClient client = new OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build();
避坑指南:我曾经在项目中把证书指纹写死,结果证书过期后App全部崩溃。后来我改用公钥固定,并预留了备用公钥。这样主证书过期时,用备用证书顶上,App不用发版。
3.6 总结:HTTPS防护的「三层防线」
聊了这么多,我习惯把HTTPS防护总结成三层:
- 第一层:TLS加密——防窃听、防篡改。这是基础,但不够。
- 第二层:HSTS——防SSL剥离、防降级攻击。强制使用HTTPS。
- 第三层:证书固定——防伪造证书、防MITM。给信任加上「指纹锁」。
你想想看,这三层都做好了,攻击者想搞你,难度就大多了。当然,没有绝对的安全,但至少咱们不能让攻击者「捡漏」。
嗯,这一章就到这里。记住:HTTPS不是配置完就完事了,证书要续期、HSTS要规划、证书固定要留后路。安全是个持续的过程,不是一锤子买卖。