惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
Cyberwarzone
Cyberwarzone
The GitHub Blog
The GitHub Blog
云风的 BLOG
云风的 BLOG
P
Proofpoint News Feed
小众软件
小众软件
Recent Announcements
Recent Announcements
博客园 - 三生石上(FineUI控件)
Security Archives - TechRepublic
Security Archives - TechRepublic
W
WeLiveSecurity
Cloudbric
Cloudbric
博客园 - 司徒正美
美团技术团队
N
News and Events Feed by Topic
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
PCI Perspectives
PCI Perspectives
宝玉的分享
宝玉的分享
H
Help Net Security
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Google DeepMind News
Google DeepMind News
Help Net Security
Help Net Security
Last Week in AI
Last Week in AI
S
Schneier on Security
N
News | PayPal Newsroom
B
Blog RSS Feed
L
LINUX DO - 最新话题
T
Troy Hunt's Blog
S
Secure Thoughts
雷峰网
雷峰网
aimingoo的专栏
aimingoo的专栏
L
Lohrmann on Cybersecurity
G
Google Developers Blog
Microsoft Azure Blog
Microsoft Azure Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
T
Tenable Blog
S
Securelist
L
LangChain Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
I
InfoQ
H
Heimdal Security Blog
Cisco Talos Blog
Cisco Talos Blog
F
Full Disclosure
Y
Y Combinator Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
K
Kaspersky official blog
T
Tailwind CSS Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
阮一峰的网络日志
阮一峰的网络日志
C
Cisco Blogs

卡瓦邦噶!

服务器高性能网络调优 | 卡瓦邦噶! 为何写作 | 卡瓦邦噶! 读《金阁寺》 | 卡瓦邦噶! 雨季又来 | 卡瓦邦噶! MTU Probe 引起的初始延迟 | 卡瓦邦噶! 3.5 秒的固定延迟问题 | 卡瓦邦噶! 学习网络的一点经验 | 卡瓦邦噶! ARP 问题诊断 | 卡瓦邦噶! 网络断断续续…… | 卡瓦邦噶! Piccolo P2P 镜像分发 | 卡瓦邦噶! 一起看电影 | 卡瓦邦噶! 《征服C指针》 | 卡瓦邦噶! 我的姥姥 | 卡瓦邦噶! Python的哲学 Python 3.5的新特性 学校不教的计算机课 垃圾回收(GC)的三种基本方式 在编程中体验纯粹的快乐 从《美丽新世界》谈自由 在快钱实习 迷人的嗓音和迷人的故事——《Sleepyhead》 Python 的十个自然语言处理工具 记一个愚蠢的bug 一年炉石传说的游戏体验 《以撒的结合:重生》网页版图鉴 分清 C++的指针、引用和数组 笑话三则 自由比皇帝更伟大——《悲惨世界》笔记 Git 10 周年访谈:Linus 讲述背后故事 用 0x3f3f3f3f 设定最大int值的优点 Joel给计算机系学生的建议 一个词法分析器的简单实现 怎样才算健康的生活方式 MacVim 配置攻略 学习培训课程的视频效果好吗? 语言的控制 可悲的大多数 CSS样式思维导图 2014年终总结 奥巴马成为首位写程序的美国总统 青岛老城区的下水道好在哪里? 做优秀 UI 的七个建议(第二部分) 选择爱情的骑士 Git简明教程 Java集合总览 读 《1984》 java问答:终极父类(六)——等待/唤醒和接口 Java 问答:终极父类(五)——toString() Hyperlapse快速视频背后的技术细节 平庸之恶 Java程序员须知的七个日志管理工具 苏州 逛书摊随想 关于考试作弊 你的工作不仅仅是编程 推荐在线学习Java的英文资源 关注女性命运——《千禧年三部曲》 用好你的幻灯片——《演说之禅》 使用ReentrantLock和Lambda表达式让同步更纯净 新手学编程,从哪里开始? 程序员都是工程师吗? 不要学习代码,要学会思考 Java 问答:终极父类(四)——hashCode() Java 问答:终极父类(三)——finalize()和 getClass() 程序员职业之路的选择 我是一名摄影家 写给何小树的城市指南 为什么一些语言会比别的快? Java的常见误区与细节 跟朋友在一起玩游戏 死神永生——读《三体》 五种类型的程序员 创业圣经——读《黑客与画家》 纪念加西亚·马尔克斯 Junit中处理异常的另一种方式:catch-exception Java8采用Martin Fowler的方法创建内部DSL Linux HotSopt虚拟机GC线程的CPU占用率 J2EE概念介绍 如何成为一名黑客 Java 问答:终极父类(二)——equals()方法 为什么我喜欢Java Java 问答:终极父类(一)——clone()方法 七个改变世界的Java项目 java中默认类型转换的小问题 传统与创新 欢迎来到互联网 莫言和马尔克斯——读《生死疲劳》 位运算的妙用 读《人为什么活着》 写博客教会我的事情 中国特色操作系统 2013年总结 《永不妥协》影评 恨不相逢未嫁时——《廊桥遗梦》影评 如何优雅地使用PPT 给明年依然年轻的我们 天才与柱子 黑客守则和黑客精神 Looking for Freedom——《被解救的姜戈》 简洁之道
数据是如何转发的
laixintao · 2025-04-04 · via 卡瓦邦噶!

在之前的文章中介绍了网络的「分层」概念1,那么这一篇继续科普一下网络的基础,即「转发」这个概念。

所有的转发都是二层转发。

为什么这么说呢?从前面网络的分层中我们已经知道,四层的网络协议是基于一种三层协议的,三层协议的数据包需要二层协议来承载(毕竟,我们不可能直接把三层数据包不经过二层直接传给别人),然后二层协议的数据包通过物理层发出去。物理层就是通信技术的知识了,可以说,到网络工程师这里第一层数字信号就是二层。在我们平时使用抓包工具抓包的时候,看的最外层数据包一般都是二层的包。

从网络设备的工作原理上讲也是这样,一个 IP 包从 src 传到 dst,中间经过了各种各样的网络设备,那么从 src 发出到 dst 收到,中间的网络设备修改了这个包的什么内容,才能一环接一环把它送到目的地呢?

交换机:不会修改任何内容,只查找自己的 mac 地址表转发走;

路由器:会根据 dst IP 查询下一跳应该发给哪一个 IP,但是下一跳的 IP 不会添加到数据包中。路由器会获取到下一跳对应的 MAC 地址,把数据包的 dst MAC 修改成下一跳的 MAC 然后转发出去。可以认为,此路由器出口 IP 和下一跳路由器入口的 IP 是在同一个子网中,所以每跳三层转发都是在同一个子网内的转发,即「所有的转发都是二层转发」。一般来说,路由器会有很多个物理接口,每一个物理接口都有 IP,互相连接的两个路由器的接口是在同一个子网(也有某些特殊的 P2P 网络可以不在同子网,甚至不需要配置 IP就能完成三层路由)。

不通路由的之间的接口是在同一个 LAN 下,所以也是基于二层转发

可以看出来,如果不考虑 NAT 这种会改变 IP 的设备,三层及以上的内容(除了 TTL 会被路由器修改)的内容是基本不会改变的。而二层内容几乎每一次都在改变。

Traceroute 的原理

一个包从源发送到目的地,要经过的网络设备太多,遇到问题怎么排查呢?traceroute 是网络的世界中最常用的一个工具了。

它的原理是:发送 TTL=1 的 ping 包,故意让第 1 跳路由器无法完成转发,第 1 跳路由器只能丢弃这个包,并发送 ICMP time exceed 错误信息回来,这个 ICMP 是告诉我转发的时候出错了,源 IP 是发生因为 TTL 丢包的设备的 IP,目的 IP 就是我,因为错误是要告诉我的。于是我就知道了第 1 跳的 IP(即丢包的 IP)是什么了。如此炮制,继续发送 TTL=2 的包出去,拿到第二跳的地址。知道目的地收到了我的包并且回复 ICMP reply 回来。这样,我就知道了整条链路上所有的设备的 IP,就可以用来定位问题了。当然了,肯定有些设备因为「安全因素」的考虑,配置了不对丢包发回去 ICMP time exceed,这样,这一跳就是空的,我们拿不到它的 IP。

说起来,还有过一次挺有意思的讨论。一次面试的时候,我和人家讨论 traceroute 的原理,对方讲的很好—— 「发送 TTL=1 的包,再发送 TTL=2 的包,到那一跳的时候会因为 TTL 丢包,然后直接发送一个 ICMP 回来」。但是这里的「直接」很有意思,有多直接呢?我问:「直接的意思是,比如第 3 跳会直接发给 src IP 一个 ICMP,还是第三跳转发 ICMP 给第 2 跳,第 2 跳转发给第 1 跳,最后转发到 src IP ?」对方说:「是前者,会直接发给 src IP,因为是要立即告诉 sender 出错了。」

候选人认为的 ICMP 工作方式

但是…… 候选人忽略了一个实际的问题——我们的 sender 和 R3 有物理连接吗?如果有物理连接,那么从发出的时候就不需要经过 R1 和 R2 了!说完之后他也恍然大悟,包是不可能隔空传递的!

什么是流?

谈到四层的时候,我认为流 (flow) 这个概念在四层上强调地不够。四层的数据流,就像小溪一样,源源不断从一个地方流到另一个地方,但是经过的路线总是一样的。

虽然在 IP 层每一跳都可能有多个下一跳设备可以选择,甚至多个设备的 cost 一样。那么在选路的时候,这一跳会根据 hash 算法来选择一个作为下一跳。hash 算法对于属于同一个流的数据包总会得到相同的结果,这样,就可以保证一个流的所有数据包经过的路线是一样的。比如,TCP 用来计算 hash 的 header 有 (src ip, src port, dst ip, dst port),UDP 和 TCP 一样,ICMP 一般是 (src ip, dst ip)。这也取决于设备的配置和实现,不一定非要使用这些字段。比如,使用 (src MAC, dst MAC) 也可以,TCP 的 hash 也可以只使用 (src ip, dst ip)。只要保证一点:同一个流经过的路线是一样的,就可以了。

尽管有多条路线,但是一个 flow 总会保持同一个路线

为什么要这样做呢?为了尽最大努力保证数据包的顺序,让接收到的顺序和发送的顺序是一致的。

但是 TCP 协议不是会保证包的顺序的一致性吗?是的。TCP 尽管可以帮我们纠正顺序,但是这不是免费的,TCP 需要在实现上利用 buffer 将乱序的包临时保存并且重新排列,然后再交给应用层。而且 TCP 协议可能认为收到的包乱序是网络堵塞了,然后会降低发送的速度。所以 IP 层会尽量保证包的到达顺序和发送顺序一致,但是不会完全保证。TCP 则会作为最后的兜底,完全保证顺序的一致性。

  1. 理解网络的分层模型 ↩︎

==抓包破案录==

这篇文章是抓包破案录系列文章(之前叫做《计算机网络实用技术》,后来改名了)中的一篇,这个系列正在连载中,我计划用这个系列的文章来分享一些网络抓包分析的实用技术。这些文章都是总结了我的工作经历中遇到的问题,经过精心构造和编写,每个文件附带抓包文件,通过实战来学习网络抓包与分析。

如果本文对您有帮助,欢迎扫博客右侧二维码打赏支持,正是订阅者的支持,让我公开写这个系列成为可能,感谢!

如果您正在阅读的是题目类的文章,这个目录内容正好用来隔离其他读者的评论。读完题目可以稍作暂停,进行思考,继续向下滑动,可能会被其他的读者剧透答案。

没有链接的目录还没有写完,敬请期待……

  1. 序章
  2. 抓包技术以及技巧
  3. 理解网络的分层模型
  4. 数据是如何路由的
  5. 网络问题排查的思路和技巧
  6. 不可以用路由器?答案和解析
  7. 网工闯了什么祸?答案和解析阅读加餐!
  8. 重新认识 TCP 的握手和挥手答案和解析
  9. 3.5 秒初始延迟问题答案和解析
  10. 网络断断续续……答案和解析
  11. 延迟增加了多少?答案和解析
  12. 压测的时候 QPS 为什么上不去?答案和解析
  13. TCP 下载速度为什么这么慢?答案和解析
  14. 请求为什么超时了?答案和解析
  15. 0.01% 的概率超时问题答案和解析
  16. 后记:学习网络的一点经验分享
与本博客的其他页面不同,本页面使用 署名-非商业性使用-禁止演绎 4.0 国际 协议。