ARTICLE DETAIL

资讯详情

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

自学第34天:用Wireshark抓包彻底搞懂TCP三次握手与DNS、HTTP

自学第34天:用Wireshark抓包彻底搞懂TCP三次握手与DNS、HTTP 第三十四天IT自学刚好满一个月还多几天。本来计划这一天开始学数据库结果早上翻了一下之前的笔记发现自己对“网络是怎么把请求送过去再送回来”这件事一直停留在背概念的水平连三次握手都说不利索。临时把今天的主题换成了计算机网络基础重点啃TCP三次握手顺手把DNS、HTTP状态码、抓包实战串了一遍。学完之后最大的感受是以前看文章总觉着三次握手是个很玄的东西等自己亲手抓到那些SYN、ACK、序列号、确认号之后它一下子就变得特别具体。这篇文章就把第三十四天具体做了什么、怎么学的、踩了哪些坑原原本本写出来给同样在自学路上的朋友一个可参考的样本。1. 第三十四天的学习路线与任务拆解1.1 前三十三天我已经学了哪些东西先说下前三十三天的底子这样你才能判断这一天安排得合不合理。我用的是典型的“效率优先”自学路线前面十天集中过了一遍Python基础语法包括数据类型、流程控制、函数、类、文件操作每天至少写二十个小练习接下来五天专门练Python内外的常用内置库重点是把json、os、re、collections这些用得滚瓜烂熟之后七天花在Linux常用命令上每天在虚拟机里敲命令从cd、ls、grep、find一直练到权限管理、systemctl和简单的shell脚本再往后五天学Git把最基本的init、add、commit、branch、merge、rebase全部过了一遍还模拟了几次冲突场景最后六天开始接触数据结构和简单算法主要学了数组、链表、栈、队列以及二分查找、双指针、几个基础排序。这套路线的问题我现在回头看也很清楚实操做了不少但底层的“为什么”严重欠账。比如我能用requests写一个爬虫脚本把它跑通但回答不了“DNS是怎么把域名换成IP的”这种基础问题我会用git clone拉代码却不理解HTTP协议里的状态码到底在表达什么。这就是第三十四天转向网络基础的直接原因。自学的特点就是欠账要趁早补越往后拖上层的东西越学越虚。1.2 这一天的时间块怎么划分学习计划我没有精确到分钟那样坚持不下来我只分成三个大块再加上晚上复盘。上午9:00-11:30看TCP三次握手、四次挥手、DNS解析流程做笔记。下午14:00-17:00动手抓包。用Wireshark抓一次完整的HTTP请求把上午学的三次握手在真实数据包里找到。晚上20:00-21:30汇总笔记、做几道网络基础练习题然后制定接下来五天的学习计划。这里有个经验如果当天学的内容偏概念下午必须安排一个动手环节否则概念就是飘的。比如你今天学了“TCP三次握手”你光记着“SYN、SYN-ACK、ACK”这九个字母第二天绝对忘。但当你在Wireshark里亲眼看到客户端发送一个标志位为0x002也就是SYN的包服务器回一个标志位为0x012SYN-ACK的包客户端再回一个标志位为0x010ACK的包整个过程就像在脑子里刻了一刀。1.3 为什么选“网络基础”作为第三十四天的主题自学很容易陷入“追着热门技术跑”的怪圈今天看机器学习火就学Python明天看前端火又去学JavaScript。我在第三十四天回头整理知识树的时候发现后端开发、爬虫、API调试、服务器部署哪条路都绕不开网络基础。不懂TCP三次握手调试接口超时的时候你就容易瞎猜不懂HTTP状态码后端返回一个302你都不知道该不该跟进不懂DNS连“为什么换了域名解析服务器之后访问不一样了”这种问题都解释不了。所以我给第三十四天定的目标很纯粹把网络基础里的高频概念彻底弄懂不仅要会背要在数据包里看到它们。计算机网络的内容非常多但第一天先聚焦在“一次HTTP请求的全过程”这条主线上把三次握手、DNS解析、HTTP请求/响应结构、常见状态码这几个点串起来。2. 用类比和抓包搞懂TCP三次握手2.1 三次握手我用的类比是“电话确认”TCP三次握手这件事教科书上写得很严谨客户端发送SYN报文服务端回复SYN-ACK报文客户端再回复ACK报文连接建立。但对于没有网络基础的人来说这三个缩写看着就劝退。我自己理解的时候用了一个类似“打电话”的类比帮我把流程捋顺了。第一次握手客户端发送SYN相当于你拿起电话拨号说“喂你能听到我说话吗”第二次握手服务端收到SYN同时把自己的SYN发过来相当于对方回答“听到了我也跟你说一声你能听到我吗”这一步对应的就是SYN-ACK。第三次握手客户端再发一个ACK相当于你说“我也听到了。”双方确认双向通信正常连接建立。这个类比帮我记住了两个关键点。第一为什么是三次而不是两次因为TCP要保证双方都能收发这需要四个方向的确认你发我收、我发你收但第二次握手把“我收到你的”和“我发我的”合并成一个包所以最少需要三次。第二第三次握手为什么是ACK不带SYN因为服务端的SYN已经在第二次发过了客户端这轮只需要确认收到不需要再发起同步。2.2 用Wireshark亲眼看三次握手光看类比还不够下午的实操环节我打开Wireshark选了一个真实网卡接口然后在自己电脑上启动了一个最简单的本地HTTP服务用浏览器访问它。过滤条件只需要两条tcp.port 8000和ip.addr 127.0.0.1就能把这次访问相关的所有包全过滤出来。抓到的包非常清楚第一个包客户端 - 服务端Flags列显示0x002也就是SYN第二个包服务端 - 客户端Flags列显示0x012也就是SYN-ACK第三个包客户端 - 服务端Flags列显示0x030这个不是只有ACK还带了PSH和ACK因为浏览器发请求的时候把数据和确认一起发了。看Sequence Number和Acknowledgment Number这两列能发现一个规律第一次握手客户端用Seq0第二次握手服务端用自己的Seq0、Ack1第三次握手客户端Seq1、Ack1。前两个数据包的序号都是0靠的是相对序号显示理解这一点之后再看服务器日志里那些莫名其妙的偏移就轻松多了。这里踩了一个新手常见的坑一开始我选了Wireshark的默认网卡结果什么都抓不到。后来发现本地回环流量在Windows上需要额外开启Npcap的回环支持安装时需要勾选“Support Loopback Traffic”选项否则过滤127.0.0.1就是一片空白。如果你用的也是Windows环境装Npcap的时候一定记得勾上这个选项。2.3 四次挥手为什么多一次三次握手学完之后我顺手把四次挥手也看了。四次挥手的过程是主动关闭方发送FIN被动方回复ACK然后被动方再发送FIN最后主动方回复ACK。为什么挥手要多一次因为TCP连接是全双工的两个方向可以独立关闭。类比来说挂电话的时候甲方说“我要挂了”FIN乙方说“知道了”ACK但乙方可能还有话没说完等乙方说完自己的内容之后再说一句“我也要挂了”FIN甲方最后说“知道了”ACK。一般情况下四次挥手会有四个独立的数据包但如果你抓包看到的挥手少于四个也不要惊慌因为ACK有可能和FIN合并或者两端同时发起关闭这些情况都会造成不同的组合。初学阶段把最标准的流程记住然后在抓包里眼见为实就够了。3. DNS解析到底做了什么3.1 从域名到IP的完整链路我一直以为DNS就是一个简单的“查表”直到第三十四天才弄明白它其实是一整套分级查询过程。如果你在浏览器里输入example.com操作系统里的解析器会先查本地DNS缓存查不到就向配置的DNS服务器比如路由器的DNS或公共DNS发起递归查询。这里可以做一个直观实验。我用dig命令查看example.com的解析过程dig example.com输出结果里可以看到一段ANSWER SECTION显示这个域名对应的IP记录和TTL缓存时间。继续用dig trace example.com能看到从根域名服务器到.com顶级域服务器再到example.com的权威服务器一层一层返回结果的详细过程。建议第一次做这个实验的人一定要在trace模式下看完整链路因为看懂这个就理解了为什么说DNS是“树状分级”的体系。3.2 常见的DNS记录类型学习这一天的过程中我整理了一份实用的DNS记录类型清单方便以后配置域名或排查问题的时候直接查。下列是使用频率比较高的几种A记录把域名解析到IPv4地址最基础的一条。AAAA记录把域名解析到IPv6地址。CNAME记录把域名解析到另一个域名常用于子域名指向主域名或者接入CDN。MX记录邮件服务的解析记录配置邮箱的时候会用到。TXT记录存放任意文本常用于域名所有权验证和SPF、DKIM等邮件验证机制。NS记录指定该域名由哪台DNS服务器负责解析。我在本地电脑上试着用nslookup -typemx example.com查了一下MX记录输出的结果明显和A记录不一样多了一组优先级数值。这里有个小知识点MX记录里数字越小优先级越高邮件服务会优先尝试数字小的服务器。第34天学到这一层就已经够用不需要一头扎进BIND配置里出不来。3.3 浏览器缓存、系统缓存、DNS服务器缓存另一个容易搞混的点是“DNS缓存”到底有几层。实测下来常见的至少有四层浏览器DNS缓存Chrome里可以通过chrome://net-internals/#dns查看。操作系统DNS缓存Windows上用ipconfig /displaydns查看Linux用systemd-resolve --statistics查看。本地路由器或局域网DNS缓存。上级互联网服务商DNS缓存。假如你修改了一个域名的解析记录但访问时还是旧地址八成是上面某层缓存没失效。以前我遇到这种问题只知道傻等现在会按层级排查先清浏览器缓存再刷系统缓存Windows用ipconfig /flushdns如果还不生效就换一个公共DNS再试。这个排查思路在第三十四天学完之后立刻变成了我的一项技能。4. HTTP请求的结构与状态码4.1 用curl把一个请求拆给人看网络基础里只有概念是不够的还要会实际观察。我下午连本地服务的时候顺手用curl发了一个HTTP请求命令很简单curl -v http://127.0.0.1:8000/-v参数非常关键它会把整个请求和响应的细节都打印到屏幕上。你可以清楚看到请求行是GET / HTTP/1.1后面跟着一堆请求头比如Host: 127.0.0.1:8000、User-Agent: curl/8.0.1、Accept: */*。响应那边会看到HTTP/1.1 200 OK、Content-Type: text/html、Content-Length等字段。看这个过程最有价值的点是普通用户以为浏览器打开网页是“一个整体操作”但实际上它是“浏览器打包一个HTTP请求发送出去服务器打包一个HTTP响应送回来”而且这个交互里所有细节都是明文可见的。学到这里再回头看爬虫、后端API开发、接口联调脑子里就会有一个具体的画面而不是模糊的“前端把请求发给后端”。比如你写后端代码时设置响应头其实就是在控制服务器往回发的那些字段。4.2 状态码不用背按区间理解HTTP状态码是我之前总记混的东西。第34天我换了一种记忆方式不再一个一个背而是按区间去理解效率提升非常明显。整理成表格就是下面这样状态码区间含义典型场景1xx信息类100 Continue请求还在继续平时很少直接遇到2xx成功200 OK、201 Created、204 No Content3xx重定向301 Moved Permanently、302 Found、304 Not Modified4xx客户端错误400 Bad Request、401 Unauthorized、403 Forbidden、404 Not Found5xx服务端错误500 Internal Server Error、502 Bad Gateway、503 Service Unavailable这个按区间记忆的方法核心逻辑是看数字的“百位识别类别十位和个位再区分细节”。遇到一个没见过的状态码先判断它是几开头就知道问题是出在客户端这边还是服务端这边。比如503一看就是5开头服务端有问题403一看就是4开头多半是权限不够。第34天之后我再看到接口测试工具里冒出一个不熟悉的状态码第一反应不再是去查列表而是先判断区间再去查具体含义。4.3 请求头里的关键字段在说什么观察HTTP请求的时候请求头字段不要只扫一眼就过去。第34天我重点理解了四个高频字段的含义。Host目标服务器的主机名和端口HTTP/1.1之后必须携带用于同一台服务器上区分多个站点。User-Agent客户端的身份标识。服务端据此判断是浏览器还是脚本很多反爬策略就是看这个字段。Content-Type请求或响应体的数据类型比如application/json表示JSON数据text/html表示HTML文档multipart/form-data表示文件上传。Content-Length请求/响应体的字节长度。我当时跟着C语言级别的输出仔细看了一遍发现curl -v输出的每一行都有一个前缀表示客户端发出的请求头表示服务端返回的响应头*是curl的额外说明信息。这个细节看起来不起眼但能帮你快速分清正在看的是哪个方向的数据。如果以后调接口遇到问题先看一眼能不能从请求头字段里找到线索很多时候问题不在代码逻辑而在Content-Type设置错了。5. 第34天踩到的坑与解决办法5.1 Wireshark抓包常见的四个坑下午的抓包环节我差不多踩了所有的入门坑这里单独记一下免得以后忘。第一个坑是抓包数据太多、找不到目标包。解决办法是先给过滤器设置一个精确的端口条件比如访问的是8000端口就填tcp.port 8000这样瞬间少掉九成以上的噪音流量。第二个坑是本机抓本地服务抓不到回环包解决办法是安装Npcap时勾选循环回话支持选项或者直接用tcpdump在Linux环境抓回环。第三个坑是忘了过滤HTTP层抓了一堆TCP包却没看到HTTP实际上报文里确实有HTTP层你只需把HTTP部分展开看或者在Wireshark顶部的显示过滤器里输入http它就会把HTTP报文过滤出来。第四个坑是抓包过程中访问了太多网站导致自己都分不清哪些是目标连接最好固定用一个测试页面或者本地服务不要边抓边乱逛。5.2 学完就忘怎么办第34天学的东西比前三十三天任何一天都更“理论性”所以我特别留意了遗忘问题。当天晚上做练习题的时候有三道关于TCP状态的判断题我全做错了原因是我在抓包时看到了连接建立后的握手数据但做题时没有把“连接状态迁移”和“具体数据包”对应起来。这就暴露了学习中的一个漏洞只看包不理解状态机下次换个场景还是不会。解决办法是去画状态迁移图。不是画复杂的全部状态只画三次握手和四次挥手涉及的状态客户端和服务端分别处于CLOSED、SYN_SENT、SYN_RCVD、ESTABLISHED等状态然后对照抓包里的每个包给每个包标注上“发送之前处于什么状态”“收到这个包之后迁移到什么状态”。这个过程很枯燥但一画完就能把TCP握手从“三个包的机械记忆”升级成“状态迁移的体系理解”。5.3 学习网络基础用什么工具最合适动手做实验之前先选工具很重要工具选错了实验就变成挫折体验。我做了一个小范围对比实际体会是Wireshark跨平台、图形化界面、协议解析能力强适合新手看细节。tcpdump命令行、轻量、适合服务器环境但需要配合-X参数看数据内容入门成本略高。curl发请求的工具配合-v参数能看到请求/响应的明文是日常调试最常用的。dig/nslookup专门查DNS的工具适合做解析实验。如果是完全零基础我建议第一天只用Wireshark加一个本地HTTP服务不要一上来就同时学tcpdump那样信息量太大容易学崩。我自己是先Wireshark把TCP三次握手和HTTP结构看懂之后再回头补tcpdump的命令行用法这样压力小很多。5.4 学习节奏怎么保证不半途而废第三十四天是个特别微妙的节点再过一天就是一个多月新鲜感已经过去很多自学的人会在三十到四十天之间放弃。我的办法是把当天的学习分解成一个“能完成的实验”上午学概念下午做实验晚上做总结。学网络基础不是“看完一本书”而是“完整抓一个包”“完整看一次DNS查询”。当你每天都能产出一个看得见摸得着的结果学习的持续动力会比靠意志力硬撑强得多。我建议所有自学的朋友都执行一条原则每个知识单元都要配一个亲手操作的小实验。尤其是网络基础这种概念密集的领域光看书最容易产生“学会了”的错觉。看得懂和做得出是两码事第三十四天我自己就是最好的例子。6. 第三十四天的实验笔记与后续计划6.1 当天的实验清单我习惯每天学完在笔记开头写五行话把当天做过的实验列出来。第三十四天的清单是这么写的使用dig命令完成一次域名解析查看A记录和TTL。使用curl -v请求本地HTTP服务观察请求行、请求头、响应行、响应头。使用Wireshark抓取一次完整的本地HTTP请求定位TCP三次握手的三个数据包并截图。使用nslookup -typemx example.com查看MX记录和优先级。用浏览器开发者工具的Network面板打开一个页面随机点开一个资源观察请求头里的User-Agent和响应头里的Content-Type并留意其状态码。这五项实验加起来用了大概两个半小时。做完之后连带的网络基础概念基本都过了一遍。如果你已经完成了前三十三天的学习可以把这份清单直接抄走第四十天左右再回来做一遍会发现理解和抓包速度都提升不少。6.2 学习笔记的记录方法这天的内容特别适合用“问题-假设-验证-结论”四段式记笔记。我自己记的一个例子是问题为什么第三十几天学网络基础这么重要假设后面学后端框架、爬虫、API调试都离不开HTTP协议理解。验证当天用curl和Wireshark做完整实验后再去看爬虫教程里说的一些“反爬”手段确实容易理解了。结论网络基础是后续多项技术的共有地基值得系统性补课。这种记笔记方式比单纯抄概念强太多它逼着你每次记录都形成一个完整的小思考单元。回顾的时候也很方便只要翻这些四段式笔记就能看出来自己当时是怎么想的卡在哪里后来怎么解决的。6.3 接下来五天怎么安排第三十四天结束前我顺手规划了后面五天的学习内容确保学过的网络基础不是孤立的一块。第三十五天学习HTTP请求方法的语义重点是GET、POST、PUT、DELETE的区别做简单的API调用实验。第三十六天学习TCP和UDP的区别通过抓包对比TCP三次握手和UDP的无连接特性。第三十七天学习HTTPS的加密过程和TLS握手只抓一次握手过程理解CA证书的角色。第三十八天集中练习Linux网络排查命令包括netstat、ping、traceroute、ss。第三十九天做一个小项目写一个简单的Python脚本同时把它部署在本地服务器上用前面的网络知识解释访问过程。这样安排是为了避免“学完就丢”。每次学完一个新主题都让下一个主题能用到它形成连续的知识链比学完一个丢一个的碎片化方式牢固得多。最后分享一个小技巧抓包时如果只想看三次握手不要看整个会话直接在Wireshark的显示过滤器里输入tcp.flags.syn 1 || tcp.flags.ack 1它会帮你把所有带SYN或ACK标志的包列出来三次握手和四次挥手会一目了然。第三十四天靠这个方法我把“三个包建立连接”这句话从抽象变成了眼见为实。下一步该把HTTPS和TLS也拆开看一看了。
返回列表