当前位置:首页>Linux>Linux网络排障实战:tcpdump、ss、iptables三板斧

Linux网络排障实战:tcpdump、ss、iptables三板斧

  • 2026-02-08 20:48:59
Linux网络排障实战:tcpdump、ss、iptables三板斧

Linux网络排障实战:tcpdump、ss、iptables三板斧

一、概述

1.1 背景介绍

线上服务出问题,十有八九跟网络有关。连接超时、丢包、端口不通、防火墙误拦截,这些问题每天都在发生。我带团队这些年,处理过的网络故障少说上千次,最后总结下来,掌握tcpdump、ss、iptables这三个工具,基本能覆盖80%的网络排障场景。

剩下20%涉及交换机、路由策略、BGP这些,通常需要网络组配合。但作为运维工程师,把这三个工具用熟,至少能快速定位问题出在哪一层,不至于跟网络组扯皮时说不清楚。

实际工作中的典型场景:

  • 业务反馈接口超时,你需要确认是网络层丢包还是应用层慢 —— 用tcpdump
  • 监控告警连接数暴涨,你需要知道连接都是谁建的、什么状态 —— 用ss
  • 新上线的服务外部访问不了,你需要检查防火墙规则 —— 用iptables

1.2 技术特点

  • tcpdump内核级抓包,零外部依赖:tcpdump基于libpcap,直接在内核层面捕获网络数据包。绝大多数Linux发行版默认安装,不需要额外装任何东西。抓到的pcap文件可以拿到Wireshark里做图形化分析,排查复杂问题时非常好用。实测在万兆网卡上抓包,CPU开销不超过3%。
  • ss替代netstat,速度快10倍以上:ss直接读取内核netlink接口获取socket信息,而netstat要遍历/proc/net下的文件。在连接数超过5万的机器上,netstat执行要30秒以上,ss只需要不到1秒。生产环境早就该全面切换到ss了。
  • iptables四表五链,精确控制每一个数据包:iptables的filter、nat、mangle、raw四张表配合PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING五条链,能实现从源地址过滤到目标端口转发的所有需求。虽然nftables是未来方向,但目前生产环境iptables仍然是主流。

1.3 适用场景

  • 场景一:线上接口超时排查:业务报告某个接口响应慢或超时,需要确认是网络层面的问题(丢包、重传、延迟高)还是应用层面的问题(处理慢、队列积压)。用tcpdump抓包分析TCP握手时间、数据传输过程中的重传情况,5分钟内就能给出结论。
  • 场景二:连接数异常监控与分析:监控系统告警某台机器的TCP连接数突破阈值,需要快速定位是哪个服务、哪些客户端IP贡献了大量连接,连接处于什么状态。ss配合简单的awk统计,10秒内就能出结果。
  • 场景三:服务上线后的网络策略配置:新服务部署后需要开放特定端口、配置NAT转发、限制访问来源。iptables规则的增删改查是日常操作,搞不好就会把线上服务搞挂,必须熟练掌握。

1.4 环境要求

组件
版本要求
说明
操作系统
CentOS 7+ / Ubuntu 18.04+ / Debian 10+
内核版本建议4.9以上,ss的部分过滤功能需要较新内核
tcpdump
4.9+
低版本缺少部分过滤表达式支持,tcpdump --version查看
iproute2
4.15+
ss命令属于iproute2包,ss --version查看
iptables
1.6+
CentOS 8+默认用nftables后端,iptables命令仍可用
硬件配置
内存2GB+,磁盘预留10GB
tcpdump抓包文件可能很大,磁盘空间要留够

二、详细步骤

2.1 准备工作

2.1.1 系统检查

# 确认内核版本,4.9以上最佳
uname -r

# 检查系统版本
cat /etc/os-release

# 查看网卡信息,确认要抓包的接口名
ip addr show

# 检查磁盘空间,抓包文件可能很大
df -h /tmp

# 查看当前内存使用情况
free -h

2.1.2 安装依赖

# CentOS / RHEL
sudo yum install -y tcpdump iproute iptables-services net-tools bind-utils mtr nc

# Ubuntu / Debian
sudo apt update
sudo apt install -y tcpdump iproute2 iptables dnsutils mtr-tiny netcat-openbsd

# 验证安装
tcpdump --version
ss --version
iptables --version

一个容易踩的坑:CentOS 8及以上版本默认用firewalld管理防火墙,底层是nftables。如果你同时用iptables命令和firewalld,规则会互相覆盖。生产环境建议二选一,我们团队的做法是关掉firewalld,直接用iptables-services:

# CentOS 7/8 关闭firewalld,启用iptables
sudo systemctl stop firewalld
sudo systemctl disable firewalld
sudo systemctl mask firewalld

sudo yum install -y iptables-services
sudo systemctl enable iptables
sudo systemctl start iptables

2.2 核心配置

2.2.1 tcpdump抓包实战

tcpdump是网络排障的第一工具。很多人觉得tcpdump难用,其实掌握几个固定套路就够了。

基础语法

tcpdump [选项] [过滤表达式]

常用选项:

选项
作用
使用频率
-i eth0
指定网卡
每次必用
-n
不解析主机名,加快速度
每次必用
-nn
不解析主机名和端口名
推荐
-c 100
只抓100个包
常用
-w file.pcap
保存到文件
常用
-r file.pcap
读取pcap文件
常用
-s 0
抓完整包内容
需要看payload时用
-A
以ASCII显示包内容
排查HTTP时用
-X
以十六进制和ASCII显示
深度分析时用
-v/-vv/-vvv
详细程度递增
按需
-tttt
显示完整时间戳
推荐

按IP过滤

# 抓取与特定IP通信的所有包
tcpdump -i eth0 -nn host 192.168.1.100

# 只抓源IP
tcpdump -i eth0 -nn src host 192.168.1.100

# 只抓目标IP
tcpdump -i eth0 -nn dst host 192.168.1.100

# 抓取某个网段的流量
tcpdump -i eth0 -nn net 192.168.1.0/24

按端口过滤

# 抓取80端口的流量
tcpdump -i eth0 -nn port 80

# 抓取源端口为3306的流量(MySQL响应)
tcpdump -i eth0 -nn src port 3306

# 抓取目标端口为443的流量
tcpdump -i eth0 -nn dst port 443

# 抓取端口范围
tcpdump -i eth0 -nn portrange 8000-9000

按协议过滤

# 只抓TCP
tcpdump -i eth0 -nn tcp

# 只抓UDP
tcpdump -i eth0 -nn udp

# 只抓ICMP(排查ping不通)
tcpdump -i eth0 -nn icmp

# 只抓ARP(排查IP冲突)
tcpdump -i eth0 -nn arp

组合过滤(实际工作中最常用)

# 抓取某IP的80端口TCP流量
tcpdump -i eth0 -nn tcp and host 192.168.1.100 and port 80

# 抓取除SSH外的所有流量(排障时避免刷屏)
tcpdump -i eth0 -nn not port 22

# 抓取来自某IP且目标端口为3306或6379的流量
tcpdump -i eth0 -nn src host 10.0.1.50 and \(dst port 3306 or dst port 6379\)

# 抓取SYN包(只看新建连接)
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0'

# 抓取SYN+ACK包(看服务端响应)
tcpdump -i eth0 -nn 'tcp[tcpflags] & (tcp-syn|tcp-ack) = (tcp-syn|tcp-ack)'

# 抓取RST包(连接被重置,排查连接异常断开)
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-rst != 0'

保存和分析pcap文件

# 保存抓包结果到文件,限制100MB自动轮转,最多保留5个文件
tcpdump -i eth0 -nn -w /tmp/capture.pcap -C 100 -W 5 port 80

# 按时间轮转,每60秒一个文件
tcpdump -i eth0 -nn -w /tmp/capture_%Y%m%d_%H%M%S.pcap -G 60 port 80

# 读取pcap文件
tcpdump -nn -r /tmp/capture.pcap

# 读取pcap文件并过滤
tcpdump -nn -r /tmp/capture.pcap 'tcp and port 80 and host 10.0.1.50'

# 统计pcap文件中各IP的包数量
tcpdump -nn -r /tmp/capture.pcap | awk '{print $3}' | cut -d. -f1-4 | sort | uniq -c | sort -rn | head -20

抓HTTP请求(排查接口问题)

# 抓取HTTP GET请求
tcpdump -i eth0 -nn -A -s 0 'tcp dst port 80 and tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'

# 更简单的方式:抓80端口并显示ASCII内容
tcpdump -i eth0 -nn -A -s 0 port 80 | grep -E "GET|POST|HTTP|Host:"

# 抓取DNS查询(排查域名解析问题)
tcpdump -i eth0 -nn port 53

# 抓取DNS查询并显示详细内容
tcpdump -i eth0 -nn -vvv port 53

实战案例:排查MySQL连接超时

某天收到告警,应用连接MySQL超时率突增到5%。先在应用服务器上抓包:

# 在应用服务器上抓与MySQL服务器的通信
tcpdump -i eth0 -nn -tttt -w /tmp/mysql_debug.pcap host 10.0.2.100 and port 3306 -c 10000

# 分析TCP握手时间(SYN到SYN-ACK的间隔)
tcpdump -nn -r /tmp/mysql_debug.pcap 'tcp[tcpflags] & (tcp-syn) != 0' | head -50

# 查看重传包数量
tcpdump -nn -r /tmp/mysql_debug.pcap 'tcp[tcpflags] & tcp-syn != 0' | wc -l

# 查看RST包(连接被拒绝)
tcpdump -nn -r /tmp/mysql_debug.pcap 'tcp[tcpflags] & tcp-rst != 0' | wc -l

这次排查发现SYN到SYN-ACK的延迟从正常的0.2ms飙升到800ms,而且有大量重传。最终定位到MySQL服务器所在宿主机的网卡队列溢出,调整了ring buffer后恢复:

# 查看网卡丢包统计
ethtool -S eth0 | grep -i drop

# 查看当前ring buffer大小
ethtool -g eth0

# 调大ring buffer(需要根据网卡支持的最大值来设)
ethtool -G eth0 rx 4096 tx 4096

2.2.2 ss命令深度使用

ss是iproute2套件里的工具,用来查看socket统计信息。netstat在连接数多的机器上慢得不能忍,ss直接读netlink接口,实测5万连接的机器上ss耗时0.3秒,netstat要35秒。生产环境全面用ss替代netstat。

基础用法

# 查看所有TCP连接
ss -tn

# 查看所有监听端口
ss -tlnp

# 查看所有UDP监听
ss -ulnp

# 查看所有连接(TCP + UDP + Unix Socket)
ss -a

# 查看连接摘要统计
ss -s

ss -s的输出非常有用,一眼就能看到各状态的连接数分布:

Total: 1856
TCP:   1523 (estab 892, closed 312, orphaned 15, timewait 289, synrecv 0)

Transport    Total     IP        IPv6
RAW          2         1         1
UDP          12        8         4
TCP          1211      1089      122
INET         1225      1098      127
FRAG         0         0         0

常用选项说明

选项
作用
说明
-t
只显示TCP
最常用
-u
只显示UDP
排查DNS时用
-l
只显示监听状态
检查端口是否在监听
-n
不解析服务名
加快速度,显示端口号
-p
显示进程信息
需要root权限
-e
显示扩展信息
包含UID、inode等
-m
显示内存使用
排查内存泄漏时用
-i
显示TCP内部信息
包含RTT、拥塞窗口等
-o
显示定时器信息
看keepalive、重传计时器

按状态过滤(排障核心技能)

# 查看所有ESTABLISHED连接
ss -tn state established

# 查看所有TIME-WAIT连接
ss -tn state time-wait

# 查看所有CLOSE-WAIT连接(这个状态多了说明应用没正确关闭连接)
ss -tn state close-wait

# 查看SYN-RECV状态(SYN Flood攻击时会暴涨)
ss -tn state syn-recv

# 查看FIN-WAIT-1状态
ss -tn state fin-wait-1

# 查看除TIME-WAIT外的所有连接
ss -tn state all exclude time-wait

按地址和端口过滤

# 查看连接到本机80端口的所有连接
ss -tn dst :80
# 注意:上面这个在某些版本不好使,用下面这个更稳
ss -tn 'sport = :80'

# 查看连接到远程3306端口的连接
ss -tn 'dport = :3306'

# 查看来自某个IP的连接
ss -tn 'src 10.0.1.0/24'

# 查看到某个IP的连接
ss -tn 'dst 10.0.2.100'

# 组合过滤:来自某网段且连接到80端口
ss -tn 'src 10.0.1.0/24 and sport = :80'

# 查看端口大于1024的连接
ss -tn 'sport > :1024'

查看连接队列(排查连接建立慢的关键)

# 查看监听socket的连接队列
ss -tlnp

# 输出示例:
# State    Recv-Q  Send-Q  Local Address:Port  Peer Address:Port  Process
# LISTEN   0       128     0.0.0.0:80          0.0.0.0:*          users:(("nginx",pid=1234,fd=6))
# LISTEN   129     128     0.0.0.0:8080        0.0.0.0:*          users:(("java",pid=5678,fd=100))

对于LISTEN状态

  • Recv-Q:当前等待accept的连接数(半连接+全连接队列中已完成握手的)
  • Send-Q:backlog值,即最大队列长度

上面第二行,Recv-Q=129 > Send-Q=128,说明全连接队列已满,新连接会被丢弃。这是典型的应用处理不过来的表现。

# 查看全连接队列溢出次数
netstat -s | grep -i "listen"
# 或者
nstat -az TcpExtListenOverflows TcpExtListenDrops

统计分析(日常巡检常用)

# 统计各状态的连接数
ss -tan | awk 'NR>1 {print $1}' | sort | uniq -c | sort -rn

# 统计连接数最多的远程IP(Top 20)
ss -tn state established | awk 'NR>1 {print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20

# 统计连接到本机各端口的连接数
ss -tn state established | awk 'NR>1 {print $4}' | cut -d: -f2 | sort | uniq -c | sort -rn | head -20

# 统计TIME-WAIT连接的远程IP分布
ss -tn state time-wait | awk 'NR>1 {print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20

# 查看TCP内部信息(RTT、拥塞窗口)
ss -ti state established dst 10.0.2.100

实战案例:排查连接数暴涨

某天下午3点,监控告警某台Web服务器TCP连接数从正常的2000飙升到6万。排查过程:

# 第一步:看连接状态分布
ss -s
# 发现TIME-WAIT有5.2万个

# 第二步:看TIME-WAIT连接的目标分布
ss -tn state time-wait | awk '{print $4}' | cut -d: -f2 | sort | uniq -c | sort -rn | head -5
# 输出:
# 48923  6379
#  2100  3306
#   800  80

# 第三步:确认是Redis连接导致的
ss -tn state time-wait | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -5
# 输出:
# 48923  10.0.3.50

# 结论:应用到Redis(10.0.3.50:6379)的短连接太多

最终发现是某个开发同事写的定时任务,每次请求都新建Redis连接而不是用连接池。修复后连接数回到正常水平。临时缓解措施是调整内核参数加速TIME-WAIT回收:

# 临时生效
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.tcp_max_tw_buckets=20000

# 永久生效写入配置
echo"net.ipv4.tcp_tw_reuse = 1" >> /etc/sysctl.conf
echo"net.ipv4.tcp_max_tw_buckets = 20000" >> /etc/sysctl.conf
sysctl -p

注意tcp_tw_recycle在4.12以上内核已经被移除,不要再用了。tcp_tw_reuse只对客户端(主动发起连接的一方)有效。

2.2.3 iptables防火墙管理

iptables是Linux防火墙的核心工具。虽然CentOS 8+和Ubuntu 20.04+推firewalld和nftables,但底层逻辑是一样的,而且很多老系统还在用iptables。搞清楚四表五链的数据流向,其他防火墙工具都是换皮。

四表五链架构

四张表(按优先级从高到低):

  • raw:决定是否跳过连接跟踪(conntrack),高流量场景下用来减少开销
  • mangle:修改数据包头部(TTL、TOS等),一般用不到
  • nat:网络地址转换,做端口转发、SNAT/DNAT
  • filter:过滤数据包,决定放行还是丢弃,最常用的表

五条链:

  • PREROUTING:数据包进入路由判断之前(raw、mangle、nat表)
  • INPUT:数据包目标是本机时经过(mangle、filter表)
  • FORWARD:数据包经过本机转发时经过(mangle、filter表)
  • OUTPUT:本机产生的数据包出去时经过(raw、mangle、nat、filter表)
  • POSTROUTING:数据包离开本机之前(mangle、nat表)

数据包流向:

外部 --> PREROUTING --> 路由判断 --> INPUT --> 本机进程
                           |
                           v
                        FORWARD --> POSTROUTING --> 外部
                           ^
本机进程 --> OUTPUT --> 路由判断 --> POSTROUTING --> 外部

查看规则(排障第一步)

# 查看filter表所有规则(带行号,方便删除)
iptables -L -n --line-numbers

# 查看filter表规则(更详细,显示包计数)
iptables -L -n -v

# 查看nat表规则
iptables -t nat -L -n --line-numbers

# 查看raw表规则
iptables -t raw -L -n

# 以iptables-save格式查看(最推荐,输出可以直接用于恢复)
iptables-save

# 只看某条链
iptables -L INPUT -n --line-numbers

添加规则

# 允许SSH访问(放在INPUT链)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# 允许特定IP访问MySQL
iptables -A INPUT -s 10.0.1.0/24 -p tcp --dport 3306 -j ACCEPT

# 允许已建立的连接和相关连接通过(这条必须有,否则回包会被拦)
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 允许本地回环
iptables -A INPUT -i lo -j ACCEPT

# 允许ICMP(ping)
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT

# 拒绝其他所有入站流量
iptables -A INPUT -j DROP

# 在指定位置插入规则(插入到第3行)
iptables -I INPUT 3 -p tcp --dport 8080 -j ACCEPT

删除规则

# 按行号删除(先用--line-numbers查看行号)
iptables -D INPUT 5

# 按规则内容删除
iptables -D INPUT -p tcp --dport 8080 -j ACCEPT

# 清空某条链的所有规则(危险操作,生产环境慎用)
iptables -F INPUT

# 清空所有链的所有规则
iptables -F

NAT配置(端口转发)

# 开启内核转发(NAT必须)
echo 1 > /proc/sys/net/ipv4/ip_forward
# 永久生效
echo"net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p

# DNAT:将外部访问本机8080端口的流量转发到内网10.0.2.100:80
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 10.0.2.100:80

# 配套的FORWARD规则(允许转发流量通过)
iptables -A FORWARD -p tcp -d 10.0.2.100 --dport 80 -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

# SNAT:内网机器通过本机上网(本机外网IP为203.0.113.10)
iptables -t nat -A POSTROUTING -s 10.0.0.0/8 -o eth0 -j SNAT --to-source 203.0.113.10

# MASQUERADE:动态IP场景下的SNAT(拨号上网等)
iptables -t nat -A POSTROUTING -s 10.0.0.0/8 -o eth0 -j MASQUERADE

# 本机端口转发:将本机80端口转发到8080
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

规则持久化

# CentOS / RHEL(使用iptables-services)
service iptables save
# 规则保存在 /etc/sysconfig/iptables

# 手动保存和恢复
iptables-save > /etc/iptables.rules
iptables-restore < /etc/iptables.rules

# Ubuntu / Debian(使用iptables-persistent)
sudo apt install -y iptables-persistent
# 安装时会提示保存当前规则

# 后续保存
sudo netfilter-persistent save
# 规则保存在 /etc/iptables/rules.v4 和 rules.v6

# 开机自动加载(如果没装iptables-persistent)
# 在 /etc/rc.local 中添加:
iptables-restore < /etc/iptables.rules

实战案例:排查端口不通

开发反馈新部署的服务(端口9090)从外部访问不了,但在服务器本地curl是通的。排查过程:

# 第一步:确认服务在监听
ss -tlnp | grep 9090
# 输出:LISTEN  0  128  0.0.0.0:9090  0.0.0.0:*  users:(("java",pid=12345,fd=50))
# 监听正常,绑定的是0.0.0.0

# 第二步:检查iptables规则
iptables -L INPUT -n --line-numbers
# 输出:
# num  target  prot  opt  source       destination
# 1    ACCEPT  all   --   0.0.0.0/0    0.0.0.0/0    state RELATED,ESTABLISHED
# 2    ACCEPT  tcp   --   0.0.0.0/0    0.0.0.0/0    tcp dpt:22
# 3    ACCEPT  tcp   --   0.0.0.0/0    0.0.0.0/0    tcp dpt:80
# 4    ACCEPT  tcp   --   0.0.0.0/0    0.0.0.0/0    tcp dpt:443
# 5    DROP    all   --   0.0.0.0/0    0.0.0.0/0
# 第5条DROP规则把9090端口的流量拦截了

# 第三步:在DROP规则之前插入允许9090的规则
iptables -I INPUT 5 -p tcp --dport 9090 -j ACCEPT

# 第四步:保存规则
service iptables save

# 第五步:验证
iptables -L INPUT -n --line-numbers

规则顺序很关键,iptables是从上到下匹配的,匹配到就不再往下走。所以ACCEPT规则一定要放在DROP/REJECT之前。

2.2.4 辅助网络工具

除了三板斧之外,还有几个工具在排障时经常配合使用。

ping / traceroute / mtr

# 基础连通性测试
ping -c 10 10.0.2.100

# 带时间戳的ping(排查间歇性丢包)
ping -c 100 -D 10.0.2.100

# 设置包大小(排查MTU问题,1472+28=1500)
ping -c 5 -s 1472 -M do 10.0.2.100
# 如果报 "message too long",说明路径上有MTU小于1500的设备

# traceroute查看路由路径
traceroute -n 10.0.2.100

# TCP模式的traceroute(ICMP被封时用)
traceroute -n -T -p 80 10.0.2.100

# mtr是ping和traceroute的结合体,实时显示每一跳的丢包率和延迟
mtr -n -c 100 10.0.2.100

# mtr生成报告模式
mtr -n -r -c 200 10.0.2.100

mtr的输出比traceroute好用很多,能看到每一跳的丢包率。生产环境排查网络抖动时,我们团队的做法是跑200个包的mtr报告,发给网络组分析。

curl(HTTP层排障)

# 查看HTTP响应头
curl -I http://10.0.1.50:8080/health

# 查看详细的连接过程(DNS解析、TCP握手、TLS握手、首字节时间)
curl -w "\nDNS解析: %{time_namelookup}s\nTCP连接: %{time_connect}s\nTLS握手: %{time_appconnect}s\n首字节: %{time_starttransfer}s\n总耗时: %{time_total}s\n" -o /dev/null -s http://10.0.1.50:8080/api/test

# 指定超时时间
curl --connect-timeout 3 --max-time 10 http://10.0.1.50:8080/health

# 指定源IP发请求(多网卡机器上有用)
curl --interface 10.0.1.10 http://10.0.2.100:8080/health

# 跳过DNS直接指定IP
curl -H "Host: api.example.com" http://10.0.1.50:8080/api/test

dig / nslookup(DNS排障)

# 查询A记录
dig api.example.com

# 指定DNS服务器查询
dig @8.8.8.8 api.example.com

# 查询详细的解析过程(+trace)
dig +trace api.example.com

# 查询反向解析
dig -x 10.0.1.50

# 简洁输出(只要IP)
dig +short api.example.com

# 查询特定记录类型
dig api.example.com MX
dig api.example.com CNAME
dig api.example.com NS

nc(netcat,端口连通性测试)

# 测试TCP端口是否通
nc -zv 10.0.2.100 3306

# 测试UDP端口
nc -zuv 10.0.2.100 53

# 扫描端口范围
nc -zv 10.0.2.100 8000-9000

# 设置超时时间(秒)
nc -zv -w 3 10.0.2.100 3306

# 用nc做简单的文件传输(接收端)
nc -l 9999 > received_file

# 用nc做简单的文件传输(发送端)
nc 10.0.2.100 9999 < send_file

2.3 启动和验证

2.3.1 启动服务

iptables作为防火墙服务需要确保开机自启:

# CentOS 7 使用iptables-services
sudo systemctl start iptables
sudo systemctl enable iptables
sudo systemctl status iptables

# 确认规则已加载
iptables -L -n | head -20

# Ubuntu 使用 netfilter-persistent
sudo systemctl enable netfilter-persistent
sudo systemctl start netfilter-persistent

2.3.2 功能验证

部署完防火墙规则后,必须做验证。我们团队有个规矩:改完防火墙规则,必须从外部测试一遍所有业务端口。

# 从另一台机器验证端口连通性
for port in 22 80 443 8080 9090; do
    nc -zv -w 3 目标IP $port 2>&1
done

# 验证NAT转发是否生效
curl -s -o /dev/null -w "%{http_code}" http://外网IP:8080/health

# 验证iptables规则的包计数(看规则是否被命中)
iptables -L -n -v | grep -E "dpt:(80|443|9090)"

# 验证连接跟踪表
cat /proc/net/nf_conntrack | wc -l
# 或者
conntrack -L | wc -l

三、示例代码和配置

3.1 完整配置示例

3.1.1 生产环境iptables规则脚本

这是我们团队在生产环境用的iptables初始化脚本,经过多次迭代,覆盖了Web服务器的常见需求。直接保存为/usr/local/sbin/iptables-init.sh,赋予执行权限即可。

#!/bin/bash
# 文件路径:/usr/local/sbin/iptables-init.sh
# 功能:生产环境iptables规则初始化
# 使用方法:sudo bash /usr/local/sbin/iptables-init.sh
# 注意:执行前务必确认SSH端口正确,否则会把自己锁在外面

set -e

# ========== 配置区域 ==========
SSH_PORT=22
HTTP_PORT=80
HTTPS_PORT=443
APP_PORTS="8080 9090"
MYSQL_PORT=3306
REDIS_PORT=6379

# 允许访问MySQL和Redis的内网网段
TRUSTED_NET="10.0.0.0/8"

# 管理员IP(紧急情况下放行所有端口)
ADMIN_IPS="10.0.1.5 10.0.1.6"

# 日志前缀
LOG_PREFIX="IPTABLES-DROP: "
# ========== 配置区域结束 ==========

echo"[INFO] 开始配置iptables规则..."

# 清空现有规则
iptables -F
iptables -X
iptables -Z
iptables -t nat -F
iptables -t nat -X

# 设置默认策略
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

echo"[INFO] 默认策略已设置"

# 允许本地回环
iptables -A INPUT -i lo -j ACCEPT

# 允许已建立的连接(这条必须在最前面,否则回包会被拦)
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 管理员IP放行所有
for ip in$ADMIN_IPSdo
    iptables -A INPUT -s $ip -j ACCEPT
done

# 允许ICMP(限速防ping flood)
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 10/s --limit-burst 20 -j ACCEPT

# SSH端口(限制连接频率,防暴力破解)
iptables -A INPUT -p tcp --dport $SSH_PORT -m state --state NEW -m recent --set --name SSH
iptables -A INPUT -p tcp --dport $SSH_PORT -m state --state NEW -m recent --update --seconds 60 --hitcount 10 --name SSH -j DROP
iptables -A INPUT -p tcp --dport $SSH_PORT -j ACCEPT

# HTTP/HTTPS端口
iptables -A INPUT -p tcp --dport $HTTP_PORT -j ACCEPT
iptables -A INPUT -p tcp --dport $HTTPS_PORT -j ACCEPT

# 应用端口
for port in$APP_PORTSdo
    iptables -A INPUT -p tcp --dport $port -j ACCEPT
done

# MySQL和Redis只允许内网访问
iptables -A INPUT -s $TRUSTED_NET -p tcp --dport $MYSQL_PORT -j ACCEPT
iptables -A INPUT -s $TRUSTED_NET -p tcp --dport $REDIS_PORT -j ACCEPT

# 防SYN Flood
iptables -A INPUT -p tcp --syn -m limit --limit 100/s --limit-burst 200 -j ACCEPT
iptables -A INPUT -p tcp --syn -j DROP

# 记录被丢弃的包(限制日志频率,防止日志撑爆磁盘)
iptables -A INPUT -m limit --limit 5/min --limit-burst 10 -j LOG --log-prefix "$LOG_PREFIX" --log-level 4

# 最终拒绝(用REJECT而不是DROP,让客户端快速收到拒绝而不是等超时)
iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited

echo"[INFO] 规则配置完成"

# 保存规则
ifcommand -v service &> /dev/null && systemctl is-active iptables &> /dev/null; then
    service iptables save
echo"[INFO] 规则已保存(iptables-services)"
elifcommand -v netfilter-persistent &> /dev/null; then
    netfilter-persistent save
echo"[INFO] 规则已保存(netfilter-persistent)"
else
    iptables-save > /etc/iptables.rules
echo"[INFO] 规则已保存到 /etc/iptables.rules"
fi

# 显示最终规则
echo""
echo"========== 当前规则 =========="
iptables -L -n --line-numbers
echo""
echo"[INFO] 配置完成,请从外部验证SSH连接是否正常!"

3.1.2 网络诊断自动化脚本

线上排障时经常需要快速收集网络信息,每次手动敲命令太慢。这个脚本把常用的诊断命令打包在一起,一键生成诊断报告。

#!/bin/bash
# 文件路径:/usr/local/sbin/net-diag.sh
# 功能:网络诊断信息一键收集
# 使用方法:sudo bash /usr/local/sbin/net-diag.sh [目标IP] [目标端口]
# 输出:诊断报告保存到 /tmp/net-diag-时间戳.txt

TARGET_IP=${1:-""}
TARGET_PORT=${2:-""}
REPORT_FILE="/tmp/net-diag-$(date +%Y%m%d_%H%M%S).txt"

log() {
echo"========== $1 ==========" | tee -a "$REPORT_FILE"
}

run_cmd() {
echo">>> $1" | tee -a "$REPORT_FILE"
eval"$1" 2>&1 | tee -a "$REPORT_FILE"
echo"" | tee -a "$REPORT_FILE"
}

echo"网络诊断报告 - $(date)" | tee "$REPORT_FILE"
echo"主机名: $(hostname)" | tee -a "$REPORT_FILE"
echo"目标IP: ${TARGET_IP:-未指定}" | tee -a "$REPORT_FILE"
echo"目标端口: ${TARGET_PORT:-未指定}" | tee -a "$REPORT_FILE"
echo"" | tee -a "$REPORT_FILE"

log"1. 网卡信息"
run_cmd "ip addr show"

log"2. 路由表"
run_cmd "ip route show"

log"3. DNS配置"
run_cmd "cat /etc/resolv.conf"

log"4. TCP连接状态统计"
run_cmd "ss -s"

log"5. 连接状态分布"
run_cmd "ss -tan | awk 'NR>1 {print \$1}' | sort | uniq -c | sort -rn"

log"6. 监听端口"
run_cmd "ss -tlnp"

log"7. 连接数Top20 IP"
run_cmd "ss -tn state established | awk 'NR>1 {print \$5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20"

log"8. iptables规则"
run_cmd "iptables -L -n -v --line-numbers"
run_cmd "iptables -t nat -L -n -v --line-numbers"

log"9. 内核网络参数"
run_cmd "sysctl net.ipv4.tcp_tw_reuse"
run_cmd "sysctl net.ipv4.tcp_max_tw_buckets"
run_cmd "sysctl net.core.somaxconn"
run_cmd "sysctl net.ipv4.tcp_max_syn_backlog"
run_cmd "sysctl net.core.netdev_max_backlog"
run_cmd "sysctl net.nf_conntrack_max 2>/dev/null || echo 'conntrack模块未加载'"

log"10. 网卡丢包统计"
run_cmd "ip -s link show"

log"11. 连接跟踪表使用情况"
run_cmd "cat /proc/sys/net/netfilter/nf_conntrack_count 2>/dev/null || echo 'N/A'"
run_cmd "cat /proc/sys/net/netfilter/nf_conntrack_max 2>/dev/null || echo 'N/A'"

# 如果指定了目标IP,做连通性测试
if [ -n "$TARGET_IP" ]; then
log"12. 目标连通性测试"
    run_cmd "ping -c 5 -W 2 $TARGET_IP"
    run_cmd "traceroute -n -w 2 $TARGET_IP 2>/dev/null || echo 'traceroute未安装'"

if [ -n "$TARGET_PORT" ]; then
log"13. 目标端口测试"
        run_cmd "nc -zv -w 3 $TARGET_IP$TARGET_PORT 2>&1"
        run_cmd "curl -s -o /dev/null -w 'HTTP状态码: %{http_code}\nDNS解析: %{time_namelookup}s\nTCP连接: %{time_connect}s\n首字节: %{time_starttransfer}s\n总耗时: %{time_total}s\n' http://$TARGET_IP:$TARGET_PORT/ 2>/dev/null || echo '非HTTP服务'"
fi
fi

echo""
echo"诊断报告已保存到: $REPORT_FILE"

3.2 实际应用案例

案例一:TCP三次握手异常分析

场景描述:某微服务集群中,服务A调用服务B的接口,偶发超时(约2%的请求耗时超过3秒)。应用日志只显示"connection timeout",没有更多信息。

排查过程

第一步,在服务A所在机器上抓包:

# 抓取与服务B(10.0.3.20:8080)的通信,保存pcap
tcpdump -i eth0 -nn -tttt -w /tmp/svc_debug.pcap host 10.0.3.20 and port 8080 -c 50000
# 等待5分钟,收集足够样本

第二步,分析pcap文件中的TCP握手:

# 提取所有SYN包(新建连接的第一个包)
tcpdump -nn -r /tmp/svc_debug.pcap 'tcp[tcpflags] = tcp-syn' | wc -l
# 输出:3847

# 提取所有SYN重传(同一个源端口出现多次SYN)
tcpdump -nn -r /tmp/svc_debug.pcap 'tcp[tcpflags] = tcp-syn' | awk '{print $3}' | sort | uniq -c | sort -rn | awk '$1>1' | head -20
# 发现有78个连接出现了SYN重传

# 查看重传的SYN包时间间隔
tcpdump -nn -tttt -r /tmp/svc_debug.pcap 'tcp[tcpflags] = tcp-syn' | grep "10.0.1.10.49832"
# 输出:
# 2024-03-15 15:23:01.123456 IP 10.0.1.10.49832 > 10.0.3.20.8080: Flags [S]
# 2024-03-15 15:23:02.125123 IP 10.0.1.10.49832 > 10.0.3.20.8080: Flags [S]
# 2024-03-15 15:23:04.129456 IP 10.0.1.10.49832 > 10.0.3.20.8080: Flags [S]
# SYN重传间隔1s、2s,符合TCP指数退避

第三步,在服务B上检查:

# 检查全连接队列
ss -tlnp | grep 8080
# 输出:LISTEN  129  128  0.0.0.0:8080  0.0.0.0:*
# Recv-Q(129) > Send-Q(128),全连接队列溢出!

# 确认溢出次数
nstat -az TcpExtListenOverflows
# TcpExtListenOverflows  12847  0.0
# 溢出了12847次

# 查看当前backlog设置
sysctl net.core.somaxconn
# net.core.somaxconn = 128

解决方案

# 调大系统级backlog上限
sysctl -w net.core.somaxconn=65535
echo"net.core.somaxconn = 65535" >> /etc/sysctl.conf

# 调大半连接队列
sysctl -w net.ipv4.tcp_max_syn_backlog=65535
echo"net.ipv4.tcp_max_syn_backlog = 65535" >> /etc/sysctl.conf

sysctl -p

# 同时需要修改应用的listen backlog参数
# Nginx: listen 8080 backlog=65535;
# Java Tomcat: server.tomcat.accept-count=65535
# Go: net.Listen设置后调用 syscall.SetsockoptInt

修改后超时率从2%降到0.01%以下。

案例二:TCP连接状态监控脚本

场景描述:需要持续监控服务器的TCP连接状态变化,在连接数异常时自动告警。这个脚本我们跑在所有Web服务器和中间件服务器上,配合crontab每分钟执行一次。

实现代码

#!/bin/bash
# 文件路径:/usr/local/sbin/tcp-monitor.sh
# 功能:TCP连接状态监控,超阈值发送告警
# crontab配置:* * * * * /usr/local/sbin/tcp-monitor.sh

# ========== 配置 ==========
HOSTNAME=$(hostname)
LOG_FILE="/var/log/tcp-monitor.log"
ALERT_SCRIPT="/usr/local/sbin/send-alert.sh"

# 告警阈值
ESTABLISHED_WARN=5000
ESTABLISHED_CRIT=10000
TIME_WAIT_WARN=10000
TIME_WAIT_CRIT=30000
CLOSE_WAIT_WARN=100
CLOSE_WAIT_CRIT=500
TOTAL_WARN=20000
TOTAL_CRIT=50000
# ========== 配置结束 ==========

TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")

# 获取各状态连接数
get_count() {
    ss -tan state "$1" 2>/dev/null | tail -n +2 | wc -l
}

ESTAB=$(get_count established)
TW=$(get_count time-wait)
CW=$(get_count close-wait)
FW1=$(get_count fin-wait-1)
FW2=$(get_count fin-wait-2)
SYN_RECV=$(get_count syn-recv)
LAST_ACK=$(get_count last-ack)
TOTAL=$(ss -tan | tail -n +2 | wc -l)

# 记录日志
echo"$TIMESTAMP ESTAB=$ESTAB TW=$TW CW=$CW FW1=$FW1 FW2=$FW2 SYN_RECV=$SYN_RECV LAST_ACK=$LAST_ACK TOTAL=$TOTAL" >> "$LOG_FILE"

# 告警判断
alert() {
local level=$1
local msg=$2
echo"$TIMESTAMP [$level$msg" >> "$LOG_FILE"
if [ -x "$ALERT_SCRIPT" ]; then
$ALERT_SCRIPT"$level""$HOSTNAME""$msg"
fi
}

if [ "$TOTAL" -ge "$TOTAL_CRIT" ]; then
    alert "CRITICAL""TCP总连接数=$TOTAL 超过阈值$TOTAL_CRIT"
elif [ "$TOTAL" -ge "$TOTAL_WARN" ]; then
    alert "WARNING""TCP总连接数=$TOTAL 超过阈值$TOTAL_WARN"
fi

if [ "$ESTAB" -ge "$ESTABLISHED_CRIT" ]; then
    alert "CRITICAL""ESTABLISHED=$ESTAB 超过阈值$ESTABLISHED_CRIT"
# 自动收集Top IP信息
    TOP_IPS=$(ss -tn state established | awk 'NR>1{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -5)
echo"$TIMESTAMP [INFO] Top5 IP: $TOP_IPS" >> "$LOG_FILE"
elif [ "$ESTAB" -ge "$ESTABLISHED_WARN" ]; then
    alert "WARNING""ESTABLISHED=$ESTAB 超过阈值$ESTABLISHED_WARN"
fi

if [ "$TW" -ge "$TIME_WAIT_CRIT" ]; then
    alert "CRITICAL""TIME_WAIT=$TW 超过阈值$TIME_WAIT_CRIT"
elif [ "$TW" -ge "$TIME_WAIT_WARN" ]; then
    alert "WARNING""TIME_WAIT=$TW 超过阈值$TIME_WAIT_WARN"
fi

if [ "$CW" -ge "$CLOSE_WAIT_CRIT" ]; then
    alert "CRITICAL""CLOSE_WAIT=$CW 超过阈值$CLOSE_WAIT_CRIT,应用可能未正确关闭连接"
# CLOSE_WAIT多了一定是应用的问题,自动收集进程信息
    CW_PROCS=$(ss -tnp state close-wait | awk 'NR>1{print $6}' | sort | uniq -c | sort -rn | head -5)
echo"$TIMESTAMP [INFO] CLOSE_WAIT进程: $CW_PROCS" >> "$LOG_FILE"
elif [ "$CW" -ge "$CLOSE_WAIT_WARN" ]; then
    alert "WARNING""CLOSE_WAIT=$CW 超过阈值$CLOSE_WAIT_WARN"
fi

# 日志轮转(保留7天)
find /var/log/ -name "tcp-monitor.log.*" -mtime +7 -delete 2>/dev/null

运行结果示例

2024-03-15 15:30:01 ESTAB=2341 TW=892 CW=3 FW1=0 FW2=12 SYN_RECV=0 LAST_ACK=1 TOTAL=3249
2024-03-15 15:31:01 ESTAB=2356 TW=901 CW=3 FW1=1 FW2=8 SYN_RECV=0 LAST_ACK=0 TOTAL=3269
2024-03-15 15:32:01 ESTAB=8923 TW=15234 CW=3 FW1=2 FW2=45 SYN_RECV=12 LAST_ACK=3 TOTAL=24222
2024-03-15 15:32:01 [WARNING] TCP总连接数=24222 超过阈值20000
2024-03-15 15:32:01 [WARNING] ESTABLISHED=8923 超过阈值5000
2024-03-15 15:32:01 [WARNING] TIME_WAIT=15234 超过阈值10000

四、最佳实践和注意事项

4.1 最佳实践

4.1.1 tcpdump抓包规范

生产环境抓包不是随便抓的,搞不好会影响业务性能或者撑爆磁盘。我们团队总结了几条铁律:

  • 限制抓包数量或时间:永远不要不加-c-G参数就跑tcpdump。实测万兆网卡满载时,不限制的tcpdump每秒能产生500MB以上的pcap文件。

    # 正确做法:限制包数量
    tcpdump -i eth0 -nn -c 10000 -w /tmp/debug.pcap port 80

    # 正确做法:限制时间(300秒后自动停止)
    timeout 300 tcpdump -i eth0 -nn -w /tmp/debug.pcap port 80

    # 正确做法:限制文件大小,100MB轮转,最多5个文件
    tcpdump -i eth0 -nn -w /tmp/debug.pcap -C 100 -W 5 port 80
  • 尽量缩小过滤范围:过滤条件越精确,对系统的影响越小。

    # 不推荐:抓所有流量
    tcpdump -i eth0 -w /tmp/all.pcap

    # 推荐:精确过滤
    tcpdump -i eth0 -nn -w /tmp/debug.pcap host 10.0.2.100 and port 3306 -c 5000
  • 抓包文件放/tmp或专用目录:不要放在根分区或业务数据分区,万一文件太大不会影响业务。

  • 抓完及时清理:pcap文件很大,抓完分析完就删。我见过有人在生产服务器上留了200GB的pcap文件忘了删,直接把磁盘撑满导致服务挂了。

4.1.2 iptables规则优化

iptables规则是线性匹配的,规则越多性能越差。实测1000条规则时,每个包的匹配延迟约增加0.1ms。看起来不多,但高并发场景下累积起来很可观。

4.1.3 防火墙变更安全措施

改防火墙规则是高危操作,改错了可能直接把自己锁在外面。我们团队的做法:

  • 变更前备份当前规则

    iptables-save > /tmp/iptables-backup-$(date +%Y%m%d_%H%M%S).rules
  • 设置自动回滚:改规则之前,先设一个定时任务在10分钟后恢复原规则。确认新规则没问题后再取消定时任务。

    # 备份当前规则
    iptables-save > /tmp/iptables-rollback.rules

    # 设置10分钟后自动回滚
    echo"iptables-restore < /tmp/iptables-rollback.rules" | at now + 10 minutes

    # 执行变更
    iptables -I INPUT 5 -p tcp --dport 9090 -j ACCEPT

    # 确认没问题后,取消回滚任务
    atq          # 查看任务编号
    atrm 任务号   # 删除回滚任务
  • 远程操作时保持两个SSH会话:一个做变更,另一个保持不动。万一第一个断了,第二个还能用来恢复。

  • 永远不要远程执行iptables -P INPUT DROP后再加规则:应该先加好ACCEPT规则,最后再改默认策略。顺序搞反了就等着去机房接显示器吧。

4.2 注意事项

4.2.1 内核参数调优建议

网络排障经常涉及内核参数调整,这里列出生产环境建议值:

# /etc/sysctl.conf 网络相关参数

# TCP连接复用(客户端角色时有效)
net.ipv4.tcp_tw_reuse = 1

# TIME-WAIT socket最大数量(超过后直接销毁)
net.ipv4.tcp_max_tw_buckets = 50000

# 全连接队列上限(配合应用的backlog参数)
net.core.somaxconn = 65535

# 半连接队列上限
net.ipv4.tcp_max_syn_backlog = 65535

# 网卡接收队列长度
net.core.netdev_max_backlog = 65535

# TCP接收/发送缓冲区(最小值、默认值、最大值,单位字节)
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

# 连接跟踪表大小(每条记录约300字节,100万条约300MB内存)
net.nf_conntrack_max = 1000000
net.netfilter.nf_conntrack_tcp_timeout_established = 3600
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30

# 本地端口范围(客户端发起连接时使用)
net.ipv4.ip_local_port_range = 1024 65535

# TCP keepalive参数
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3

# 开启SYN Cookie(防SYN Flood)
net.ipv4.tcp_syncookies = 1

# TCP FIN超时时间(默认60秒,可以适当调小)
net.ipv4.tcp_fin_timeout = 15
# 使参数生效
sysctl -p

4.2.2 常见错误

错误现象
原因分析
解决方案
iptables规则保存后重启丢失
没有安装iptables-services或netfilter-persistent
CentOS装iptables-services,Ubuntu装iptables-persistent
ss显示端口在监听但外部连不上
防火墙拦截或服务绑定了127.0.0.1
检查iptables规则;检查服务绑定地址是否为0.0.0.0
tcpdump抓不到包
网卡名不对或流量走了其他接口
ip addr
确认网卡名;检查路由表确认流量走哪个接口
conntrack表满导致丢包
nf_conntrack_max设置太小
调大nf_conntrack_max,或对不需要跟踪的流量用raw表NOTRACK
iptables和firewalld冲突
两个同时运行,规则互相覆盖
二选一,关掉不用的那个
NAT不生效
没开ip_forward
sysctl -w net.ipv4.ip_forward=1
TIME-WAIT过多
短连接太多,没用连接池
应用层用连接池;调整tcp_tw_reuse和tcp_max_tw_buckets

4.2.3 兼容性问题

  • iptables vs nftables:CentOS 8+和Ubuntu 20.04+默认用nftables后端。iptables命令仍然可用(通过iptables-nft兼容层),但iptables-save的输出格式可能不同。如果需要在新旧系统间迁移规则,建议统一用iptables-legacy或全部切换到nft命令。

  • ss版本差异:老版本的ss(iproute2 < 4.15)不支持部分过滤语法,比如ss -tn state time-wait在某些老系统上需要写成ss -tn -o state time-wait。遇到语法报错时先检查版本。

  • tcpdump在容器中的使用:在Docker容器内抓包需要--cap-add=NET_ADMIN权限。更好的做法是在宿主机上用nsenter进入容器的网络命名空间抓包:

    # 获取容器PID
    PID=$(docker inspect -f '{{.State.Pid}}' 容器名)

    # 进入容器网络命名空间抓包
    nsenter -t $PID -n tcpdump -i eth0 -nn port 80 -c 100

五、故障排查和监控

5.1 故障排查

5.1.1 日志查看

网络问题的日志分散在好几个地方,要养成习惯逐个检查:

# 查看系统日志中的网络相关信息
journalctl -k | grep -iE "drop|reject|error|link|eth|net" | tail -50

# 查看iptables丢弃日志(前面配置了LOG规则的话)
grep "IPTABLES-DROP" /var/log/messages | tail -30
# Ubuntu系统
grep "IPTABLES-DROP" /var/log/kern.log | tail -30

# 查看dmesg中的网络错误
dmesg | grep -iE "link|eth|net|drop|error|nf_conntrack" | tail -30

# 查看conntrack表满的告警
dmesg | grep "nf_conntrack: table full"

# 实时监控内核日志
dmesg -wH

5.1.2 常见问题排查

问题一:端口监听正常但外部访问不通

这是最常见的网络问题,排查思路是从内到外逐层检查:

# 第一步:确认服务在监听,且绑定地址不是127.0.0.1
ss -tlnp | grep 8080
# 如果显示 127.0.0.1:8080 说明只监听了本地,需要改成 0.0.0.0:8080

# 第二步:本机测试
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8080/health
# 返回200说明服务本身没问题

# 第三步:检查iptables
iptables -L INPUT -n -v --line-numbers | grep -E "8080|DROP|REJECT"
# 看8080端口是否有ACCEPT规则,以及DROP/REJECT规则的位置

# 第四步:临时关闭防火墙测试(确认是不是防火墙的问题)
# 注意:生产环境慎用,测完立刻恢复
iptables-save > /tmp/iptables-backup.rules
iptables -F INPUT
iptables -P INPUT ACCEPT
# 测试完恢复
iptables-restore < /tmp/iptables-backup.rules

# 第五步:检查云平台安全组(如果是云服务器)
# AWS/阿里云/腾讯云都有安全组,这个在OS层面看不到
# 需要去云控制台检查

解决方案

  1. 服务绑定地址改为0.0.0.0
  2. 添加iptables ACCEPT规则
  3. 检查云平台安全组放行对应端口

问题二:TCP连接建立慢(首包延迟高)

用户反馈接口偶尔响应慢,但服务端日志显示处理时间正常。这种情况大概率是网络层的问题。

# 用curl精确测量各阶段耗时
curl -w "DNS: %{time_namelookup}s\nTCP: %{time_connect}s\nTLS: %{time_appconnect}s\n首字节: %{time_starttransfer}s\n总计: %{time_total}s\n" -o /dev/null -s http://10.0.2.100:8080/api/test

# 如果TCP连接时间异常(正常内网应该<1ms)
# 在客户端抓SYN和SYN-ACK
tcpdump -i eth0 -nn -tttt 'tcp[tcpflags] & (tcp-syn) != 0' and host 10.0.2.100 -c 200

# 检查服务端的全连接队列是否溢出
ssh 10.0.2.100 "ss -tlnp | grep 8080; nstat -az TcpExtListenOverflows"

# 检查网络路径上的丢包
mtr -n -r -c 100 10.0.2.100

解决方案

  1. 全连接队列溢出 -> 调大somaxconn和应用backlog
  2. 网络路径丢包 -> 联系网络组检查交换机/路由器
  3. 网卡队列溢出 -> 调大ring buffer,开启多队列

问题三:CLOSE_WAIT连接持续增长

CLOSE_WAIT状态说明对端已经关闭连接(发了FIN),但本端应用没有调用close()。这100%是应用的bug。

# 查看CLOSE_WAIT连接数量和归属进程
ss -tnp state close-wait

# 按进程统计CLOSE_WAIT数量
ss -tnp state close-wait | awk '{print $NF}' | sort | uniq -c | sort -rn

# 查看具体是连接到哪些远程地址
ss -tn state close-wait | awk 'NR>1{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -10
  • 症状:CLOSE_WAIT连接数持续增长,不会自动减少
  • 排查:确认是哪个进程、连接到哪个远程服务
  • 解决:修复应用代码,确保HTTP客户端/数据库连接等资源正确关闭。临时措施可以重启应用进程释放连接

问题四:conntrack表满导致间歇性丢包

高并发服务器上经常遇到的问题。conntrack表满了之后,新连接会被直接丢弃,表现为间歇性连接超时。

# 检查conntrack表使用情况
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max
# 如果count接近max,就是表满了

# 查看dmesg确认
dmesg | grep "nf_conntrack: table full"

# 查看conntrack表中各状态的分布
conntrack -L 2>/dev/null | awk '{print $4}' | sort | uniq -c | sort -rn

解决方案

# 方案一:调大conntrack表(每条约300字节,100万条约300MB)
sysctl -w net.nf_conntrack_max=1000000
echo"net.nf_conntrack_max = 1000000" >> /etc/sysctl.conf

# 缩短各状态的超时时间
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=3600
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_close_wait=60
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_fin_wait=30

# 方案二:对不需要跟踪的流量跳过conntrack(比如Web服务器的80/443端口)
iptables -t raw -A PREROUTING -p tcp --dport 80 -j NOTRACK
iptables -t raw -A PREROUTING -p tcp --sport 80 -j NOTRACK
iptables -t raw -A OUTPUT -p tcp --sport 80 -j NOTRACK
iptables -t raw -A OUTPUT -p tcp --dport 80 -j NOTRACK
# 注意:NOTRACK的流量不能使用state匹配,需要单独加ACCEPT规则
iptables -A INPUT -p tcp --dport 80 -j ACCEPT

5.1.3 调试模式

有些网络问题比较隐蔽,需要开启更详细的调试信息。

# 开启iptables的TRACE功能(跟踪数据包经过的每条链和规则)
modprobe nf_log_ipv4
sysctl -w net.netfilter.nf_log.2=nf_log_ipv4

# 对特定流量开启TRACE
iptables -t raw -A PREROUTING -p tcp --dport 8080 -s 10.0.1.50 -j TRACE
iptables -t raw -A OUTPUT -p tcp --sport 8080 -d 10.0.1.50 -j TRACE

# 查看TRACE日志
journalctl -k -f | grep TRACE
# 或者
tail -f /var/log/kern.log | grep TRACE

# 输出示例:
# TRACE: raw:PREROUTING:policy:2 IN=eth0 ... SRC=10.0.1.50 DST=10.0.2.100 ... DPT=8080
# TRACE: filter:INPUT:rule:3 IN=eth0 ... SRC=10.0.1.50 DST=10.0.2.100 ... DPT=8080

# 排查完毕后关闭TRACE(TRACE会产生大量日志)
iptables -t raw -D PREROUTING -p tcp --dport 8080 -s 10.0.1.50 -j TRACE
iptables -t raw -D OUTPUT -p tcp --sport 8080 -d 10.0.1.50 -j TRACE

TCP层面的调试

# 查看TCP重传统计
nstat -az | grep -i retrans
# TcpRetransSegs  重传的段数
# TcpExtTCPSlowStartRetrans  慢启动阶段的重传

# 查看TCP错误统计
nstat -az | grep -iE "abort|reset|overflow|drop"

# 实时监控TCP统计变化(每秒刷新)
watch -n 1 "nstat -az | grep -iE 'retrans|overflow|drop|abort' | grep -v ' 0 '"

# 查看某个连接的详细TCP信息(RTT、拥塞窗口、重传次数)
ss -ti dst 10.0.2.100
# 输出示例:
# cubic wscale:7,7 rto:204 rtt:0.523/0.05 ato:40 mss:1448 pmtu:1500
# rcvmss:1448 advmss:1448 cwnd:10 bytes_sent:1234 bytes_acked:1234
# bytes_received:5678 segs_out:50 segs_in:60 data_segs_out:25 data_segs_in:30
# send 221.5Mbps lastsnd:100 lastrcv:50 lastack:50 pacing_rate 442.9Mbps
# delivery_rate 180.2Mbps delivered:26 busy:200ms

5.2 性能监控

5.2.1 关键指标监控

日常巡检和故障排查时需要关注的核心网络指标:

# 网卡流量(每秒刷新)
watch -n 1 "cat /proc/net/dev | awk 'NR>2{printf \"%-12s RX: %10d bytes  TX: %10d bytes\n\", \$1, \$2, \$10}'"

# 更直观的方式用sar(需要安装sysstat)
sar -n DEV 1 5

# 网卡错误和丢包
ip -s link show eth0

# TCP连接状态实时监控
watch -n 2 "ss -s"

# 连接跟踪表使用率
watch -n 5 "echo \"conntrack: $(cat /proc/sys/net/netfilter/nf_conntrack_count)/$(cat /proc/sys/net/netfilter/nf_conntrack_max)\""

# 网卡队列统计(需要ethtool)
ethtool -S eth0 | grep -E "rx_|tx_" | grep -v ": 0$"

# 软中断分布(网络密集型服务器要关注)
cat /proc/softirqs | grep -E "NET_RX|NET_TX"

# 查看各CPU的软中断处理情况(判断是否需要开启RPS/RFS)
cat /proc/interrupts | grep eth0

5.2.2 监控指标说明

指标名称
正常范围
告警阈值
说明
TCP ESTABLISHED连接数
业务相关,通常<5000
>10000
突增说明有异常流量或连接泄漏
TCP TIME_WAIT连接数
<5000
>20000
过多说明短连接太多,需要用连接池
TCP CLOSE_WAIT连接数
<10
>100
任何持续增长都是应用bug
conntrack表使用率
<70%
>85%
满了会丢弃新连接
网卡丢包率
0
>0.01%
任何丢包都需要关注
TCP重传率
<0.1%
>1%
高重传说明网络质量差
全连接队列溢出
0
>0(持续增长)
说明应用处理不过来
网卡带宽使用率
<60%
>80%
接近满载需要扩容或限流

5.2.3 Prometheus监控告警配置

用node_exporter采集网络指标,配合Prometheus告警规则,实现自动化监控。node_exporter默认就会采集网络相关的指标,不需要额外配置。

# Prometheus告警规则文件:/etc/prometheus/rules/network_alerts.yml
groups:
-name:network_alerts
rules:
# TCP连接数过高
-alert:TcpConnectionsHigh
expr:node_netstat_Tcp_CurrEstab>10000
for:5m
labels:
severity:warning
annotations:
summary:"TCP连接数过高 {{ $labels.instance }}"
description:"当前ESTABLISHED连接数: {{ $value }},超过10000阈值"

# TIME_WAIT过多
-alert:TcpTimeWaitHigh
expr:node_sockstat_TCP_tw>20000
for:5m
labels:
severity:warning
annotations:
summary:"TIME_WAIT连接过多 {{ $labels.instance }}"
description:"当前TIME_WAIT数: {{ $value }}"

# conntrack表使用率过高
-alert:ConntrackTableNearFull
expr:node_nf_conntrack_entries/node_nf_conntrack_entries_limit*100>85
for:2m
labels:
severity:critical
annotations:
summary:"conntrack表即将满 {{ $labels.instance }}"
description:"使用率: {{ $value | printf \"%.1f\" }}%"

# 网卡丢包
-alert:NetworkInterfaceDrops
expr:rate(node_network_receive_drop_total[5m])>0
for:5m
labels:
severity:warning
annotations:
summary:"网卡丢包 {{ $labels.instance }}{{ $labels.device }}"
description:"丢包速率: {{ $value | printf \"%.2f\" }}/s"

# TCP重传率过高
-alert:TcpRetransmissionHigh
expr:rate(node_netstat_Tcp_RetransSegs[5m])/rate(node_netstat_Tcp_OutSegs[5m])*100>1
for:10m
labels:
severity:warning
annotations:
summary:"TCP重传率过高 {{ $labels.instance }}"
description:"重传率: {{ $value | printf \"%.2f\" }}%"

# 全连接队列溢出
-alert:ListenOverflows
expr:rate(node_netstat_TcpExt_ListenOverflows[5m])>0
for:2m
labels:
severity:critical
annotations:
summary:"全连接队列溢出 {{ $labels.instance }}"
description:"溢出速率: {{ $value | printf \"%.2f\" }}/s,应用处理不过来"

# 网卡带宽使用率
-alert:NetworkBandwidthHigh
expr:(rate(node_network_transmit_bytes_total{device="eth0"}[5m])*8)/1000000000*100>80
for:10m
labels:
severity:warning
annotations:
summary:"网卡带宽使用率过高 {{ $labels.instance }}"
description:"出方向带宽使用率: {{ $value | printf \"%.1f\" }}%"

5.3 备份与恢复

5.3.1 iptables规则备份策略

防火墙规则是服务器安全的最后一道防线,必须有备份。我们团队的做法是每天自动备份一次,保留30天。

#!/bin/bash
# 文件路径:/usr/local/sbin/iptables-backup.sh
# crontab配置:0 2 * * * /usr/local/sbin/iptables-backup.sh

BACKUP_DIR="/opt/backup/iptables"
KEEP_DAYS=30
DATE=$(date +%Y%m%d_%H%M%S)
HOSTNAME=$(hostname)

mkdir -p "$BACKUP_DIR"

# 备份iptables规则
iptables-save > "${BACKUP_DIR}/${HOSTNAME}_iptables_${DATE}.rules"

# 备份内核网络参数
sysctl -a 2>/dev/null | grep -E "^net\." > "${BACKUP_DIR}/${HOSTNAME}_sysctl_${DATE}.conf"

# 如果有ipset,也备份
ifcommand -v ipset &> /dev/null; then
    ipset save > "${BACKUP_DIR}/${HOSTNAME}_ipset_${DATE}.rules" 2>/dev/null
fi

# 清理过期备份
find "$BACKUP_DIR" -name "*.rules" -mtime +${KEEP_DAYS} -delete
find "$BACKUP_DIR" -name "*.conf" -mtime +${KEEP_DAYS} -delete

echo"[$(date)] iptables备份完成: ${BACKUP_DIR}/${HOSTNAME}_iptables_${DATE}.rules"

5.3.2 恢复流程

恢复防火墙规则的操作步骤。恢复前一定要确认备份文件的内容是正确的,不要恢复了一个有问题的规则把自己锁在外面。

  1. 检查备份文件内容

    # 先看一下备份文件的内容,确认规则是合理的
    cat /opt/backup/iptables/web01_iptables_20240315_020000.rules

    # 确认里面有SSH的ACCEPT规则
    grep "dpt:22" /opt/backup/iptables/web01_iptables_20240315_020000.rules
  2. 恢复规则

    # 恢复iptables规则
    iptables-restore < /opt/backup/iptables/web01_iptables_20240315_020000.rules
  3. 验证规则

    # 查看恢复后的规则
    iptables -L -n --line-numbers

    # 从外部测试SSH连接
    # 从外部测试业务端口
  4. 持久化

    # CentOS
    service iptables save

    # Ubuntu
    netfilter-persistent save

六、总结

6.1 技术要点回顾

  • tcpdump是网络排障的起点:遇到网络问题先抓包,不要猜。抓包结果是客观证据,能快速判断问题出在哪一层。记住-nn -tttt -w三个常用选项,过滤表达式掌握host、port、tcp flags这几个就够应付大多数场景。
  • ss是连接状态分析的利器:替代netstat,速度快一个数量级。ss -s看全局概览,ss -tn state xxx按状态过滤,ss -tlnp看监听队列。CLOSE_WAIT持续增长一定是应用bug,TIME_WAIT过多要用连接池。
  • iptables规则顺序决定一切:ESTABLISHED,RELATED放第一条,ACCEPT放在DROP/REJECT之前。改规则前备份,设自动回滚。大量IP封禁用ipset。
  • 内核参数调优是基础功:somaxconn、tcp_max_syn_backlog、nf_conntrack_max这几个参数,生产环境部署时就应该调好,不要等出了问题再改。

6.2 排障思路总结

网络问题的排查有一套固定的方法论,按层次从下往上排查:

  1. 物理层/链路层:网线是否插好、网卡是否UP、有没有丢包(ip -s link show
  2. 网络层:IP是否可达、路由是否正确(pingtraceroutemtr
  3. 传输层:端口是否监听、TCP握手是否正常、有没有重传(sstcpdump
  4. 防火墙:iptables/安全组是否放行(iptables -L -n -v
  5. 应用层:服务是否正常响应(curl、应用日志)

90%的网络问题在第3和第4层,所以tcpdump、ss、iptables这三个工具用熟了,排障效率会提升很多。

6.3 进阶学习方向

  1. eBPF/BCC工具集:比tcpdump更底层的网络观测工具,能在内核态做过滤和聚合,对性能影响更小。推荐从tcplifetcpretranstcpconnect这几个BCC工具开始学。

    • 学习资源:Brendan Gregg的《BPF Performance Tools》
    • 实践建议:先在测试环境装bcc-tools,用tcpretrans替代tcpdump抓重传
  2. nftables:iptables的替代品,语法更统一,性能更好。CentOS 9和Ubuntu 22.04已经默认使用nftables。迟早要迁移,建议提前学。

    • 学习资源:nftables wiki(https://wiki.nftables.org)
    • 实践建议:先在测试环境用nft list ruleset查看当前规则,对比iptables-save的输出
  3. Wireshark深度分析:tcpdump抓包后用Wireshark做图形化分析,能看到TCP流的时序图、重传统计、RTT分布等。排查复杂的TCP性能问题时非常有用。

    • 学习资源:Wireshark官方文档和Chris Sanders的《Practical Packet Analysis》
    • 实践建议:把生产环境的pcap文件下载到本地用Wireshark分析,重点学会用Statistics菜单下的各种统计功能

6.4 参考资料

  • tcpdump官方手册 - 过滤表达式的完整语法参考
  • iproute2文档 - ss命令的详细用法
  • netfilter/iptables项目 - iptables官方文档和FAQ
  • Linux内核网络参数 - 所有net.*内核参数的说明
  • Brendan Gregg的网络工具图 - Linux性能工具全景图

附录

A. 命令速查表

# ==================== tcpdump 速查 ====================
tcpdump -i eth0 -nn host 10.0.1.50                          # 抓指定IP的包
tcpdump -i eth0 -nn port 80                                  # 抓指定端口
tcpdump -i eth0 -nn tcp and host 10.0.1.50 and port 80      # 组合过滤
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0'# 只抓SYN包
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-rst != 0'# 只抓RST包
tcpdump -i eth0 -nn -c 5000 -w /tmp/cap.pcap port 80        # 保存到文件
tcpdump -nn -r /tmp/cap.pcap                                 # 读取pcap文件
tcpdump -i eth0 -nn -A -s 0 port 80                         # 显示HTTP内容
tcpdump -i eth0 -nn not port 22                              # 排除SSH流量
tcpdump -i eth0 -nn -tttt port 53                            # 抓DNS带时间戳

# ==================== ss 速查 ====================
ss -s                                                         # 连接状态摘要
ss -tlnp                                                      # 查看所有TCP监听端口
ss -tn                                                        # 查看所有TCP连接
ss -tn state established                                      # 只看ESTABLISHED
ss -tn state time-wait                                        # 只看TIME-WAIT
ss -tn state close-wait                                       # 只看CLOSE-WAIT
ss -tn 'dport = :3306'# 过滤目标端口
ss -tn 'src 10.0.1.0/24'# 过滤源网段
ss -ti dst 10.0.2.100                                         # 查看TCP内部信息
ss -tnp state close-wait                                      # CLOSE-WAIT带进程信息

# ==================== iptables 速查 ====================
iptables -L -n --line-numbers                                 # 查看filter表规则
iptables -L -n -v                                             # 查看规则带包计数
iptables -t nat -L -n --line-numbers                          # 查看nat表规则
iptables-save                                                 # 导出所有规则
iptables-restore < rules.file                                 # 导入规则
iptables -A INPUT -p tcp --dport 80 -j ACCEPT                # 添加规则
iptables -I INPUT 3 -p tcp --dport 8080 -j ACCEPT            # 插入到第3行
iptables -D INPUT 5                                           # 删除第5条规则
iptables -F INPUT                                             # 清空INPUT链
iptables -P INPUT DROP                                        # 设置默认策略

# ==================== 辅助工具速查 ====================
ping -c 10 10.0.2.100                                         # 连通性测试
mtr -n -r -c 100 10.0.2.100                                   # 路径丢包分析
nc -zv -w 3 10.0.2.100 3306                                   # TCP端口测试
dig +short api.example.com                                     # DNS查询
dig @8.8.8.8 api.example.com                                   # 指定DNS服务器
curl -w "TCP:%{time_connect}s Total:%{time_total}s\n" -o /dev/null -s URL  # HTTP耗时分析
nstat -az | grep -i retrans                                    # TCP重传统计
conntrack -L | wc -l                                           # conntrack表条目数
ethtool -S eth0 | grep -i drop                                 # 网卡丢包统计
ip -s link show eth0                                           # 网卡流量统计

B. 关键内核网络参数详解

参数
默认值
建议值
说明
net.core.somaxconn
128
65535
全连接队列上限,listen()的backlog不能超过这个值
net.ipv4.tcp_max_syn_backlog
128/256
65535
半连接队列上限,SYN Flood时会被打满
net.core.netdev_max_backlog
1000
65535
网卡接收队列长度,高流量时调大防丢包
net.ipv4.tcp_tw_reuse
0
1
允许复用TIME-WAIT连接,仅对客户端有效
net.ipv4.tcp_max_tw_buckets
各版本不同
50000
TIME-WAIT最大数量,超过直接销毁
net.ipv4.tcp_fin_timeout
60
15
FIN-WAIT-2状态超时时间(秒)
net.ipv4.tcp_keepalive_time
7200
600
TCP keepalive探测间隔(秒)
net.ipv4.tcp_keepalive_intvl
75
30
keepalive探测失败后重试间隔(秒)
net.ipv4.tcp_keepalive_probes
9
3
keepalive探测失败重试次数
net.ipv4.tcp_syncookies
1
1
SYN Cookie防护,半连接队列满时启用
net.ipv4.ip_local_port_range
32768 60999
1024 65535
本地端口范围,客户端角色时影响并发连接数
net.ipv4.ip_forward
0
按需开启
IP转发,做NAT网关时必须开启
net.nf_conntrack_max
65536
1000000
conntrack表最大条目数
net.netfilter.nf_conntrack_tcp_timeout_established
432000
3600
ESTABLISHED状态conntrack超时(秒),默认5天太长
net.netfilter.nf_conntrack_tcp_timeout_time_wait
120
30
TIME-WAIT状态conntrack超时(秒)
net.ipv4.tcp_rmem
4096 87380 6291456
4096 87380 16777216
TCP接收缓冲区(最小/默认/最大,字节)
net.ipv4.tcp_wmem
4096 16384 4194304
4096 65536 16777216
TCP发送缓冲区(最小/默认/最大,字节)

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-02-09 02:06:33 HTTP/2.0 GET : https://f.mffb.com.cn/a/474403.html
  2. 运行时间 : 0.102646s [ 吞吐率:9.74req/s ] 内存消耗:5,042.14kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=1251d6c741171c8bf6b02124eca51408
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000680s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001030s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000373s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000282s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000622s ]
  6. SELECT * FROM `set` [ RunTime:0.000261s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000683s ]
  8. SELECT * FROM `article` WHERE `id` = 474403 LIMIT 1 [ RunTime:0.000689s ]
  9. UPDATE `article` SET `lasttime` = 1770573993 WHERE `id` = 474403 [ RunTime:0.013391s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.004675s ]
  11. SELECT * FROM `article` WHERE `id` < 474403 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.003466s ]
  12. SELECT * FROM `article` WHERE `id` > 474403 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000562s ]
  13. SELECT * FROM `article` WHERE `id` < 474403 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.001039s ]
  14. SELECT * FROM `article` WHERE `id` < 474403 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.004117s ]
  15. SELECT * FROM `article` WHERE `id` < 474403 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.001951s ]
0.104663s