ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

HTTP与HTTPS核心差异、TLS握手及迁移排障实战指南

HTTP与HTTPS核心差异、TLS握手及迁移排障实战指南 大概每个写代码的人都被问过这么一个问题HTTP和HTTPS到底有什么区别我在面试别人的时候十有八九得到的答案是HTTPS比HTTP安全多了加密。这话没错但离能用还差得远。真要说到为什么HTTPS能防劫持“TLS握手时客户端到底验证了什么”“公司让你把老接口从HTTP迁到HTTPS你要改哪些东西”很多人就卡壳了。这篇文章打算把两个协议按开发者和运维的实际视角拆开讲一遍包括报文结构、TLS握手、证书体系、协议栈位置再顺带把日常干活时最常遇到的几个报错场景Docker拉镜像失败、跨域、Content-Type不匹配、请求头过长、JMeter录制HTTPS脚本等一起复盘掉。不管你是刚入门的前后端同学还是每天要跟接口、容器、摄像头流设备打交道的测试和运维这篇文章都能给你一些直接能用的东西。1. HTTP协议把客户端和服务端的对话规则讲清楚1.1 请求-响应模型像饭店点餐一样的对话方式HTTP全称是HyperText Transfer Protocol超文本传输协议。名字里有超文本是因为它最早就是为了传HTML页面而设计的后来才陆续承载JSON、图片、视频、二进制文件这些五花八门的数据。它的基本工作方式只有四个字请求-响应。你作为客户端向服务器发起一次请求服务器处理完以后返回一个响应一次对话结束。这跟饭店点餐很像你报菜名服务员去后厨下单厨师做完后端上来服务员把菜端给你。整个过程围绕着一来一回展开服务器不会无缘无故先给你发一段数据。我接手过的不少前端请求失败问题排查到最后有一半是URL拼错了另一半是请求头或请求体格式不对。所以第一个要养成的习惯是遇到接口问题打开浏览器开发工具F12的Network面板先看请求行和响应行别急着怀疑代码。在HTTP里一次请求由请求方法、URL、协议版本、请求头、请求体组成一次响应由状态码、响应头、响应体组成。方法最常用的就是GET和POST一个偏重获取一个偏重提交此外还有PUT、DELETE、PATCH这些纯REST风格接口里常见的动词。拿URL来举例一个完整的URL长这样https://api.example.com:443/users?page1size20#top它拆开以后是这几段https协议方案告诉客户端用什么方式访问api.example.com主机名告诉客户端去哪台服务器443端口服务器上哪个门开着/users路径请求这个服务里的哪个资源?page1size20查询参数给服务器传的附加条件#top片段标识浏览器专用不会发给服务器。在排查接口问题时我习惯先把URL复制到在线接口调试工具里看一遍比对路径和参数往往一眼就能看出是少了斜杠还是参数名拼错了。这种事靠代码排查反而慢因为框架层的报错通常不会告诉你URL具体错在哪。1.2 HTTP报文结构请求行、请求头、请求体一次HTTP请求发到服务器对服务器来说就是一段纯文本。以浏览器访问一个JSON接口为例发出去的请求大概长这样GET /api/users?page1 HTTP/1.1 Host: api.example.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Accept: application/json Accept-Encoding: gzip, deflate, br Connection: keep-alive如果带了请求体比如登录时提交用户名密码POST请求会在头部之后空一行再把JSON数据放在后面POST /api/login HTTP/1.1 Host: api.example.com Content-Type: application/json Content-Length: 42 {username:admin,password:123456}注意头部和请求体之间的那个空行它是HTTP协议规定的分隔符千万别漏。有些极简HTTP客户端实现拼报文时就是漏了空行导致服务端解析失败这种问题在自研协议对接时非常坑。服务器响应则长这样HTTP/1.1 200 OK Content-Type: application/json Cache-Control: no-cache {code:0,data:[{id:1,name:张三}]}第一行就是状态行200 OK指的是请求成功Content-Type告诉浏览器响应体的格式响应体是实际的数据。这里面最关键的一个头就是Content-Type。很多前后端联调出问题都是因为前端发了JSON但是Content-Type没设对后端框架按表单格式去解析结果拿到一串字符串而不是对象轻则解析失败重则返回400或415。所以我在联调时总强调一句话请求头里的Content-Type必须和请求体的真实格式保持一致。1.3 HTTP的三大先天短板HTTP能跑遍全世界但它本身的三个短板也很明显这三个短板也是HTTPS出现的原因。第一个是明文传输。HTTP报文里的内容没有经过任何加密在网络上传输时任何能截获网络流量的人都可以直接看到数据。这就跟寄明信片一样邮递员在途中翻过来就能看到你写了什么。密码、Token、Cookie如果走明文HTTP相当于把家门钥匙直接放在门口地垫下面。第二个是无法验证对方身份。HTTP协议本身没有身份认证机制你连上一台服务器它不会主动向你证明我是你原本想连的那台服务器。攻击者在网络链路上伪装成目标站点客户端无法辨别于是用户就被带到了钓鱼页面。第三个是无法保证内容完整性。就算数据在传输途中被篡改接收方也没有办法发现。你请求的是一个页面攻击者在中间插入一段恶意脚本浏览器照样直接执行因为HTTP没有校验机制。这三条短板堆在一起催生了HTTPS。HTTPS并不是一种全新的协议而是在HTTP和TCP之间塞了一层TLS加密把原来的明信片变成了带锁的密封包裹。2. HTTPS协议在HTTP外面加了哪三道锁2.1 HTTPS的构成HTTP TLSHTTPS全称是HyperText Transfer Protocol Secure从名字就能看出来它只是在HTTP的基础上加了一个Secure。具体加的这层叫TLSTransport Layer Security它的前身是SSL现在大家日常聊天时经常说的申请SSL证书其实就是指申请TLS证书。HTTPS默认跑在443端口HTTP默认跑在80端口这是一个最容易记的区分点。加了TLS之后原来的HTTP报文先交给TLS层做加密、加消息认证码再交给TCP发送。接收方则反过来TCP收到数据先交给TLS层解密、校验完整性再把解密后的HTTP明文交给上层应用处理。你可以把它想象成一套加强版快递流程HTTP负责写好信的内容和处理业务逻辑TLS负责把信封封好、贴防伪封条、在运输途中全程加锁。因为多了这些步骤HTTPS从建立连接到正式收发业务数据都比HTTP多耗时。我见过不少团队在纯内网或者测试环境为了省事继续用HTTP但在生产环境还坚持用HTTP的如今基本绝迹了。原因很简单浏览器对HTTP站点会直接标不安全搜索引擎和App审核也对明文请求非常不友好。只要对外提供服务HTTPS基本是标配。2.2 TLS握手一次连接建立时的互相验明正身TLS层在正式开始传数据之前要先做一次握手握手的核心目的是让客户端和服务器协商出一把双方共用的对称加密密钥。为什么不用非对称加密直接传数据因为RSA这类非对称加密虽然安全但计算开销是AES这类对称加密的几十上百倍如果整段通信都用非对称加密服务器CPU会先撑不住。于是TLS采用了混合加密方案握手过程大致分四步客户端发送ClientHello告诉服务器自己支持的TLS版本、加密套件列表和客户端随机数服务器回复ServerHello选出一套双方都支持的加密套件带上服务器随机数同时把服务器证书内含公钥一起发给客户端客户端验证证书有效性确认服务器身份没问题后生成一个新的pre-master secret用服务器证书里的公钥加密发送给服务器服务器用自己的私钥解密得到pre-master secret。到此客户端和服务器都拿到了客户端随机数服务器随机数pre-master secret双方基于同样的三份材料各自独立计算出相同的会话密钥。之后的业务数据全部用这个会话密钥做对称加密。这个过程用大白话讲就是客户端先问你有什么证明你是你要冒充的那台服务器服务器递上证书客户端检查证书上的签名、域名、有效期确认没问题后双方再用一种公开的锁安全地交换了一把共同的钥匙之后的通信全靠这把共同的钥匙来加密解密。TLS 1.2的完整握手需要两次网络往返2-RTT到了TLS 1.3简化为一次往返1-RTT还支持0-RTT的会话恢复机制性能明显改善。所以新项目能上TLS 1.3就尽量上别一直停留在老版本。2.3 证书与CA为什么浏览器会提示不安全HTTPS安全性的基石是数字证书。证书由CACertificate Authority证书颁发机构签发CA是行业公认的可信第三方相当于网络世界的公证处。服务器证书里包含域名、组织信息、服务器公钥、证书有效期、签发者信息以及CA对证书内容的数字签名。客户端收到证书后校验流程其实就三个动作用根证书里内置的CA公钥验证证书的签名是否有效确保证书不是伪造的检查证书里的域名和用户当前访问的域名是否一致检查证书是否在有效期内是否被吊销。这三步任何一步不过浏览器都会弹出您的连接不是私密连接之类的警告。我见过最多的情况是证书过期了没人管或者访问的是https://example.com证书却只签了www.example.com域名匹配不上直接报错。这类问题在排查时第一件事就该看证书详情而不是急着清缓存。还有一批自签名证书。所谓自签名就是服务器自己给自己签发证书没有经过CA背书。开发环境用一用没问题但生产环境绝对不能用因为客户端不信任它。很多中间件默认就拒绝自签名的HTTPS连接除非你手动把证书加进系统信任库否则每次连都不方便。3. 选型和迁移从HTTP切换到HTTPS的实操路径3.1 核心差异快速对照日常选型时最关键的区别可以用一张表说清楚对比项HTTPHTTPS默认端口80443URL前缀http://https://传输内容明文TLS加密身份验证无证书验证服务器身份完整性校验无TLS消息认证码连接建立成本TCP握手即可TCP握手 TLS握手证书成本无免费或按年付费适用场景内网调试、非敏感数据所有涉及用户隐私和数据的场景选择上不用纠结只要系统需要经过公网、需要登录、涉及用户数据就无脑选HTTPS。内网的一些管理后台如果实在不方便接证书走HTTP也勉强能接受但要清楚其中的风险。3.2 从HTTP迁移到HTTPS的具体配置步骤假设你手里有个Nginx反代的服务要给它配上HTTPS第一步是申请证书。个人站点和中小项目用Lets Encrypt这类免费证书就足够了用certbot工具可以自动申请并续期。申请之前域名需要先解析到服务器IP且80端口暂时不能被占用因为签发流程需要验证域名所有权。申请完成后你会得到两个关键文件证书链文件和私钥文件。Nginx配置核心部分如下server { listen 443 ssl; server_name api.example.com; ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; } } server { listen 80; server_name api.example.com; return 301 https://$host$request_uri; }这里面有几个容易踩的坑。第一proxy_pass后面的后端服务可以继续走HTTP因为Nginx和后端之间通常在同一台机器或内网这个链路可以不加密但如果你希望全链路加密那后端也需要配上HTTPS。第二X-Forwarded-Proto这个头要带上否则后端的Spring、Node.js框架通过request.protocol拿到的协议类型是HTTP有些框架的Cookie Secure策略就会出问题。第三如果后端服务开启了HSTS响应头那么用户再次访问时浏览器会强制走HTTPS这时候你如果还没配好证书用户会被死死卡住所以HSTS要在迁移稳定后再开。我实际迁移过一个老项目最麻烦的不是证书配置而是页面里嵌套的图片、脚本、样式写死了http://开头的地址。浏览器在HTTPS页面里加载HTTP资源会被判定为混合内容Mixed Content轻则被拦截重则整个页面样式错乱。解决办法是全局搜代码把静态资源改成相对路径或者//开头的协议相对URL再不行就用Nginx做一层静态代理。3.3 性能和开销HTTPS真的慢很多吗很多人担心HTTPS慢实际上它慢的主要就是TLS握手和证书链下载。现代处理器普遍支持AES-NI指令集对称加密解密对CPU的消耗已经很小真正明显的影响是每建立一次新连接都要做一次完整握手多出来的两个RTT在高延迟网络下会感觉明显。缓解手段主要有几个开启HTTP连接复用Keep-Alive让同一个连接处理多个请求避免反复握手开启TLS会话恢复Session Ticket或Session ID客户端和服务器在有效期内的会话凭证可以直接跳过部分握手步骤开启TLS 1.3将握手往返从两次减到一次HTTP/3直接基于UDP的QUIC连接建立更快用OCSP Stapling由服务器自己把证书吊销状态查询结果附在握手包内省得客户端再去访问CA的查询接口。我在压测里见过一个数据同一个接口HTTP裸跑QPS约2000加上HTTPS且每次新建连接时降到约1200差距很大但一旦开启连接复用和会话缓存差距缩到5%以内。所以实际生产里HTTPS的性能开销完全可以接受真正要警惕的是每次都新建连接这种错误用法。顺带说一个跟Docker相关的典型报错error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled这个https://registry-1.docker.io/v2/是Docker官方镜像仓库的HTTPS接口。出现这个报错先按链路排查第一解析域名看通不通第二用curl -v https://registry-1.docker.io/v2/看服务器证书和TLS握手是否正常第三检查本机有没有配置错误的HTTP代理环境变量。很多开发机在配置代理后Docker后台进程也走了这个代理代理连不上就会出现net/http: request canceled这类报错。如果本机本来就访问不了外网那需要给Docker配置可用的镜像加速源而不是直接怪Docker本身。4. 协议栈视角HTTP/HTTPS和那些你没细想的兄弟协议4.1 从OSI七层到实际的四层模型大学教材里讲网络都要从OSI七层模型讲起物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。实际生产里大家更常用的是四层模型链路层、网络层、传输层、应用层。HTTP和HTTPS都工作在应用层它们依赖传输层的TCP来保证数据可靠传输。TCP负责把数据切分成数据包、按序发送、超时重传HTTP则不必关心底层丢包这些事只要把请求和响应拼好交给TCP即可。这也是HTTP的连接和TCP的连接经常被混为一谈的原因——实际上HTTP协议的连接复用本质上是复用一条已经建立的TCP连接。为什么面试官爱问输入一个URL到页面显示中间发生了什么因为它串起来的恰恰就是这条完整链路DNS解析域名拿到IPTCP三次握手建立连接如果是HTTPS再加TLS握手发起HTTP请求服务器处理并返回HTML浏览器解析渲染后续资源再通过连接复用继续加载。任何一个环节出问题页面就出不来。4.2 你经常遇到的协议其实分布在各层很多人把HTTP当成唯一的协议一提到协议就只想到Web接口。实际上协议这个词涵盖的范围远不止此。我把日常工作中常见的几个协议归了个类。协议主要层级/类型典型场景TCP / UDP传输层HTTP的底层传输视频通话、实时游戏常用UDPIP网络层路由和寻址的基础RIP路由协议路由器之间交换路由信息常见于老式网络设备HTTP / HTTPS应用层Web接口、浏览器页面RTSP应用层海康等摄像头视频流区分主码流、子码流Modbus / OPC UA应用层工业PLC、传感器、数控机床的数据采集CAN / UART总线协议汽车电子、嵌入式设备、锁控板之间的底层通信MIPI / C-PHY硬件接口协议手机摄像头、屏幕与主控芯片之间高速传输CPRI前传接口协议通信基站设备与射频单元之间的数据交互InfiniBand网络互联协议高性能计算集群中的高速互联phar / zip 等程序语言包装协议PHP、Java等运行时里对归档文件的操作方式这里单独说几个容易误解的点。RTSP和HTTP不是一回事。RTSP用于控制视频流常见的海康摄像头地址格式是rtsp://用户:密码IP:554/Streaming/Channels/101其中101代表主码流102代表子码流。主码流分辨率高、码率大适合录像存储和单路精细预览子码流分辨率低、带宽占用小适合多画面预览和手机端看监控。调试时如果画面卡顿可以尝试切到子码流。CAN和UART这类总线协议更底层它们传的是比特流或帧和HTTP不在一个维度。CAN协议报文解析在汽车电子里常见报文一般由帧ID、数据长度、8字节数据组成解析的关键是先拿到对应车型的DBC文件里面的信号起始位、字节序、缩放因子决定了一个原始字节如何换算成物理量。Modbus和OPC UA则是工业互联网里的应用层协议一个偏传统串口/网关采集一个偏现代以太网数据建模。用它们读取PLC、传感器、数控机床的运行状态再上报到MES系统是很多工厂数字化项目的基础链路。理解这些协议的分层和定位对排查跨界问题特别重要。比如你问为什么摄像头画面出不来如果只在应用层找问题永远也发现不了其实是海康摄像头的RTSP认证方式在NVR里配置错了或者是网络端口被防火墙挡了。5. 排障现场接口报错、状态码、Content-Type和证书问题5.1 状态码速查与实战错误分析HTTP状态码是最基础也最实用的知识。我做了一张速查表排查时可以直接对号入座。状态码含义常见原因与处理方向200成功请求正常检查响应体是否满足预期301永久重定向域名变更浏览器或客户端需更新地址302临时重定向常见于未登录跳转登录页304未修改命中缓存客户端可直接使用本地缓存400请求错误参数错误、报文格式错误重点看请求头和请求体401未认证缺少Token或Token失效403禁止访问无权限、IP被限、WAF拦截404资源不存在URL路径错误或后端未正确挂载路由408请求超时客户端长时间没发送完整请求429请求过多触发了限流检查是否频繁调用500服务器内部错误后端代码异常需看后端日志502网关错误Nginx等网关连不上后端服务503服务不可用服务过载或维护中504网关超时后端处理时间过长反向代理等待超时拿Docker的另一个报错来练手docker search redis request returned 500 internal server error for api route and version http://%2f%2f.%2fpipe%2fdockerdesktoplinuxengine/v1.56/images/search?termredis, check if the server supports the requested api version这个报错的格式很典型里面出现了api route and version和v1.56。它说明Docker客户端通过引擎API发请求时API版本不匹配。Docker引擎和客户端各自有API版本如果客户端版本太新、引擎太旧或者Docker Desktop的Linux引擎后台异常就可能返回500。处理办法简单直接重启Docker Desktop或引擎服务确保客户端和引擎版本匹配必要时彻底重启机器。遇到任何接口报错我的排查顺序固定为URL对不对 → 请求头对不对 → 请求体对不对 → 状态码属于哪类 → 后端日志输出什么。按照这个顺序大部分问题都能在十分钟内定位。5.2 Content-Type格式不匹配接口返回415或400前后端联调时Content-Type不匹配是我遇到频率最高的低级错误。举一个真实例子。前端用axios发POST请求axios.post(/api/login, { username: admin, password: 123456 })axios默认会把JS对象序列化成JSON字符串同时自动设置Content-Type: application/json。如果后端接口写得是用表单格式接收func login(c *gin.Context) { username : c.PostForm(username) password : c.PostForm(password) }那么后端从PostForm里拿到的就是空字符串因为请求体根本不是表单格式。反过来也一样前端用new FormData()提交表单后端却用json.Unmarshal解析结果绑定失败报400。解决思路很清晰先看后端接口文档要求的是JSON还是表单再让前端设置对应的Content-Type。JSON就设application/json表单就设application/x-www-form-urlencoded文件上传就要用multipart/form-data。这三者是联调中最常见的三种格式本质上对应请求体的不同组织方式。调试时可以在Network面板里直接点开请求查看Content-Type头一眼就能确认是否匹配。5.3 跨域、Cookie和请求头过长的疑难杂症前后端分离的架构里跨域报错几乎是必经之路。典型报错长这样Access to XMLHttpRequest at http://127.0.0.1:8000/myapp/center from origin http://localhost:3000 has been blocked by CORS policy这是浏览器的同源策略在起作用浏览器规定页面里的脚本只能访问同协议、同域名、同端口下的接口否则就拦截。localhost:3000访问127.0.0.1:8000端口不同属于跨域。解决办法在后端加CORS响应头Access-Control-Allow-Origin: http://localhost:3000 Access-Control-Allow-Credentials: true放在Nginx里就是add_header Access-Control-Allow-Origin $http_origin; add_header Access-Control-Allow-Credentials true;这里有个关键细节如果你需要跨域请求携带CookieAccess-Control-Allow-Origin不能写成*必须写具体的来源域名因为带凭证的跨域请求浏览器要求显式指定允许来源。很多团队把*改成具体域名后Cookie相关问题就消失了。另一个比较稀奇的报错是HTTP Error 400. A request header field is too long.这个翻译过来就是请求头某个字段超过服务器限制。最常见的原因是单点登录信息太多JWT太长或者Cookie过大被塞进了Authorization头或Cookie头。Nginx默认请求头缓冲区较小超长请求头会直接报400。解决办法是在Nginx配置里调大缓冲large_client_header_buffers 4 16k;但我不建议无脑调参更好的做法是检查是不是把不该放头里的数据放进去了。移动端和网页端的登录态如果动辄十几KB就要考虑改造成短Token加服务端会话缓存的方案。5.4 HTTPS调试与脚本录制JMeter录制HTTPS接口的正确姿势日常调接口最趁手的工具是curl和浏览器DevTools。curl -v https://example.com/api可以显示完整的TLS握手过程和请求响应头排查证书问题时比GUI工具更直接。如果服务端用的是自签名证书curl -k可以跳过证书校验但这个参数只建议在开发环境用。做性能测试或自动化测试时常需要用JMeter录制HTTPS脚本。录制过程本质上是让JMeter作为中间人代理来解密HTTPS流量具体流程分几步在JMeter里新建线程组和HTTP代理服务器在JMeter的bin目录下找到ApacheJMeterTemporaryRootCA证书安装到本机系统信任库把浏览器的HTTP代理地址设为JMeter代理服务器的地址默认127.0.0.1:8080操作浏览器访问目标系统JMeter会录制所有HTTP请求生成测试脚本录制完成后对脚本做清洗删掉静态资源请求图片、JS、CSS用正则表达式提取动态Token把硬编码参数改为变量。录制HTTPS请求和解密HTTPS流量本质是一样的原理都是在客户端和服务器之间插入一个信任的代理。这里必须特别强调这类操作只能用于自己拥有或有明确授权的系统和接口在合法授权范围内做开发调试和性能测试是这个岗位的基本职业操守。千万别拿这些手段去探测别人的系统。JMeter录制脚本最容易翻车的是忘记安装根证书导致浏览器访问HTTPS站点时提示您的连接不是私密连接。另一个坑是录制完脚本后脚本里的请求顺序和浏览器实际发出的顺序不完全一致因为浏览器有并发加载。遇到这种问题建议在事务控制器里手动分组把关键接口按业务逻辑排序而不是直接用录制的原始顺序。6. 常见问题速查与我的实操心得6.1 常见问题速查表问题现象可能原因建议处理浏览器提示证书错误证书过期、域名不匹配、自签名换有效证书或检查证书SAN域名curl报SSL certificate problem系统CA证书过期、系统时间错误更新CA证书库校准服务器时间接口返回415 Unsupported Media TypeContent-Type与请求体格式不符对齐前后端的Content-Type接口返回401Token缺失、过期、请求头名称拼错查看鉴权中间件日志检查请求头接口返回403无权限、IP白名单、WAF规则确认权限配置和防火墙策略Nginx返回502后端服务挂掉或端口不通检查后端进程和监听端口Nginx返回504后端接口处理超时优化慢接口调大proxy_read_timeoutHTTPS页面样式错乱页面里内嵌HTTP明文资源被判定为混合内容把静态资源改为HTTPS或相对路径Docker拉镜像报net/http: request canceledDNS不可达、代理配置错误、外网不通排查DNS、代理环境变量配置镜像加速器JMeter录制HTTPS失败根证书未安装、代理端口未设置安装JMeter临时根证书重新配置浏览器代理这张表不是万能的但覆盖了我这些年排查Web接口问题时最常碰到的场景。遇到报错先不慌把现象写清楚再按网络层 → 传输层 → 应用层 → 业务代码的顺序逐层排查效率会高很多。6.2 一些个人体会与建议协议这种东西看起来是纯理论但实际排障时你对它理解的深浅直接决定排查方向对不对。我自己吃了很多亏以后养成了两个习惯。第一个习惯是接到任何接口问题先不用IDE先在命令行用curl把请求完整打一遍。为什么因为curl能暴露最原始的报文结构。浏览器上可能因为缓存、预检请求、扩展插件等因素干扰判断curl加上-v参数把所有交互细节都打出来问题往往一眼就能看出来。比如HTTP/1.1 400 Bad Request和curl: (35) SSL connect error前者是应用层的事后者是TLS握手的事两者排查方向完全不同。第二个习惯是遇到不懂的报错不要只复制报错到搜索引擎先把报错里出现的URL、协议、端口、版本号、状态码拆出来。就拿error response from daemon那一类Docker报错来说里面藏着registry-1.docker.io、v2/、net/http这些关键线索结合这些线索你才能判断是连接层、TLS层还是应用层出了问题。盲目搜索整段报错大概率只能搜到各种无效答案。最后再分享一个小技巧给刚接触这些协议的朋友搭一个最简单的服务端程序监听本地端口用curl分别访问http://和https://对比观察两者报文和握手过程的变化比看十篇教程都管用。协议本质上就是一组格式约定亲手看到一次请求从明文变成加密密文你对HTTP和HTTPS的理解就再也不会停留在一个加密一个不加密这句话上了。
返回列表