
Linux下的网络基础说真的属于那种你觉得自己会了但一到生产环境就露怯的主题。干运维这些年我最大的体会是网络不通的根因绝大多数不是命令不够炫而是没把底层的数据流转、协议分层、路由决策这些基本功串起来。这篇文章不谈那些花哨的框架就老老实实把这些基础铺开从内核收包到ip命令从配置文件到防火墙NAT再到真实排障时该怎么一步步追问题。适合刚接触Linux的开发者也适合已经写了一年脚本但遇到网络问题就懵的系统管理员。保证你看完能少踩几个我当年踩过的坑。1. 先把Linux网络这件事的轮廓描清楚1.1 一次收包请求在内核里走了多远我记得第一次独自排查服务器“网络全部不通”时第一反应是重启网卡。后来问题依旧才知道自己连最基础的数据包走向都模糊。理解Linux网络基础应该从网卡收到数据的那一刻开始。当网卡接收到一段电平信号先做CRC校验确认帧没坏再通过DMA直接写进内存里的环形缓冲区这一步基本不消耗CPU。接着硬中断触发内核会注册一个软中断NET_RX_SOFTIRQ把数据包封装成一个叫sk_buff的结构体。这个结构体是整个协议栈的“快递包裹”从链路层一路传到传输层都靠它。随后包进入协议栈链路层去掉以太网头根据头里的协议字段判断是IPv40x0800、ARP0x0806还是IPv60x86DD。网络层拿到IP头后第一件事是查路由表搞清楚这个包是给本机的还是需要转发出去的。如果是给本机的再根据TCP或UDP头里的端口号去找对应的socket最终放进socket接收队列应用层通过read、epoll这些系统调用拿到数据。这趟链路听起来不复杂但每一步都可能出问题。比如MTU不匹配导致包被分片或者被丢弃路由表策略不对导致包绕了远路socket接收队列满了导致内核丢弃数据。如果你一上来就抓包看到现象却解释不了根因那大概率就是没把这条链路吃透。1.2 分层的意义以及排障为什么容易错位TCP/IP模型分四层链路层、网络层、传输层、应用层。每层各司其职但排障时最容易犯的错是拿高层工具去测低层故障或者反过来。拿寄快递打比方链路层是快递货车网络层是分拣中心决定包裹去哪个城市传输层是快递单号衣服柜子应用层是收件人签收。全链路畅通收件人才拿得到货。网络问题虽然表现为应用层“连不上”根因却可能出在任何一层。我见过不少人遇到“网络不通”就拼命检查业务端口结果真正原因是物理网线松了。更有意思的是反向场景ping通就以为网络没问题结果业务端口被防火墙挡在INPUT链上。分层思维的价值在于排障顺序永远不会乱。先链路再IP再路由再传输再应用。每层都有专属工具和专属查看命令后面几节我会按这个顺序展开。2. 用ip命令把网络状态摸透2.1 ip link先确认接口活着而且状态是UP现在很多Linux发行版仍然保留ifconfig命令但它早已不是主流。现代系统上ip命令是标准操作入口。排查第一步永远应该先看接口状态ip link show ip -s link show ens3第一条输出能看到每个接口的名称、MAC地址、状态和MTU。尤其要关注state UP还是state DOWN。如果接口处于DOWNip addr里配置再漂亮的IP也是白搭。第二条加-s参数能看到收发统计。重点看errors、dropped、overruns这几列。errors大幅上涨多半是物理层问题比如网线松动、交换机端口协商异常。dropped上涨可能是接收缓冲区不够或者防火墙策略丢包。overruns说明内核处理不过来常见于小包冲击或者CPU软中断被绑核。提到MTU很多人忽略。默认1500字节在绝大多数场景没问题但用VXLAN、隧道或者巨型帧环境就很容易出现黑洞。怎么验证MTU可以用带DF标志的pingping -M do -s 1472 192.0.2.1默认ping payload是64字节以太网总帧大小大约1500所以payloadIP头20ICMP头81472刚好不超。如果这个能通说明网络路径支持1500MTU。如果再往上加字节ping不通那就是某个中间设备MTU太小并且ICMP不可达消息又被防火墙吞了。2.2 ip addrIP地址、CIDR和scope别只记命令接口正常后第二步检查地址ip addr show ip addr add 192.0.2.10/24 dev ens3 ip addr del 192.0.2.10/24 dev ens3我一直强调要理解CIDR。/24不是随便写上去的它代表子网掩码是255.255.255.0。192.0.2.10/24意味着网络地址192.0.2.0广播地址192.0.2.255有效可用主机地址是192.0.2.1到192.0.2.254。看到“/24”如果不能立刻反应出掩码和广播地址说明还需要补基础。ip addr输出里还有个容易被忽略的scope字段。常见的global表示这个地址对外可见host表示只属于本机。比如lo接口上的127.0.0.1/8就是scope host。有些服务监听在127.0.0.1上外部永远无法访问本质就是地址scope限定的。检查地址时还要警惕一个现象接口上有多个IP并不奇怪但同一个IP出现在两个接口上会出事。Linux对地址冲突不是特别敏感两个接口广播同一个IP会导致后续收到数据的arp缓存来回跳。如果你发现ip addr里出现两处相同地址这通常比防火墙问题更隐蔽也更致命。2.3 ip route路由表决定数据包去向默认网关别乱配地址有了怎么知道数据包走哪个口出去看路由ip route show ip route add default via 192.0.2.1 dev ens3 ip route add 10.10.0.0/16 via 192.0.2.1 ip route del 10.10.0.0/16路由表的核心规则是“最长前缀匹配”。比如有一条default路由也有一条10.10.0.0/16路由那么去10.10.1.5的数据包会选择后面这条因为它前缀更长、更精确。理解这个规则解决“为什么走了奇怪网关”就很容易。ip route show输出里经常有一行proto kernel scope link src 192.0.2.10这是内核因为接口配置了地址而自动生成的直连路由。它保证了同网段的包可以直接出去不需要网关。有些人手动删掉这类路由结果同网段通信立刻断开就是这个原因。默认网关配置也常见一个坑一个网卡配了多个IP或者系统有多个网卡如果把默认网关指向一个并不存在的下一跳外部流量全都会消失。我习惯配置完地址后立刻ip route show确认默认路由的dev接口真的是通往外部的那张网卡。3. 从临时配置到永久生效Linux网络配置的三种姿势3.1 NetworkManager与nmcli适合桌面也适合大部分云主机ip命令改的配置只对当前运行生效重启后一切还原。要持久化绕不开网络管理服务。目前最常见的管理者是NetworkManager。虽然很多人对它有成见但它对动态网络环境处理确实好尤其适合云主机。常用命令nmcli device status nmcli connection show nmcli con mod ens3 ipv4.method manual ipv4.addresses 192.0.2.10/24 ipv4.gateway 192.0.2.1 nmcli con up ens3nmcli con mod不会立即生效需要up或者重启网络服务。这也经常让人误会改了配置没重启查半天发现运行时的配置还是旧的。NetworkManager强大的地方在于可以统一管理bond、vlan、bridge。比如多网卡绑定链路聚合用nmcli可以一步到位。如果只用脚本跪多个配置文件遇到bond或者vlan会非常痛苦。我碰到过生产环境为了做bond手写了半天ifcfg文件最后发现NetworkManager根本不读原因是没有设置NM_CONTROLLEDyes。这类问题在纯NetworkManager环境里反而不会发生。但NetworkManager也不是万能。如果你是一个极简容器或者轻量虚拟机不需要复杂连接管理那么它反而是累赘。所以下面这个选择很关键。3.2 systemd-networkd适合轻量服务器和容器场景凡是看NetworkManager不顺眼的多半会喜欢systemd-networkd。它通过文本文件直接描述“哪个网卡用哪个地址”规则简单粗暴。静态配置示例写入/etc/systemd/network/10-static.network[Match] Nameens3 [Network] Address192.0.2.10/24 Gateway192.0.2.1 DNS1.1.1.1使用这个配置要先把NetworkManager停掉systemctl stop NetworkManager systemctl disable NetworkManager systemctl enable --now systemd-networkd注意/etc/systemd/network/下文件的命名顺序系统按字典序加载文件名。如果两个文件匹配同一网卡配置就可能相互覆盖。养成以数字开头命名的习惯比如10-ens3.network这样优先级一目了然。DHCP配置更简单[Match] Nameens3 [Network] DHCPyessystemd-networkd还有个好处没有NetworkManager那么在意的配置文件缓存干扰改文件后执行networkctl reload出错就是白纸黑字报错没有那么多“玄学”。我在需要跑容器的小机上基本都会把网络管理切到它。3.3 ifcfg传统脚本遇到旧系统照样得会读还没完全淘汰的CentOS 6、7时代常看/etc/sysconfig/network-scripts/ifcfg-ens3BOOTPROTOnone ONBOOTyes IPADDR192.0.2.10 NETMASK255.255.255.0 GATEWAY192.0.2.1 DNS11.1.1.1后来即使CentOS 7也逐步被NetworkManager接管但如果系统配置变了还是要能读懂这些字段。最常见的坑是ONBOOTno网卡地址配了却没法自启。还有BOOTPROTOdhcp和静态IP混用导致启动时先抢了DHCP地址后来静态地址才覆盖上去。遇到这类旧系统我建议在改配置前先备份然后执行systemctl restart network重启后立即看ip addr。如果不如预期立刻查journalctl -u network和message日志。配置文件差一个下划线、少一个引号都可能让整个服务起不来。4. 排障工具箱从ping到tcpdump4.1 ping真的能通不代表一切正常排查连通性大家第一个想到ping。但我要泼盆冷水ping通只能说明ICMP和链路层通了不代表TCP、UDP端口通也不代表DNS正常。反之ping不通也不能立刻断定网络挂了因为很多设备主动丢弃ICMP。遇到“ping不通但业务好像还正常”的情况先确认是不是策略问题。用arping看看二层邻居在不在arping -I ens3 192.0.2.1这个命令直接在数据链路层发送ARP请求不依赖IP转发。如果arping有响应而ping没有那问题多半在中间路由器的防火墙或ICMP配置上。ping的主要价值在于测丢包和延迟。比如ping -c 100 -i 0.2 192.0.2.1稳定的内网延迟应该在1ms以内。如果延迟忽高忽低还能观察到dup重复响应多半是网卡bond配置错误或者交换机环路。4.2 traceroute看的是路径不是终点网络路径变长、延迟变大需要找出卡在哪一跳这时候上traceroutetraceroute -n 203.0.113.5 traceroute -T -p 443 203.0.113.5原理是每次发送TTL递增的数据包从1开始每过一个路由器TTL减1减到0时路由器返回ICMP超时这样就能记录每一跳。-n关闭反解速度快很多。-T -p 443表示用TCP协议探测443端口很多防火墙允许HTTP端口出去这个方法常能穿透普通ICMP被拦的路径。输出里出现*不要慌它只代表这一跳没有回复ICMP超时有可能是该设备禁了ICMP并不是链路断。真正要关心的是在某一跳之后所有后续跳全部超时那才说明路径从这里开始出问题。我根据自己经验排障少看中间节点只看首跳、末跳和延迟突变点就够了。4.3 ss端口有没有在听连接处于什么状态查端口监听和连接状态用ss。它比老旧的netstat快信息也更准确ss -lntp ss -s ss -tan state established第一条列出所有监听中的TCP端口-n表示不做域名解析-p显示进程名和PID排障时立刻能知道某个端口到底是哪个程序在监听。第二条查看系统socket统计比如TIME_WAIT、CLOSE_WAIT总量这个数字突然暴涨往往预示应用异常。第三条筛出已建立的连接方便排查大量连接堆积的情况。一个经典误判程序报“端口被占用”ss -lntp却怎么都看不到。为什么会这样多半是程序监听在IPv6的::地址而ss没加-6参数被误导为没监听。加上-6再看立刻真相大白。还有一种情况服务监听在127.0.0.1同机器可以通过外部连接却失败ss -lntp里还是能看到监听但地址决定了它只对本机开放。4.4 DNS排查先从系统的角度看再谈digDNS问题真的很容易和网络问题混在一起。先确认系统解析行为getent hosts example.com cat /etc/resolv.conf系统里很多程序不是直接用DNS协议而是走libc的getaddrinfo它受/etc/nsswitch.conf控制。比如nsswitch里配置了files dns表示先查/etc/hosts再查DNS。如果你往/etc/hosts里写了一条解析记录即使DNS正常解析结果也会优先用hosts里的值。排障时一定要先getent hosts再决定要不要看dig。看DNS查询本身用digdig 1.1.1.1 example.com short dig trace example.com指定上游DNS服务器可以跳过本地缓存直接测公共解析。trace能展示从根域到最终目标的完整解析链路。如果你发现本地程序解析异常但dig 公共DNS正常问题大概率出在本地DNS服务器或/etc/resolv.conf配置顺序上。注意/etc/resolv.conf经常被NetworkManager偷偷重写。很多人在里面手写了DNS重启后就剩一行127.0.0.53那是systemd-resolved在接管。不要直接编辑后等着重启要检查是不是被某个管理服务给覆盖了。4.5 tcpdump抓包最后用证据说话前面所有工具都只是间接推断只有抓包能看到最原始的网络交互。tcpdump是最终的“呈堂证供”tcpdump -i ens3 -nn port 53 tcpdump -i any -nn tcp port 8080 -w /tmp/http.pcap第一条监听53端口-nn不解析主机名和端口避免干扰自己。第二条把8080端口包存入pcap文件方便后续用图形化工具慢速分析。抓包时如果流量很大建议先加上-c 100限制抓包数量不然文件膨胀得吓人。我举一个用tcpdump定位的真实场景应用日志大量报“上游连接超时”ping网关正常端口也能连通就是业务整体变慢。我抓包后发现TCP重传率居高不下连续看到TCP Dup ACK和Retransmission。顺着重传下去定位到这台机器与核心交换机之间有大量错包最后查清楚是网卡驱动固件太老导致协商速率不稳定。如果不抓包这件事怎么查都像是“玄学”。抓包务必注意权限普通用户跑需要root或者赋予CAP_NET_RAW。另外抓包本身会影响性能生产环境别长时间全量抓条件尽量选精确。5. 防火墙与NATnetfilter体系其实很朴素5.1 从iptables到nftables规则链里发生了什么Linux防火墙的本质是内核里的netfilter框架。它对数据包设置了几道关口管理员可以往关口上追加规则。以前用iptables现在更推荐nftables但概念一脉相承表和链。记住这张表就够了链触发时机用途PREROUTING包到达本机路由决策之前DNAT、地址伪装前处理INPUT目标地址是本机过滤发往本机的流量FORWARD目标地址非本机需要转发过滤经本机转发的流量OUTPUT本机发出包路由决策之后过滤本机外发流量POSTROUTING包即将离开网卡SNAT、MASQUERADE为什么要理解这个顺序因为你做的每条规则放在不同链生效点完全不一样。举个典型困惑做端口转发时为什么DNAT规则写在PREROUTING而通常必须配合SNAT规则因为PREROUTING先改了目标地址让数据包知道该往哪转发但如果源地址还是外部客户端地址回包就会直接发给客户端而不是回到我们的服务器所以必须再在POSTROUTING做SNAT让回包先经过我们这台机器。5.2 最小防火墙规则集与动态加载用nftables配一个基础规则集示例写入/etc/nftables.conftable inet filter { chain input { type filter hook input priority 0; policy drop; ct state established,related accept iif lo accept tcp dport 22 accept tcp dport 80 accept tcp dport 443 accept } chain forward { type filter hook forward priority 0; policy drop; } chain output { type filter hook output priority 0; policy accept; } }这里policy drop表示默认丢弃所有包。最保险的顺序是先把放行规则写好再提policy drop。如果你正在远程操作服务器大胆设置了drop又忘记放行22端口那么恭喜你只能去机房或带外管理口“救火”了。我自己的经验是任何防火墙改动都先操作后检查并且给自己留一条回滚路径。比如iptables可以先iptables-save /tmp/fw.backupnftables先nft list ruleset /tmp/nft.backup。改动完立刻从另一个会话测试通断一旦断掉马上回滚别抱侥幸心理。5.3 DNAT端口映射与MASQUERADE经典内外网穿透需求很常见内网一台服务器192.0.2.20只跑在80端口但是外部访问入口应该是192.0.2.10的8080端口。你可以在网关这台Linux上做转发。开启内核转发先sysctl -w net.ipv4.ip_forward1 echo net.ipv4.ip_forward1 /etc/sysctl.conf然后用nftables配置nft add rule ip nat prerouting tcp dport 8080 dnat to 192.0.2.20:80 nft add rule ip nat postrouting ip saddr 192.0.2.0/24 masquerade第一条将外部访问本机8080的流量改写成目标192.0.2.20:80。第二条让转发出去的内网源地址被伪装成本机地址。如果少了第二条回包路径很可能不对称内网服务器看到源地址是外部IP自己回包时会尝试直接发给外部IP而我们这台网关根本没有做路连接自然失败。MASQUERADE跟SNAT的区别在于会动态获取出口IP适合出口地址不固定的情况。如果系统开启了firewalld也能完成类似操作firewall-cmd --add-forward-portport8080:prototcp:toport80:toaddr192.0.2.20 --permanent firewall-cmd --reload这类NAT配置在生产中经常和容器、虚拟化重叠使用。哪怕你现在不做网关掌握了DNAT和SNAT的配合关系看容器里端口映射的手册也会轻松很多。6. 常见网络故障与排查流程6.1 一条完整的排查路径不管多复杂的网络问题我都按这条路径走基本没有走偏过。先看接口链路ip link检查UPethtool ens3确认协商速率。链路层没问题再看IP层ip addr确认地址ip route确认默认网关。通了之后测DNS解析getent hosts判断系统侧解析是否正常。解析正常再测端口ss -lntp看服务监听nc -vz 192.0.2.20 80测远程端口可达性。如果还是不通直接抓包找证据。有人会问是不是一上来就抓包更省事我的回答是不要。无差别抓包容易让人陷入海量信息中反而找不到重点。先通过分层排查把范围缩到最小再抓包就是精准打击。举个例子某台服务器上的应用偶尔连接慢直观感觉是网络故障。我按路径走下来接口、地址、路由都正常但getent hosts返回结果时快时慢。这时直接dig 本地DNS域名发现响应时间抖动最后定位到DNS服务器性能问题。整个排查没抓包就定位得明明白白。6.2 高频问题速查表现象候选原因先做什么网卡显示DOWN物理链路或接口未启用ip link set ens3 up有地址但ping不通网关路由问题或网关侧防火墙ip route检查默认路由ping通但SSH连不上防火墙端口拦截 / SSH监听地址ss -lntp看22端口监听检查INPUT链域名解析失败resolv.conf被篡改 / 上游DNS不可达cat /etc/resolv.confdig 8.8.8.8连接频繁重置并发过高 / 连接数限制dmesg查连接跟踪表满ss -s看状态偶发重传网卡协商 / 中间链路丢包ethtool -S ens3查错误计数tcpdump看重传老手和新手的区别往往不在知道多少命令而在出问题时能不能按表索骥快速缩小范围。这张表帮我在值班时省下大量无效操作你完全可以照着自己的环境维护一张更细的版本。6.3 几条越早明白越好的实战心得先说改动前留退路。网络配置不像改代码可以提交后重启验证配置改错可能直接连不上机器。我每次远程改网络都先把当前配置导出并开一条“保命”会话防止改完自己连工具窗都关不掉。再说谨慎对待一切自动重写的服务。Cloud-init、NetworkManager、systemd-resolved都会按自己逻辑覆写配置。如果你的静态配置总是莫名其妙消失别怀疑同事先排查这些管理服务的状态。还有一个容易翻车的地方IPv6。很多问题表现为“偶尔连不上”最后发现是应用只监听了IPv4而客户端优先走了IPv6。排查时ss -lntp6和ping6都要会用。你的网络基础有没有真正过关就看能不能在同一台机器上把v4、v6、路由、防火墙这些因素同时理顺。最后一个小小的建议是每次排完一个网络问题把过程和结论记下来。不用写多长关键命令加结果即可。下次遇到类似case翻看自己的笔记比重新翻文档快十倍。网络基础就是在一轮轮实践中越变越扎实的没有人能跳过这一步。