ARTICLE DETAIL

资讯详情

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

Linux网络基础进阶:从ip命令到TCP/IP与故障排查实战

Linux网络基础进阶:从ip命令到TCP/IP与故障排查实战 1. 从命令输出看懂Linux网络状态三张表是基本功上次聊完Linux网络基础的第一部分配套讲的基本都是配置怎么改改IP、改网关、改DNS、重启网卡服务。那种操作属于能把机器联网的范畴但真正进入网络基础2这个阶段首先得跨过一个坎——从看懂命令输出到能根据命令输出反推系统当前的网络状态。这中间的载体就是三张表接口地址表、路由表、连接表。很多刚接触Linux的人有个习惯查IP还在用ifconfig查连接还在用netstat甚至查路由还在用route命令。不是说这些命令不能用而是它们在现代Linux发行版里基本已经被ip、ss这套iproute2工具集取代了。更重要的是ip命令输出出来的信息密度远远高于老命令但是默认格式不友好需要训练自己的眼睛。1.1 网卡与地址ip addr输出的信息分层先看最基础的ip addr缩写ip a。它的输出通常长这样$ ip addr 1: lo: LOOPBACK,UP,LOWER_UP mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: BROADCAST,MULTICAST,UP,LOWER_UP mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff inet 192.168.1.100/24 brd 192.168.1.255 scope global dynamic eth0 valid_lft 86382sec preferred_lft 86382sec inet6 fe80::5054:ff:fe12:3456/64 scope link valid_lft forever preferred_lft forever看起来很长但核心信息就几块。第一是尖括号里的状态标志UP代表这个接口是启用的LOWER_UP代表物理链路是通的网线插着、交换机端口正常。如果网线拔了你会看到NO-CARRIER这时候别急着查配置物理层先查一遍。第二是inet那行这是IPv4地址、掩码、作用域和获取方式。第三行的dynamic说明这是DHCP获取的static就是手动配置的。我排查网络问题时第一步永远是ip addr为什么因为配置层面和物理链路层的问题在这里一眼就能分辨。如果你看到IP地址正常但state DOWN那问题在接口没启用如果接口UP但NO-CARRIER那问题在物理链路。这基本上能把一半的上不了网问题分流掉。1.2 路由表数据包出网的路线图第二张表是路由表。ip route缩写ip r的输出。这是很多新手会跳过的一步但恰恰是网络不通时最需要看的一张表。$ ip route default via 192.168.1.1 dev eth0 proto dhcp metric 100 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.100这里就两行但信息量很大。第一行default via 192.168.1.1是默认路由所有目标不在本地子网的数据包都走192.168.1.1这个网关。第二行是本地子网的路由目标是192.168.1.0/24的包直接走eth0不需要网关。排查不通的问题光看默认路由是否存在是不够的还得确认网关本身通不通。我见过太多情况默认路由在但网关配置错了比如网关IP写成别的机器的IP结果所有流量都发给了错误的设备自然上不了网。这时候ping网关IP是一个极快的验证手段。1.3 连接表用ss看端口与连接状态第三张表是连接表。老派做法是用netstat -tunlp但现在我更推荐ss -tunlp。原因很简单ss的性能比netstat好一个量级尤其在连接数多的服务器上netstat可能会卡半天甚至跑不完ss基本秒出。$ ss -tunlp Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:((sshd,pid1234,fd3)) tcp LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:((nginx,pid5678,fd6))看待监听地址时要特别小心0.0.0.0:80和127.0.0.1:80的区别前者是监听所有网卡后者只监听回环地址。很多安全类面试题就藏在这类细节里服务监听在内网地址和监听在所有地址暴露面完全不一样。平时做网络基础排查或者Linux面试准备这三张表的顺序基本就是固定套路先看接口有没有地址再看路由有没有默认网关最后看端口有没有在监听。把这三步练熟了能覆盖80%的网络基础运维场景。2. TCP/IP协议栈的行为特征握手、断开与状态机聊完了命令得往下一层走。网络基础2这个阶段真正卡住人的往往不是命令记不熟而是不理解协议栈为什么要这样设计。TCP/IP里很多反直觉的地方恰恰是排查间歇性故障的钥匙。2.1 三次握手与SYN队列的核心逻辑TCP建立连接的三次握手理论大家都背得出SYN、SYN-ACK、ACK。但实际排查的时候光背这个过程没用你得知道握手是分两条路走的。第一条路是半连接队列SYN队列内核收到SYN包后把连接放到这里等ACK确认。第二条路是全连接队列accept队列三次握手完成后连接被移到这里等应用程序调用accept()取走。这两条队列都有长度上限而且上限机制在Linux上发生过变化。早期内核net.ipv4.tcp_max_syn_backlog管SYN队列net.core.somaxconn管全连接队列。但现代内核引入了tcp_syncookies之后SYN队列满了会启用syncookie机制行为又不一样。这里不展开太多只说一句经验之谈当你的服务出现端口通但连不上的情况优先查全连接队列溢出也就是ss -lnt里Send-Q那一列的值就是accept队列长度上限。2.2 TIME_WAIT与端口耗尽的那笔账TIME_WAIT可能是TCP状态机里最被误解的一个状态。很多运维看到netstat里一堆TIME_WAIT就紧张其实在主动关闭连接多的场景下典型如Nginx代理、短连接服务TIME_WAIT出现是很正常的。TIME_WAIT的作用有两个一是确保最后的ACK能到达对端万一丢了可以重发二是让属于旧连接的报文在网络里自然消失避免污染新连接。所以TIME_WAIT会持续2个MSL最大报文生存时间。在Linux上TIME_WAIT的默认保留时间是60秒这也就是为什么短连接服务每秒新建连接超过一定数量后会出现大量TIME_WAIT堆积。那怎么判断TIME_WAIT是不是病态看这条命令的输出$ ss -s Total: 128 (kernel 0) TCP: 42 (estab 8, closed 0, orphaned 0, synrecv 0, timewait 32/0), ports 0如果timewait后面的数字长期占TCP连接总数的相当比例且一直不降可能引发的问题是端口耗尽。因为每条TCP连接对应一个四元组客户端主动发起的连接会占本地端口默认net.ipv4.ip_local_port_range是32768-60999总共两万多个端口如果TIME_WAIT都占着不放新连接就没有端口可用了表现就是服务突然大量报错Cant assign requested address。这里有个重要的认知TIME_WAIT是主动关闭方的事情。如果你的服务只做被动关闭比如Nginx作为服务端由客户端主动断开TIME_WAIT大概率不会成为问题。真正需要调优的是那些充当反向代理、短连接压力大的场景这时候可以开net.ipv4.tcp_tw_reuse配合timestamp让内核安全复用TIME_WAIT状态的连接。2.3 连接状态排查的实战读法理解了状态机再看ss -state的输出就不一样了。一次典型的后端连接排查对应状态大概是这样的链路SYN-SENT → ESTABLISHED →数据传输→ FIN-WAIT-1 → FIN-WAIT-2 → TIME_WAIT如果对方端口不通连接会卡在SYN-SENT表现为请求超时如果对方进程崩了但内核还活着可能直接收到RST表现为Connection refused如果中间网络设备丢了包连接可能长期卡在ESTABLISHED但数据不通这时候就得从应用层做超时控制。提示协议栈排查最有价值的经验不是背状态而是把状态变化和具体场景对上号。看到SYN_RECV堆积想的是握手包回不去看到FIN_WAIT_2堆积想的是对端不想理你了看到CLOSE_WAIT堆积想的是你这边应用代码没调用close()。3. DNS解析的完整链路与系统的解析行为网络基础2里DNS是重头戏但这里我讲的不是怎么配DNS服务器而是理解一台Linux机器从敲下域名到拿到IP中间发生了什么以及哪些环节会出问题。这个理解比记住几条配置命令值钱得多。3.1 解析器的优先级nsswitch.conf的串联逻辑当你执行ping baidu.com程序第一件事是调用getaddrinfo()而这个函数的行为由/etc/nsswitch.conf里hosts那一行决定。默认情况下通常是hosts: files dns myhostname意思是先查/etc/hosts文件查不到再走DNS解析最后再匹配自己的主机名。这个顺序很有讲究files优先意味着你可以通过改/etc/hosts实现本机级别的域名覆盖比如屏蔽某些站点或者把内网域名映射到内网IP而完全不需要动DNS服务器。实际工作中/etc/hosts的坑往往出在格式上。正确的格式是IP地址加空格加域名一行一个。但有些人会把注释写错位置或者把IP和域名顺序写反了导致解析行为变得诡异。我见过最典型的例子是有人把127.0.0.1 localhost删了结果本机连回环地址都解析不了。3.2 resolv.conf的坑超时与重试机制/etc/resolv.conf是最容易被改坏的文件之一。一个常见的配置是nameserver 8.8.8.8 nameserver 114.114.114.114 options timeout:2 attempts:2这个文件有几个行为特性值得注意。第一nameserver最多可以配三个但解析器按顺序尝试只有前一个超时才用下一个并不是多个同时查询。第二timeout和attempts两个参数控制的是第一个nameserver超时后的行为timeout是等待单个查询的秒数attempts是重试次数。如果第一个DNS出现了丢包一个解析请求可能耗掉数秒这对在线业务是致命的。有些发行版默认不写options行导致解析器使用内置默认值可能是timeout 5秒、attempts 2次。这意味着一个DNS请求最坏情况可以拖10秒。所以做服务器初始化时我会习惯性地在resolv.conf里加上options timeout:2 attempts:1缩短等待时间快速失败。3.3 用dig判断问题在哪一层判断DNS问题最核心的命令是dig。注意它默认不带搜索域和配置文件的干扰完全按照你给的参数做原始查询所以适合定位问题。$ dig 114.114.114.114 www.example.com这行命令强制使用114这个nameserver查询绕开系统配置如果这个能查出来但系统解析失败问题就在resolv.conf配置或nsswitch顺序上如果这个也查不通那就要考虑网络到该DNS服务器的连通性或者DNS服务本身。另外记得看dig输出末尾的查询耗时和状态字段。状态是NOERROR表示域名存在NXDOMAIN表示域名不存在SERVFAIL表示服务器内部故障REFUSED表示被拒绝。这些状态码本身就是排查线索。注意不要一上来就ping域名测DNSping里看到的解析结果和DNS链路测试之间隔了好多层。先dig再ping IP再ping域名一层层剥开才是合格的做法。4. 多网卡与策略路由一张路由表搞不定的现实单网卡、单路由表的场景其实很好理解真正让人头疼的是多网卡机器。嵌入式Linux设备、双线上网的服务器、堡垒机都容易碰到这种情况。4.1 多网卡场景的核心矛盾想象一台机器有两块网卡eth0接内网eth1接外网。内网IP是192.168.1.10外网IP是203.0.113.10。默认网关只能有一个如果指向eth1的网关那去内网的流量也会被丢给外网网关结果内网不通如果指向eth0的网关那外网流量就出不去。这个问题本质上是主路由表的表达能力不够Linux默认只有一张main路由表虽然路由规则支持按目标网段分流但遇到从哪个接口进来的流量就从哪个接口回去这种需求时就得引入策略路由。4.2 ip rule与独立路由表的配合策略路由的设计思路是先匹配规则再根据规则选路由表。你可以为不同的来源IP或mark值定义不同的路由表而且每个表里可以有自己的默认网关。配置过程大概是这样的。先为主路由表之外的新表建规则比如表100用于内网ip rule add from 192.168.1.10 table 100然后在表100里声明独立的默认路由ip route add default via 192.168.1.1 dev eth0 table 100 ip route add 192.168.1.0/24 dev eth0 table 100再把主路由表里的默认路由删掉否则流量还是会优先走主表。这样来自内网地址的流量会先匹配rule进表100走eth0的网关来自其他地址的流量走main表默认路由指向eth1。这套思路在linux 网口转串口服务器这类嵌入式设备上非常常见。网口转串口设备往往同时有业务网口和管理网口两条链路不能互相干扰策略路由就是最干净的解法。配置策略路由时必须注意表ID和表名的对应关系写在/etc/iproute2/rt_tables里建议加注释说明每个表的作用不然三个月后你自己都看不懂。4.3 策略路由的验证方法配完路由后别急着说好了先用两条命令验证。$ ip route get 192.168.2.5 from 192.168.1.10 $ ip route get 8.8.8.8 from 203.0.113.10ip route get是测试路由选择的利器它会按照源地址、目的地址、规则优先级实际走一遍查表流程并告诉你该走哪个接口、哪个网关。如果结果跟预期不一致再逐条检查rule的优先级rule的priority数值越小优先级越高,默认是按添加顺序从0开始递增。5. 防火墙过滤链路iptables与nftables的排查要点说网络基础2绕不开防火墙。这里不教大家从头配置一套完整的企业防火墙策略那个篇幅不够只讲清楚一件事当业务连不上服务时怎么判断是不是防火墙在拦以及五链的基本走向。5.1 五链的数据包走向iptables有五条内置链PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING。一个数据包从网卡进来先过PREROUTING然后判断目的地址——如果是本机就进INPUT送给本地进程如果是要转发的就进FORWARD。本地进程发出的包先过OUTPUT再过POSTROUTING出去。我见过很多系统的排查误区就是分不清INPUT和FORWARD。比如一台Linux路由器两个网口之间的流量不通有人习惯性看INPUT链但INPUT只管发往本机的包转发流量根本不会经过它。这种时候应该在FORWARD链里找原因。$ iptables -L INPUT -n -v $ iptables -L FORWARD -n -v-n禁止反解-v显示计数配合起来可以看到每条规则匹配了多少包。如果计数器长时间不增长说明流量根本没走到这条规则问题得往上游找。5.2 快速定位防火墙拦截的三板斧判断是不是防火墙拦截我的习惯操作是三条命令$ iptables -L -n --line-numbers $ iptables -S $ systemctl status firewalld先看有什么规则-S能看到完整的iptables命令格式包括删除的规则再看防火墙服务是否开启。很多发行版默认用firewalld管理iptablesfirewalld和直接改iptables的规则偶尔会互相覆盖所以改规则之前先确认你在跟哪个管理端说话。如果怀疑规则太长不好排查有个临时方案加一条放行规则在不合适的地方观察计数器变化。比如你想知道http流量是不是被后面的规则拦了可以临时在INPUT链开头插一条ACCEPT tcp dport 80如果业务立刻恢复那说明确实是被后面的某条规则DROP了。定位完再删掉这条临时规则恢复原状。5.3 nftables迁移要注意的思路差异新版系统越来越倾向用nftables命令风格完全不同。iptables是链规则模型nftables是表链规则的统一框架理论上表达能力更强但排查思路要从看链变成看表和链的关联。举一个常见坑nftables默认有一个规则集可能存在多个表流量可能在某个表的INPUT链被drop。你用iptables -L查是空的就以为没有防火墙其实规则都在nftables的table里。所以在新系统上排查时我一般直接跑nft list ruleset一次性看全所有规则而不是用iptables命令去查一个已经被替代的框架。6. 真实故障排查链路一个跨网段访问超时的复盘这部分写一个我印象深刻的实际排查过程。当时一台应用服务器连着一段内网所有内网访问都很正常但访问某台跨网段的数据库时延迟极高且有间歇性超时。整个排查链路走完后发现是一件很小但很隐蔽的事。6.1 排查起点先分层还是先分段有人排查网络故障喜欢按OSI模型从物理层一层层往上查理论没错但效率太低。我的习惯是先分段客户端到服务端的路径上先确认哪一段不通。当时我先在应用服务器上ping数据库IP结果丢包率很高Ping值在几百毫秒波动。这说明网络链路有问题但还不能确定是在应用服务器到自己网关这一段还是在中间链路。于是我在同一网段的另一台机器上再ping数据库结果完全正常。这就把问题圈定在应用服务器到网关这一段。6.2 定位到网卡队列一个没人注意的配置接着查应用服务器的网卡状态。ip -s link show eth0输出里RX错误计数高得离谱而且有大量的dropped。同一个交换机的另一台机器没有这个问题所以交换机端口大概率没问题。再查网卡驱动和中断配置发现网卡多队列功能没启用中断全部打在一个CPU核心上而该核心还承载着应用进程的大量软中断处理处理不过来就开始丢包。解释一下原理现代网卡普遍支持多队列RSS就是把收包队列分散到多个CPU核心上并行处理。如果队列只有一个碰到高并发或流量突增单一CPU核心的软中断就会成为瓶颈表现为网卡层面出现丢包但物理链路完全正常。6.3 修复与验证修法也很直接。如果网卡支持用ethtool打开多队列$ ethtool -L eth0 combined 4或者确认irqbalance服务是否在跑让它自动均衡中断到多个核心$ systemctl status irqbalance改完之后再做同样的ping测试丢包消失。这次故障的根因不是IP、不是路由、不是网关而是流量处理带宽跑在了网卡中断上。如果不是靠计数器的提示光想三层以上的问题永远摸不到这个点。提示Linux网络排查有个原则——从现象往下挖但别只盯着一种可能性。ping不通可能是防火墙拦了ICMP电路没问题但业务超时可能是MTU导致分片甚至可能是nginx的worker连接数满了。多用计数器观察少用猜测试错。7. 网络基础2的进阶清单把这些命令练成肌肉记忆以上都是场景化的知识点。把它们拆成一份可以照着练的清单我按使用频率排个序建议对着真实机器操作几遍别光看不练。ip addr/ip route/ss -tunlp三张表看一切网络状态的入口ping -c 3 ip测连通性注意要ping IP别ping域名否则混入DNS变量dig ns domainDNS专项分析比nslookup详细得多traceroute -n ip或者mtr -n ip看每一跳的延迟和丢包定位中间链路问题ip -s link看网卡的错误计数、丢包计数驱动层问题的第一线索ethtool eth0看网卡速率、双工模式排查物理层协商问题iptables -L -n -v或nft list ruleset看防火墙规则和计数器ip rule看策略路由规则多网卡场景的必备命令ss -s看TCP统计总量快速判断TIME_WAIT等状态是否异常sysctl net.ipv4.*看内核协议栈参数端口范围、超时、转发开关都在这里每条命令背后的逻辑本文前面已经展开过了这里不再重复。关键是练的时候要思考输出对应的是哪一层网卡层、网络层、传输层、应用层还是防火墙层。8. 从命令到经验最常见的三个认知误区最后聊几个容易被带偏的认知这些在Linux面试题里经常出现但答案跟很多人理解的完全不一样。误区一ping不通就是网络不通。很多服务器出于安全考虑禁用了ICMP但TCP业务完全正常。用ping测出来的不通可能只是防火墙丢弃了ICMP报文。正确做法是同时用nc -vz ip port测一下具体端口看能不能建立TCP连接。误区二DNS配置了就能解析。DNS解析链条很长resolv.conf只是第一步。程序也可能绕过系统解析器直接用自己内置的DNS配置比如很多容器应用、nginx resolver指令或者被/etc/hosts里的记录干扰。改完resolv.conf后最好用getent hosts domain验证一下系统层面解析结果而不是只看到dig输出正常就认为好了。误区三丢包一定发生在物理链路。前面那个网卡队列的案例就是典型物理链路完全正常丢包发生在网卡驱动和内核之间。处理不过来时网卡会先把包丢掉。此外iptables的DROP规则、tc限速、socket缓冲区满都可能表现为丢包。判断丢包在哪一层最直观的就是看各层计数器的变化。我个人体会网络基础2这类进阶内容学的不是单个命令的用法而是排错的分层思路。数据包从网卡到应用每一层都有自己的计数器测量点和日志线索。什么时候看哪一层取决于现象的特征。把这一套分层排查的逻辑装进脑子里比你背一百条命令都管用。篇幅有限这次先聊到这里。后面有机会可以专门写一篇iptables生产配置实例把那些规则怎么dump、怎么备份、怎么原子性重载都展开讲讲。
返回列表