ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

HTTP与HTTPS安全差异及TLS加密原理详解

HTTP与HTTPS安全差异及TLS加密原理详解 1. 从浏览器地址栏那把小锁说起每天打开浏览器地址栏里那串字符前面要么是http://要么是https://多数人扫一眼就过去了。但如果你做过抓包、排查过接口、或者被安全扫描报告追着跑过就会知道这两个协议之间的差距远不止多了一个字母s那么简单。我最早意识到这件事是很多年前做内网系统联调时用抓包工具随手一抓发现登录请求里的用户名和密码居然是明文躺在数据包里那一刻的冲击比看任何教材都来得直接。这篇内容想聊的就是HTTP与HTTPS的安全差异以及背后的加密原理。它适合几类人刚入行的后端或前端想搞清楚为什么生产环境必须上HTTPS做运维或安全的同学需要理解SSL/TLS握手到底在干什么还有那些被SSL/TLS协议信息泄露漏洞这类扫描报告搞得一头雾水、不知道从哪下手的人。我不会只停留在HTTPS就是加密的HTTP这种层面而是把握手流程、证书验证、加密套件、常见漏洞的成因都拆开讲让你看完能自己判断一个HTTPS配置到底安不安全。先说结论性的认知HTTP是明文传输的应用层协议HTTPS是在HTTP和TCP之间插了一层TLS历史上叫SSL用非对称加密协商出对称密钥再用对称加密传输数据同时用证书体系解决我在跟谁说话的信任问题。这三件事——机密性、完整性、身份认证——缺一不可。很多人只记住了加密却忽略了后两者结果配置出来的HTTPS照样能被中间人攻击。下面我会从明文到底暴露了什么开始一层层往上拆。2. HTTP明文传输到底暴露了什么2.1 一个抓包实验看清全部内容要理解HTTPS的价值最直观的办法是先看看HTTP有多裸。假设你在本地起一个最简单的HTTP服务然后用抓包工具监听回环网卡发起一次登录请求。你会看到类似这样的原始报文POST /login HTTP/1.1 Host: example.internal Content-Type: application/x-www-form-urlencoded Content-Length: 38 usernameadminpasswordPassw0rd123注意最后一行。用户名、密码、会话相关的字段全部以可读文本形式出现在网络里。任何能接触到这段链路的人——同一个局域网里的其他设备、路径上的路由器、代理服务器——都能直接读到。这不是理论风险是每天都在发生的现实。HTTP协议设计于上世纪九十年代初那个年代的网络环境相对单纯协议本身压根没考虑机密性。它的报文结构就是请求行 请求头 空行 请求体全部明文。响应也是同理服务器返回的HTML、JSON、Cookie一样是明文。2.2 明文带来的三类具体风险第一类是窃听。上面说的密码泄露就是典型。更隐蔽的是Cookie和Token的泄露——攻击者拿到会话Cookie就能直接冒充你的身份根本不需要知道密码。这也是为什么现在很多站点给Cookie加Secure和HttpOnly属性前者强制只在HTTPS下发送后者禁止JS读取。第二类是篡改。明文不仅可读还可改。中间人可以往返回的HTML里注入一段脚本或者把下载的安装包替换成带后门的版本。用户端完全无感因为没有任何机制校验数据在传输途中是否被动过。第三类是冒充。HTTP没有身份认证机制你访问http://bank.example怎么确认对面真的是那台服务器而不是DNS被污染后指向的伪造站点没有证书体系这个问题无解。提示判断一个请求是否敏感不要只看它是不是登录接口。任何携带身份凭证、个人隐私、业务机密的请求走HTTP都是不可接受的。2.3 为什么内网就没事是个危险错觉我听过太多次这是内网系统不用HTTPS。这个说法的问题在于它假设内网是绝对可信的。但现实里内网横向移动恰恰是攻击链中最常见的一环。一台被钓鱼的办公电脑就能让攻击者在内网里抓包。而且很多所谓的内网其实跨了多个办公点、甚至走了公网链路只是逻辑上划在一个网段里。退一步说即便链路真的可信明文日志、代理缓存、负载均衡的访问记录里也会留下敏感数据。合规审计时这些都是扣分项。所以我的建议很直接只要涉及认证或敏感数据无论内外网一律上HTTPS。成本已经很低了没有理由省这一步。3. TLS握手加密到底是怎么谈成的3.1 为什么不能全程用非对称加密很多人第一次接触HTTPS会问既然有非对称加密公钥加密、私钥解密为什么不干脆全程用它传数据答案是性能。非对称加密的数学运算大数模幂、椭圆曲线点乘比对称加密慢几个数量级。用它加密几KB的握手数据没问题但要加密整个网页、视频流CPU直接扛不住。所以TLS的设计思路是用非对称加密安全地协商出一个对称密钥然后用这个对称密钥加密后续所有数据。非对称加密只干传钥匙这一件事干完就退场。这个思路叫混合加密是HTTPS性能和安全能兼得的关键。3.2 一次完整握手的逐步拆解以目前主流的TLS 1.2为例一次完整握手大致是这样走的TLS 1.3做了大幅精简后面单独说Client Hello客户端发起带上自己支持的TLS版本、加密套件列表、一个随机数Client Random。Server Hello服务端选定TLS版本和加密套件返回自己的随机数Server Random。Certificate服务端把证书链发给客户端。Server Key Exchange视套件而定发送密钥交换所需的参数。Server Hello Done服务端表示我这边说完了。客户端验证证书检查证书是否可信、是否过期、域名是否匹配。Client Key Exchange客户端生成预主密钥Pre-Master Secret用服务端证书里的公钥加密后发出去。Change Cipher Spec Finished双方各自用三个随机数Client Random、Server Random、Pre-Master Secret算出会话密钥然后互发Finished消息验证握手没被篡改。握手完成后双方用协商出的对称密钥加密应用数据。注意这里的关键点预主密钥是用服务端公钥加密的只有持有私钥的服务端能解开。中间人即使截获了全部握手报文没有私钥也解不出预主密钥自然算不出会话密钥。3.3 三个随机数为什么都要用有人会疑惑会话密钥为什么不能只用预主密钥非要掺两个随机数原因是前向安全性和随机性增强。如果只用预主密钥那么一旦服务端私钥泄露攻击者可以解密历史上所有抓到的握手记录。掺入每次连接都不同的Client Random和Server Random后即使私钥泄露也只能解密当前这次握手因为随机数是每次新的历史流量依然安全——当然严格的前向安全还要靠ECDHE这类密钥交换算法随机数只是其中一环。这个细节在排查为什么同样的密钥算不出同样的结果时特别有用。我见过有人调试加密逻辑发现两次连接密钥不一样就以为出bug了其实这正是设计如此。3.4 TLS 1.3把握手压缩到了什么程度TLS 1.3最大的改动是把完整握手从两个往返2-RTT压缩到一个往返1-RTT会话恢复甚至能做到0-RTT。做法是把密钥交换的参数直接塞进Client Hello和Server Hello省掉了单独的Server Key Exchange和Client Key Exchange消息。同时它砍掉了一堆不安全的加密套件比如RC4、CBC模式的很多组合只保留AEAD类算法。代价是兼容性。TLS 1.3对中间设备老防火墙、老负载均衡不太友好因为它们可能不认识新的扩展字段。所以生产环境通常是1.2和1.3都开让客户端自己选。实测下来现代浏览器和主流服务端库对1.3的支持已经很成熟新项目没理由不开。4. 证书体系HTTPS信任的根基在哪4.1 证书到底证明了什么加密解决了别人看不懂但没解决我在跟谁说话。证书体系PKI就是补这一环的。一张X.509证书里最关键的几个字段主体Subject、公钥、有效期、颁发者Issuer、签名。它的逻辑是CA证书颁发机构用自己的私钥对服务器公钥 域名信息做签名。客户端内置了受信任CA的公钥列表拿到证书后用对应CA的公钥验签。验签通过就说明这张证书确实是那个CA签发的里面的公钥确实属于这个域名。这里有个容易被忽略的点证书绑定的核心是域名不是IP。所以用IP直接访问HTTPS站点证书校验通常会失败因为证书里没有那个IP。这也是为什么内网系统用IP访问时经常报证书错误。4.2 证书链是怎么一级级验上去的实际部署中服务端往往不会直接发一张由根CA签的证书而是发一条链服务器证书 → 中间CA证书 → 根CA证书。客户端从服务器证书开始用中间CA的公钥验签再用根CA的公钥验中间CA最后根CA在自己内置的信任库里链条闭合。常见故障是服务端漏发中间证书。浏览器有时能靠AIAAuthority Information Access机制自动补全但很多客户端比如某些语言的HTTP库、移动端不会结果就是证书链不完整报错。排查时用openssl s_client -connect host:443 -showcerts看一眼服务端到底发了几张证书一目了然。4.3 自签证书和私有CA的适用边界开发测试环境用自签证书很常见但要注意两点。一是自签证书默认不被信任客户端要么导入信任库要么关闭校验——生产环境绝对不能关闭校验那等于把HTTPS降级成HTTP。二是如果团队内部服务多建议搭一个私有CA统一签发而不是每个服务各自自签。私有CA的好处是只需在客户端信任一次根证书后续所有内部服务的证书都能自动通过校验管理成本低很多。注意关闭证书校验的代码比如各种verifyFalse、InsecureSkipVerify在代码审查里应该被当作高危项。我见过因为一行verifyFalse导致整个API通信可被中间人劫持的案例。5. 加密套件与那些年被扫出来的漏洞5.1 加密套件名字怎么读一个典型的加密套件名字长这样TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256。拆开看ECDHE密钥交换算法基于椭圆曲线的临时Diffie-Hellman提供前向安全。RSA身份认证算法用RSA证书验签。AES_128_GCM对称加密算法AES算法、128位密钥、GCM模式一种AEAD模式同时提供加密和完整性校验。SHA256握手阶段的哈希算法。看懂这个结构你就能判断一个套件安不安全。比如出现RC4、3DES、CBC在某些场景下、MD5基本就是该淘汰的老古董。5.2 CVE-2016-2183那个反复出现在扫描报告里的漏洞做等保或安全扫描的同学大概率见过SSL/TLS协议信息泄露漏洞CVE-2016-2183。它的本质是3DESTriple DES加密套件存在Sweet32生日攻击风险。3DES的块大小只有64位当同一密钥加密的数据量超过一定阈值约32GB攻击者通过大量流量分析有可能恢复出明文片段。这个漏洞之所以烦人是因为它往往不是配置错了而是服务端默认还开着3DES套件。修复方法很直接在服务端配置里禁用所有含3DES和DES的套件。以Nginx为例ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers on;Tomcat则在server.xml的Connector里配置ciphers属性排除3DES相关项。改完记得用nmap --script ssl-enum-ciphers -p 443 host或在线扫描工具复验确认3DES确实没了。5.3 降级攻击与协议版本控制另一个经典问题是协议降级。早期TLS支持协商到SSL 3.0甚至SSL 2.0这些老版本有POODLE等严重漏洞。攻击者可以通过干扰握手逼迫双方降级到弱协议然后利用弱协议的缺陷。防御手段就是在服务端明确禁用SSL 2.0/3.0和TLS 1.0/1.1只留TLS 1.2和1.3。配置示例Nginxssl_protocols TLSv1.2 TLSv1.3;这里有个实操经验禁用TLS 1.0/1.1之前先确认没有老客户端依赖它们。有些老旧的嵌入式设备、Java 6/7环境只支持到TLS 1.0贸然禁用会导致这些客户端连不上。稳妥做法是先开日志观察一段时间确认没有1.0/1.1的流量再关。6. 从HTTP迁移到HTTPS的实操路径6.1 证书申请与部署的完整流程迁移第一步是搞证书。免费的有Lets Encrypt适合个人和小团队商业CA适合对信任链、保险有要求的企业。申请流程大同小异生成私钥和CSR证书签名请求提交给CA通过域名验证DNS验证或文件验证拿到证书文件。部署时要注意文件权限。私钥文件.key必须严格限制访问通常设为600属主是运行Web服务的用户。我见过私钥权限设成644被扫描出来的案例等于把钥匙挂在门上。Nginx的典型配置server { listen 443 ssl; server_name example.com; ssl_certificate /etc/nginx/ssl/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; add_header Strict-Transport-Security max-age31536000; includeSubDomains always; }fullchain.pem是服务器证书加中间证书的合并文件这一步千万别漏否则就是前面说的证书链不完整问题。6.2 混合内容迁移后最容易翻车的地方页面本身上了HTTPS但里面还引用着HTTP的资源图片、脚本、样式这叫混合内容。浏览器对它的处理分两种被动混合内容图片、视频可能只是警告主动混合内容脚本、iframe会直接拦截。结果就是页面样式错乱、功能失效。排查方法很简单打开浏览器开发者工具看Console和Network里有没有被标记为mixed content的请求。修复就是把所有资源引用改成HTTPS或协议相对URL//example.com/asset.js。如果第三方资源不支持HTTPS那就只能换供应商或本地代理。6.3 HSTS让浏览器记住只走HTTPS光配置HTTPS还不够因为用户第一次访问可能还是走HTTP这中间有个可被利用的窗口。**HSTSHTTP Strict Transport Security**就是让服务器告诉浏览器以后访问我这个域名一律用HTTPS别再试HTTP了。响应头这么写Strict-Transport-Security: max-age31536000; includeSubDomains; preloadmax-age是生效时长秒includeSubDomains让所有子域名也生效preload是申请加入浏览器内置的HSTS列表。这里有个大坑preload一旦生效想撤销非常麻烦需要向浏览器厂商申请移除周期很长。所以建议先不加preload用max-age跑一段时间确认所有子域名都支持HTTPS了再考虑preload。7. 排查HTTPS问题时我常用的几招7.1 用openssl把握手过程看个透命令行排查HTTPSopenssl s_client是首选openssl s_client -connect example.com:443 -servername example.com -showcerts它会打印出完整的证书链、协商到的协议版本和加密套件。重点看三处Protocol是不是TLS 1.2/1.3Cipher是不是强套件证书链是不是完整。如果握手直接失败错误信息通常会告诉你原因比如证书过期、域名不匹配、或者协议版本不支持。7.2 抓包分析加密流量能看出什么HTTPS流量虽然内容加密但元数据是暴露的目标IP、端口、SNIServer Name Indication握手时明文传输的域名、证书信息、流量大小和时序。所以抓包依然能看出你在访问哪个站点大概传了多少数据只是看不到具体内容。这也是为什么SNI加密ESNI/ECH会成为新的研究方向。排查连接问题时抓包能帮你确认TCP三次握手是否完成、TLS握手卡在哪一步、是不是被中间设备重置了连接。我遇到过防火墙因为不认识某个TLS扩展而阻断握手的情况就是靠抓包定位的。7.3 常见报错与对应处理报错信息常见原因处理方向certificate has expired证书过期续签并重新部署hostname mismatch证书域名与实际访问域名不符换证书或改用正确域名unable to get local issuer certificate证书链不完整补发中间证书unsupported protocol协议版本不匹配调整ssl_protocolssslv3 alert handshake failure加密套件无交集检查双方支持的套件列表这张表基本覆盖了我日常遇到的大部分握手失败场景。定位思路永远是先看是TCP层还是TLS层的问题再看是证书问题还是协议/套件问题。8. 我对HTTPS配置的一点个人体会做了这么多年我最大的感受是HTTPS的难点从来不是配不配得上而是配得对不对。把证书装上、能访问这只是及格线。真正拉开差距的是那些细节——证书链完不完整、老协议关没关、弱套件禁没禁、HSTS加没加、混合内容清没清。安全扫描报告里那些反复出现的漏洞十有八九都是这些细节没做到位。另一个体会是别把HTTPS当成一次性任务。证书会过期加密套件的安全评级会变化新的攻击手法会冒出来。我习惯每隔一段时间用扫描工具复验一遍自己的站点看看有没有新的弱项。这个习惯帮我提前发现过好几次证书即将过期的问题避免了线上事故。最后分享一个实用的小技巧如果你不确定某个配置改动会不会影响老客户端别直接上生产。先在测试环境用openssl s_client模拟各种协议版本和套件去连确认目标客户端能正常握手再灰度发布。这个流程虽然多花点时间但比半夜被叫起来处理线上故障划算得多。
返回列表