1. 网络这门课最核心的思想分层到底在分什么1.1 网络要解决的第一难题异构设备如何协作我学计算机网络的时候最强烈的感受是这门课太“虚”了。操作系统能打开进程列表数据结构能写出二叉树到网络这儿我看不见网线里的电信号也没法手工把一个数据包举起来观察。后来我换了个角度才想明白计算机网络不是一个“设备”的问题而是一个“协作”的问题。全世界有几十亿台设备它们的操作系统不一样、硬件厂商不一样、通信速率不一样凭什么能互相传文件、刷网页、打视频电话如果让每台设备直接跟其他所有设备约定一套通信方式工业界早就乱套了。这就是分层思想的出发点把一件巨复杂的事拆成若干件相对独立的小事每一层只解决一个明确的问题。就像快递寄包裹你不需要知道货轮怎么开、飞机怎么飞你只需要把东西交给快递员填好地址后面每一段运输都有专人负责但这整个链条对外看起来是“寄快递”一件事。网络分层之后每层都向上一层提供固定能力的服务同时使用下一层提供的服务。层与层之间只需要认准“接口约定”至于内部怎么实现其他层完全不关心。这个思路本质上和软件工程里的模块化、服务化是一回事。1.2 七层模型与四层模型的现实取舍我当年背OSI七层模型时相当痛苦物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。背完之后过两天又忘了。直到后来看到TCP/IP四层模型才明白OSI的意义不是让你按图索骥而是让你知道早期设计者理想中的网络应该有哪些环节。两套模型的对应关系是学习时绕不开的坎。我自己整理过一张对照表现在每次讲网络都会用OSI七层模型TCP/IP四层模型核心职责典型协议应用层应用层面向用户提供语义化服务HTTP、DNS、FTP表示层并入应用层数据格式转换、加密、压缩TLS其实在这一层说话会话层并入应用层建立、管理、终止会话实际工程中很少单独拆分传输层传输层端到端可靠或尽力传输TCP、UDP网络层网络层寻址与路由跨网络转发IP、ICMP数据链路层链路层相邻节点之间的帧传输Ethernet、Wi-Fi物理层链路层0和1的物理信号传输网线、光纤、无线频谱真正在互联网上跑的是TCP/IP模型。OSI里的会话层和表示层工程上基本被应用层或传输层吸收掉了比如TLS握手虽然发生在传输层之上但我们在写代码时通常把它看作是HTTP客户端库的一部分。学习时我建议用“两头抓中间放”的策略应用层是离代码最近的传输层是面试最容易问的网络层是理解全局的关键链路层和物理层了解原理就够了。不要把时间平均分配到七层上否则很容易陷入细节堆砌。1.3 数据在层间流动封装与解封装分层模型不是摆设数据从一台机器到另一台机器的过程就是一层层“套壳”和“脱壳”的过程。发送端应用层产生数据例如你提交了一串JSON。传输层加上端口信息封装成段。网络层加上IP地址封装成包。链路层加上MAC地址和帧校验封装成帧。物理层把帧变成比特流发送出去。接收端反过来物理层收到比特流链路层校验帧网络层取出IP包传输层根据端口号把数据交给正确的进程应用层拿到原始数据。我理解这个过程最有效的类比是套娃寄信内容写好后装进信封写上收件人和发件人然后套进更大的外包装箱填上地址再交给快递系统。每一层只看得懂自己那一层写的“面单信息”不会去拆开里面看内容。面试里经典的“从浏览器输入网址到页面展示中间经历了什么”本质就是考察你能不能把这套封装和解封装的过程走一遍。很多新手答不完整不是因为不知道协议名而是脑子里没有“数据逐层下沉、逐层上升”的画面。后面第3章我会结合DNS解析把这个完整过程再走一遍。2. TCP的可靠承诺用什么代价换来的2.1 端口从“和谁通信”到“和哪个程序通信”IP地址解决的是“哪台机器”的问题但一台机器上同时跑着浏览器、微信、邮件客户端网络包到了却被认领这个活儿靠传输层端口号完成。端口是一个16位的数字范围0到65535。0到1023是知名端口比如HTTP用80、HTTPS用443、DNS用53。客户端程序发起连接时操作系统会给它分配一个随机的临时端口通常在一万以上。所以我喜欢把“IP地址端口号”理解成快递里的“小区门牌号房间号”。小区对应的是一台主机房间对应一个进程。没有端口字段操作系统收到数据只能干瞪眼。TCP报文头部里源端口和目的端口各占两个字节紧跟在开头的序号字段之前。如果你抓过包会发现前两个字节往往是随机数那个就是客户端临时端口。2.2 三次握手与四次挥手为什么次数这么讲究TCP是面向连接的协议。所谓“连接”本质是通信双方各自维护一套状态并且确认对方也愿意通信。建立连接的标准流程是三次握手客户端发送SYN报文并携带一个初始序号x。服务器回复SYNACK确认号是x1同时携带自己的初始序号y。客户端再回复ACK确认号是y1。我第一次学的时候想不明白为什么不能省掉第三步让服务器发完SYNACK就开始传数据原因是TCP面临一个场景——网络里可能残留一个“迟到的旧连接请求”。假设客户端曾经发送过SYN但迟迟没收到回复于是超时重发。第一份SYN在网络上绕了一圈现在才到服务器。服务器如果收到SYN就直接进入已连接状态它就会为一个根本不存在的连接开资源。等真实请求再来时服务器资源已经被浪费了。三次握手让服务器必须在收到客户端对“服务器初始序号”的确认之后才认为连接真的建立。也就是说它不是单向确认而是双向确认客户端确认了服务器能收到自己的消息服务器也确认了客户端能收到自己的消息。断开连接时是四次挥手很多教材直接让你背FIN、ACK、FIN、ACK四个包。这里的关键在于TCP是全双工的两个方向的数据传输彼此独立。关闭时每一方都要单独声明“我这边没有数据要发了”并且等对方确认。所以最少需要各一次FIN和一次ACK加起来就是四次。说个面试常见的追问为什么客户端在最后一个ACK之后还要等TIME_WAIT因为最后的ACK可能丢失服务器会重发FIN如果没有等待时间客户端可能已经关闭重发的FIN到达后找不到对应连接服务器就会一直处于关闭不完全的状态。TIME_WAIT一般持续两倍的最大报文生存期确保旧连接的迟到数据包不会污染新连接。2.3 流量控制与拥塞控制网络卡顿的根因之一TCP号称可靠传输但它不是简单地“发了等确认”就完了。真实网络里还有两个更棘手的问题接收方处理不过来以及网络中间设备转发不过来。接收方处理不过来的问题靠流量控制解决。TCP报文头里有个窗口字段接收方在回复ACK时会顺便告诉发送方“我现在的接收缓冲区还能装下多少字节”。发送方根据这个窗口大小限制自己未确认数据的总量。就好比你往朋友家寄快递朋友每次只收两箱你一次寄十箱剩下的只能在路上或者在快递点等着甚至被拒收。窗口字段就是“我现在能收几个箱子”的实时通告。网络中间设备转发不过来的问题靠拥塞控制解决。拥塞不是接收方能力不足而是网络本身堵了。TCP的拥塞控制算法分几个阶段慢启动从一个小窗口如10个报文段开始每收到一个确认就翻倍指数增长直到阈值。拥塞避免超过阈值后改为线性增长每次往返只增加一个报文段慢慢试探网络容量。快速重传如果连续收到三次重复确认就认为某个报文丢失了不等超时立刻重传。我实习时遇到过一个问题某服务到客户端的文件传输偶尔特别慢抓包发现大量TCP重传现象上是消息确认迟迟不来。后来定位到是跨运营商链路拥塞加上服务端默认的TCP参数是面向低延迟场景调的慢启动阈值偏保守大文件传输一直被卡在拥塞避免阶段。那时候我才真正体会到拥塞控制不是课本概念它直接影响业务体验。2.4 UDP什么时候比TCP更合适每次讲完TCP必然绕不开UDP。两者最直观的差异可以用一张表说清楚对比维度TCPUDP连接方式面向连接无连接可靠性可靠、按序、去重尽力而为可能丢包乱序传输效率头部20字节起握手成本高头部8字节零握手流量与拥塞控制有无适用场景文件传输、网页、邮件音视频、DNS、游戏、实时控制UDP被嫌弃的不可靠在某些场景下恰恰是优点。视频通话里丢一两帧画面用户感知不到但用TCP重传反而会拖慢实时性导致画面卡顿。游戏里玩家操作指令也走UDP因为旧指令还没重传完新指令已经产生了重传旧数据没有意义。我在学习时有个体会不要默认“遇事不决用TCP”。实时性优先且少量丢包可接受的场景UDP是更合理的选择。甚至会有人直接在UDP上面实现自己的可靠层比如把流量控制、重传逻辑定制成适合特定业务的版本。这属于典型的“牺牲通用性换极端性能”。3. 寻址与解析IP、路由和DNS如何把人找出来3.1 IP地址与MAC地址两套标识各管一段一台设备在网络里至少有两套标识。IP地址是逻辑地址负责跨网络定位MAC地址是物理地址负责在一个局域网内定位网卡。这两者的关系有点像你的收货地址和你的身份证号。地址可以随搬家改变是路由的依据身份证号一辈子不变只在特定环节核对身份。IPv4地址是32位通常写成四段十进制数。早期的地址分类体系A、B、C类已经基本被CIDR无类别域间路由取代。现在你看到192.168.1.0/24这种写法意思是前24位是网络号后8位是主机号。我刚开始学子网掩码时很烦躁后来找到了一个最实用的理解方式子网掩码就是告诉你“这个网段里有多少台机器可以直接在局域网里通信”。比如/24代表最多有254个可用主机地址去掉网络地址和广播地址/16就是65534个。这个理解在日常排查网络问题时比背公式管用得多。MAC地址是48位的出厂烧录在网卡里。但注意MAC地址只在同一链路内生效。一个数据包从北京传到上海它在每个局域网段里的MAC帧都会被重新封装。所以你不能把MAC地址当成设备的全球唯一身份而应该当成“当前这一段路的门牌”。3.2 私网地址与NATIPv4不够用的现实解法IPv4地址总数约43亿早就分配完了。现实世界是怎么撑下来的靠私有地址加NAT。私有地址段有几块固定的比如192.168.0.0/16、10.0.0.0/8、172.16.0.0/12。内网设备分配私有地址出口路由器把内网地址转换成公网地址。家里那台路由器就是一台NAT设备多个手机和电脑只共用一个公网IP路由器通过端口号区分是哪个设备的流量。NAT严重拖延了IPv4的耗尽但也带来了一个副产品内网设备默认不对外暴露。这从安全角度讲反而是好事很多家庭设备不直接被公网扫描到。IPv6把地址扩到128位设计初衷是让每台设备都有全球唯一地址彻底摆脱NAT。但因为演进周期长很多网络仍是IPv4和IPv6双栈并存。学习阶段你只需要理解IPv6的地址格式、地址类型和过渡机制的基本思想真正在业务里大面积配置的场景还不多。3.3 路由转发数据包逐跳前进的接力赛有了IP地址数据包怎么从源主机到目标主机答案是逐跳转发。每一台路由器只知道自己直连的网段以及下一跳该把包送给谁并不需要知道整条路径。教科书里会讲路由协议比如RIP、OSPF、BGP做运维的同学需要深入学。但大部分人首先要建立的是“路由表”和“默认网关”的概念。路由表本质是一套规则目标网段匹配到哪个条目就送到对应的接口或下一跳IP。如果所有条目都不匹配就走默认路由通常指向运营商网关。家里的电脑发出的非局域网流量先送到路由器路由器再送到运营商一层一层接力到目标服务器。有个小细节值得记住数据包在每一跳转发时源IP和目的IP始终不变但MAC帧的源地址和目的地址每经过一个链路都会被改写。这也是为什么抓包时你看到的是路由器网关的MAC而不是远方服务器的MAC。3.4 输入网址到页面返回一次完整的寻址旅程把前面的概念串起来就是“浏览器输入https://example.com后发生了什么”的完整版本浏览器先查本地DNS缓存。没命中就向配置的DNS递归解析器发出域名查询请求。这个请求往往是UDP到53端口。递归解析器如果也没有缓存就一路问下去根域名服务器告知顶级域服务器地址顶级域名服务器告知权威服务器地址权威服务器返回example.com对应的IP。这个过程叫递归迭代查询。浏览器拿到IP后发起TCP连接也就是第2章的三次握手。应用层构造HTTP请求传输层封装TCP报文并附上源端口和443端口网络层封装IP包并附上源IP和目标IP。链路层通过ARP获得默认网关的MAC地址封装成帧发送。路由器逐跳转发最终到达目标服务器。服务器响应后数据沿着相同路径返回浏览器解析渲染页面然后关闭连接或复用连接。这条路看着很长实际往往在几十毫秒内完成。每次排查网络问题时我就按照这条链路逐段测先看域名解析是否正常再看TCP建连是否正常最后看HTTP响应是否正常。能定位到层就能缩小问题范围。4. HTTP到HTTPS从明文信任到加密握手4.1 HTTP的基本盘方法、状态码与无状态会话HTTP是应用层最重要的协议前端后端每天都打交道。我整理它的核心只需要四部分请求方法、状态码、请求头、响应体。常用的方法就那么几个GET取资源POST提交数据PUT覆盖资源DELETE删资源。早期开发者习惯用GET带参数查询但涉及修改数据的操作标准做法是用POST或PUT避免敏感信息出现在请求行里同时也防止被浏览器历史或代理日志记录。状态码是快速判断问题的一类信息。1xx表示继续2xx表示成功3xx表示重定向4xx是客户端出错5xx是服务端出错。我最常查的几个301永久重定向、302临时重定向、401未认证、403无权限、404资源不存在、500服务端内部错误、502网关错误、503服务不可用、504网关超时。排查线上问题时先看响应码基本能决定下一步往哪里查。另外一句话记住HTTP的本质它是无状态协议。服务器默认不记得你上一次请求是谁。为了解决“记住登录状态”的需求才有了Cookie和Session这套方案。服务器在响应头里下发Set-Cookie客户端后续请求自动带上Cookie服务器根据Cookie里的会话ID从Session存储中恢复用户状态。我第一次写登录功能时就是没搞清这两者的关系结果把用户信息直接塞进Cookie导致可以伪造身份。后来才明白Cookie只是凭证真正的状态信息应该存在服务器端。4.2 明文带来的风险抓包视角看HTTP纯HTTP风险中最要命的一点是所有内容明文传输。在一个共享网络里任何能截获数据包的人都能直接读到你的请求内容。我做过一次演示开一个HTTP测试站点输入用户名密码然后抓包看数据。明文里清清楚楚能看到usernameadminpassword123456。如果这套流程发生在登录接口密码相当于裸奔。除窃听之外明文传输还给了中间人篡改的机会。攻击者可以在网关位置改掉响应内容往返回的HTML里注入脚本。用户看到页面明明是从自己的会话请求来的实际上内容已经被替换过。这些风险引出了网络安全的第一个底层要求传输数据需要机密性不能被偷看和完整性不能被篡改。单靠应用层自己写加密逻辑不够因为每个开发者自己实现的加密正确性很难保障。行业需要一套标准化的安全传输协议于是HTTPS成了默认选择。4.3 HTTPS与TLS握手证书、密钥协商与加密信道HTTPS不是一种新协议它是HTTP跑在TLS之上。TLS的核心目标是给通信双方建立一条加密信道同时保证彼此身份可信。这里要理解一个密码学难题对称加密比如AES效率高但双方需要共享同一个密钥这个密钥怎么在不安全的网络里安全交付如果直接传密钥攻击者截获后所有加密都白搭。解决思路是非对称加密一对密钥里公钥可以公开分发私钥自己保存。用公钥加密的数据只有私钥能解开反之用私钥签名、公钥验证。但非对称加密性能远不如对称加密所以TLS的实际策略是“混合加密”用非对称算法安全协商出一个临时的对称会话密钥然后用会话密钥加密后续所有数据。简化版的握手过程是客户端发送ClientHello包含支持的TLS版本和密码套件列表以及一个客户端随机数。服务器回复ServerHello选定TLS版本和密码套件附带服务器随机数并下发自己的证书。客户端验证证书是否可信确认服务器确实是域名对应的主体。客户端生成预备主密钥用服务器公钥加密发送过去。双方基于两个随机数和预备主密钥各自动派生相同的会话密钥。之后所有HTTP数据都用会话密钥对称加密传输。这个过程里最值得花时间理解的是第3步证书验证。如果证书无效后面的密钥协商其实就是在跟不明身份的人说话加密也没意义。4.4 证书链与信任模型理解“锁标志”背后的含义TLS证书是“域名和公钥绑定”的凭证。服务器证书里包含域名、公钥、有效期、签发者等信息。这个证书不能是自说自话得由可信的第三方签发。这里引出CA证书颁发机构体系。用户设备和操作系统里内置了一批受信任的根证书。服务器提供的证书由某个CA的私钥签名而这个CA的证书又可能由更上层的根CA签名形成一条证书链。浏览器验证时沿着证书链往上找到受信任的根证书再用根公钥逐级验证签名最终确认服务器的证书是真的。我遇到过同事问为什么公司内网自建的证书浏览器总报不安全原因就是浏览器里没有信任该自建CA的根证书。解决办法是在内网设备上手动安装根证书并把这个根证书标记为受信任。但这里有个安全禁忌绝不要在生产设备上随便安装来路不明的根证书一旦装了攻击者持有对应私钥时就能伪造任意网站。日常开发时本地调试用自签名证书没问题但不要让浏览器永久信任它。测试完就该移除。我自己习惯把本地证书加入“仅供当前项目”的信任范围而不是全局信任。5. 计算机安全从威胁模型到可落地的防御习惯5.1 安全的三个基础目标与威胁分类先记三个字母CIA。这不是中央情报局是安全的三大目标——机密性Confidentiality、完整性Integrity、可用性Availability。机密性保证数据不泄露给未授权的人完整性保证数据不被篡改可用性保证服务和数据在需要时可访问。所有攻击行为都可以从“破坏了哪个目标”来分类想要机密性失效网络嗅探、数据窃取、撞库。想要完整性失效中间人篡改、SQL注入改数据、文件内容替换。想要可用性失效DDoS攻击打满带宽或CPU、勒索软件加密磁盘、删库。我最早学安全时总是记不住各种攻击名后来发现更高效的方式是按攻击发生的阶段归类侦察扫描端口、探测指纹、入侵漏洞利用、弱口令爆破、钓鱼、持久化留后门、创建隐藏账号、横向移动从一台机器跳到内网其他机器、影响加密数据、删库、对外发出。按照阶段去理解防御时就能做到“每条链路都有对应的检测手段”而不是孤立地封堵某一个攻击。5.2 攻击面思维系统暴露越多越危险防御安全最怕思维误区是“我加了密码就安全了”。真正的安全工程师会先问我的攻击面有多大攻击面指所有可以被未授权用户接触到的入口。常见入口包括对外暴露的端口、开放的API、可上传文件的接口、登录页面、甚至是电脑上插着的USB口。攻击面越大被找到弱点的概率越高。我自己做过一次服务巡检时发现一个内部服务为了图方便监听在0.0.0.0:8080上结果这个端口直接被外网扫描到再配合一个老版本框架的漏洞差点被打穿。后来把监听地址改成127.0.0.1攻击面立刻缩小了一大截。减少攻击面有可操作的做法只暴露必要的端口服务监听地址绑定到内网或回环地址而不是所有网卡关闭不必要的管理接口对外API要限流、认证、校验输入开发环境和生产环境彻底隔离。理解攻击面之后你会发现很多所谓的“安全漏洞”其实不是黑客用多么高深的技术而是系统自己把门敞开了。5.3 纵深防御与最小权限不把鸡蛋放在一个篮子里纵深防御的思想是即使某一层防守被突破后面还有更多层兜住不让攻击者轻松直达核心。就像银行金库外有围墙、中有安保、内有保险柜而不是只靠一扇门。落到具体工程网络层防火墙放行最小规则、划分VLAN隔离网段。主机层及时打补丁、配置主机防火墙、开启日志审计。应用层身份认证、参数校验、防止SQL注入和XSS。数据层数据库账号独立、备份加密、最小权限表结构。备份与恢复定期验证备份可还原这是最后一道防线。最小权限原则和纵深防御是一对组合拳。给服务账户只分配它需要的权限给员工只开他业务需要的访问权。权限越小被攻破一个账号后的爆炸半径就越小。我见过一个典型案例某开发同学拥有云平台全部权限他的笔记本被钓鱼攻击拿下攻击者跟着他的API密钥把整个环境配置都拖走了。如果当初只给他项目级权限即使笔记本沦陷影响范围也能可控。安全设防时一定要思考“如果一个环节被突破损失会被限制在多大范围”。5.4 普通人也能执行的安全基线不少人觉得安全是运维和安全工程师的事其实大多数攻击是从人入手的。我给自己和家人定的安全基线只有几条但落实之后效果很明显密码不用同一个密码跨多个网站优先使用密码管理器生成并保存随机密码。双因素认证重要账号打开MFA短信验证码可用但首选认证器应用。补丁系统和软件开启自动更新不要长期停留在不维护的版本。备份重要数据按3-2-1原则备份至少一份在异地或离线存储。识别钓鱼看到“账号异常”“逾期通知”“中奖信息”先核对网址和发件人不随便点附件。这些事一点不玄乎但缺一条可能全盘皆输。学安全的意义不是让你成为一个渗透攻击专家而是建立“每个环节都可能被攻击”的意识然后让系统即使被攻击损失也可控。6. 我自己怎么把这份笔记用起来的最后一次复习计算机网络时我给自己定了三个“不看笔记也能讲清楚”的挑战第一画出一张完整的分层模型图标注每层在“浏览器输入网址到页面展示”这条链路里具体做了什么。第二解释三次握手为什么必须三次、四次挥手为什么必须四次并且能用生活例子说服一个完全不学技术的人。第三说清楚HTTPS的握手过程中非对称加密和对称加密分别解决什么问题证书在这个链路里起到什么作用。这三个挑战全部能顺利讲完才说明我不是在背概念而是真的理解了网络的设计逻辑。安全部分我个人最大的收获不是记住威胁列表而是养成了一个习惯每次设计系统或写接口时都会下意识问一句“如果这个接口被恶意调用最坏会发生什么”。答案往往就是需要补防护的地方。你也试着拿自己的项目走一遍这个提问比看完十篇安全文章都有用。这份速成课笔记只是起点。网络与安全像一张大网越深入越会发现每个协议、每个安全机制背后都有一整套工程权衡。保持“求甚解”的心态当你能用自己的话把那几条链路讲明白时这门课就算真正入门了。