216 条网络命令(四):故障注入、二层配置、反例
第四篇。这一篇收尾:故障注入、二层配置、反例清单,以及这份清单真正的用法。
十二、内核计数与参数(21 条)
nstat -az
协议栈层的全部计数。
nstat -az | grep -i drop
nstat -az | grep -i conntrack
纪律:看增量,不看绝对值。
坑:只查网卡计数,漏掉协议栈层的丢弃。
cat /proc/net/softnet_stat
第二列是软中断队列丢包。
判据:它涨而网卡 rx_dropped 是 0 → CPU 处理不过来。
这是「网卡没丢包但业务丢包」的答案。
sysctl:真正需要看的几个
sysctl net.ipv4.ip_forward # 是否开了转发
sysctl net.ipv4.conf.all.rp_filter # 反向路径过滤
sysctl net.ipv4.tcp_syncookies # SYN 保护
sysctl net.ipv4.tcp_abort_on_overflow # 队列溢出时回 RST 还是丢
sysctl net.ipv4.tcp_congestion_control # 当前拥塞算法
rp_filter 的坑值得单说:
关键:最终生效取 all 与接口两者的最大值(最严的那个)。
坑:「规则对但不回包」就关掉它——那是拆防线。
正确顺序是先修路由对称(让去程和回程走同一路径)。
调优的几个常改项
sysctl -w net.core.somaxconn=4096
sysctl -w net.ipv4.tcp_congestion_control=bbr # 需内核支持
sysctl -w net.netfilter.nf_conntrack_max=524288
sysctl -w net.ipv4.neigh.default.gc_thresh3=8192
坑:tcp_congestion_control 只对新建连接生效。改了不重建连接,会看到「没用」的假象。
坑:调大上限只是把撞墙时间推后。真正的解法是缩小广播域 / 降产生速率。
cat /proc/sys/net/ipv4/ip_local_port_range
默认约 32768–60999,约 28000 个端口。
理论上限 ≈ 端口数 / 60(TIME_WAIT 时长)。
报「无法分配地址」时,先查这里 + ss -s。
十三、命名空间(4 条)
nsenter -t <pid> -n ss -tulnp
nsenter -t <pid> -n ss -tulnp | grep 8080
坑:宿主 ss 看不到容器内监听 ≠ 服务没起。
直接判「服务没起」,会浪费大量时间——这是容器排障的第一大坑。
ip netns list / ip -d link show type veth
关键:veth 成对。删掉一半会留孤儿。
十四、故障注入与守护(5 条)
flock -n 9
exec 9>/tmp/guard.lock
flock -n 9 || exit 0
单实例锁,比 PID 文件可靠。
关键:锁随进程退出由内核释放,所以锁文件永不删。
反例:退出时 rm 锁文件 → 制造竞态(A 删了,B 建了,C 也拿到锁)。
strace -e trace=connect
strace -e trace=connect curl -s -m2 http://198.51.100.77:80
本机和远端看到的完全不一样,这一条能证明:
远端视角:100% 静默丢包,SYN 重传,几十秒后 ETIMEDOUT
本机视角:connect(...) = -1 EINVAL,0 毫秒返回
原因:blackhole 路由在本机发起的路径上直接把错误返回给系统调用,包根本没生成。
判据:curl 报 after 0 ms 连不上 → 查本机策略路由,不要抓包。
网卡上一个包都没有,tcpdump 只会给你一段空白,
然后你会开始怀疑抓包过滤写错了、接口选错了——那才是真正浪费时间的开始。
先跑 ip route show type blackhole,十秒钟就有答案。
十五、二层配置与 mTLS(12 条)
排查之外,书里还有一类命令是「造环境」用的。它们不出现在故障现场,但你要复现故障、或者搭实验场时离不开。
VLAN 子接口
ip link add link eth0 name eth0.10 type vlan id 10
ip addr add 192.168.10.5/24 dev eth0.10
ip link set eth0.10 up
坑:只加子接口不 up,地址配了也不通。
坑:父接口 eth0 必须 up,子接口才可能 up(依赖关系)。
判据:ip -d link show eth0.10 能看到 vlan protocol 802.1Q id 10。
macvlan / ipvlan
ip link add mv0 link eth0 type macvlan mode bridge
ip link add iv0 link wlan0 type ipvlan mode l2
关键区别:
macvlan 给每个虚拟接口分配独立 MAC,宿主与容器同网段
ipvlan 共享父接口 MAC,只分 IP
坑:macvlan 在无线网卡上基本不可用(AP 会丢弃非本机 MAC 的帧)。
这就是为什么这里 ipvlan 挂 wlan0、macvlan 挂 eth0。
坑:macvlan 子接口与父接口之间不能直接通信(内核设计如此)。
bond
ip link add bond0 type bond mode 802.3ad
ip link set eth0 master bond0
ip link set eth1 master bond0
ip link set bond0 up
坑:一端配了 bond、对端没配 LACP → 反而更糟(部分链路被哈希到黑洞)。
判据:cat /proc/net/bonding/bond0 看 Partner Mac 是否为非零。
为零 = 对端根本没跑 LACP。
netfilter 基线(nftables 版)
nft add table inet myfilter
nft add chain inet myfilter input '{ type filter hook input priority 0 ; policy drop ; }'
nft add rule inet myfilter input ct state established,related accept
nft add rule inet myfilter input tcp dport 22 accept
关键:priority 0 是 filter 钩子的标准位置。
conntrack 那条必须排在最前面,否则回程包全被 policy drop 掉。
mTLS 客户端证书
curl --cert client.crt --key client.key https://api.example.com/
curl --cert client-chain.crt --key client.key https://api.example.com/
判据:第一行报错、第二行成功 → 服务端只认完整链,需要带上中间证书。
背景:很多服务端配了 fullchain,但客户端证书链同样可能不全。
WebSocket 握手
curl -s -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" \
-H "Sec-WebSocket-Version: 13" -H "Sec-WebSocket-Key: <16字节base64>" \
https://example.com/ws
判据:期望 101 Switching Protocols。
返回 200 说明代理没转发 Upgrade 头(常见于 Nginx 少了 proxy_set_header Upgrade)。
十六、反例清单:认出来,别照抄
| 命令/参数 | 为什么是反例 |
|---|---|
net.ipv4.tcp_tw_recycle=1 |
NAT 下会造成部分客户端连不上,Linux 4.12 已移除 |
ss -s | grep ports |
输出里没有这个字样,永远 grep 不到 |
nc -u <host> <port> |
默认不做等待,「没输出」不携带任何信息 |
全局 rp_filter=0 |
拆防线。应先修路由对称 |
iptables -A INPUT -p icmp -j DROP |
制造 PMTUD 黑洞,大包被丢小包正常,极难查 |
nf_conntrack_max 直接翻倍 |
每条约 300B 常驻不可交换,小内存机器先 OOM |
-s 1392 不给前提 |
换 MTU 就错 |
tcp_tw_reuse=1 解决服务端 TIME_WAIT |
只对出向连接生效,入向无效 |
tcp_max_tw_buckets 调得过小 |
TIME_WAIT 被提前回收,旧包到达会回 RST |
最后:这份清单真正的用法
不是「照着敲」,是「照着排除」。
正确的顺序永远是:
1. 先定层:这个现象属于 L2 / L3 / L4 / L7 的哪一层?
2. 再取证:那一层有哪几条计数/状态可以看?
3. 写预期:如果正常,我会看到什么?
4. 执行并比对:不符 → 方向;相符 → 下一层。
命令是第 4 步的事。跳过前 3 步直接找命令,你会有 216 个选项和零个方向。
清单来自《从协议到自愈》,216 条命令、31 个工具族。书里的每条命令都带「前提 / 判据 / 出处」,这里按博客可读性重排过。