netstat 是 Linux 中一个显示网络连接、路由表、接口统计等网络相关信息的经典工具。它提供了系统网络状态的全面视图,是网络故障排查和性能分析的重要工具。
📖 基本语法
bash
netstat [选项]
重要特性:
- 显示网络连接状态
- 显示路由表信息
- 显示接口统计信息
- 显示多播组成员
- 显示网络协议统计
🎯 常用选项
| 选项 | 说明 |
|---|---|
-a, --all |
显示所有连接和监听端口。 |
-t, --tcp |
仅显示 TCP 连接。 |
-u, --udp |
仅显示 UDP 连接。 |
-n, --numeric |
以数字形式显示地址和端口,不解析主机名和服务名。 |
-l, --listening |
仅显示监听状态的套接字。 |
-p, --program |
显示每个连接所属的进程 ID 和程序名。 |
-r, --route |
显示路由表。 |
-i, --interfaces |
显示网络接口统计信息。 |
-s, --statistics |
显示每个协议的统计信息。 |
-c, --continuous |
连续输出,每隔一秒刷新一次。 |
-e, --extend |
显示扩展信息。 |
-o, --timers |
显示计时器信息。 |
-g, --groups |
显示多播组成员信息。 |
-4, --inet |
仅显示 IPv4 连接。 |
-6, --inet6 |
仅显示 IPv6 连接。 |
-C, --cache |
显示路由缓存。 |
-F, --fib |
显示转发信息库。 |
-W, --wide |
不截断 IP 地址。 |
-h, --help |
显示帮助信息。 |
-V, --version |
显示版本信息。 |
💡 核心用法示例
1. 显示所有连接
bash
# 显示所有连接(包括监听和非监听)
netstat -a
# 显示所有 TCP 连接
netstat -at
# 显示所有 UDP 连接
netstat -au
# 显示所有连接(数字形式)
netstat -an
# 显示所有连接,包含进程信息
netstat -ap
# 显示所有 IPv4 连接
netstat -4a
# 显示所有 IPv6 连接
netstat -6a
2. 显示监听端口
bash
# 显示所有监听端口
netstat -l
# 显示 TCP 监听端口
netstat -lt
# 显示 UDP 监听端口
netstat -lu
# 显示监听端口(数字形式)
netstat -ln
# 显示监听端口,包含进程信息
netstat -lp
# 显示 IPv4 监听端口
netstat -4l
# 显示 IPv6 监听端口
netstat -6l
3. 显示路由表
bash
# 显示路由表
netstat -r
# 显示路由表(数字形式)
netstat -rn
# 显示路由缓存
netstat -C
# 显示内核路由表
netstat -e
# 显示详细路由信息
netstat --verbose -r
4. 显示接口统计
bash
# 显示所有接口统计
netstat -i
# 显示扩展接口统计
netstat -ie
# 显示接口统计(数字形式)
netstat -in
# 显示特定接口统计
netstat -i eth0
# 显示接口统计,包含错误信息
netstat -s -i
5. 显示协议统计
bash
# 显示所有协议统计
netstat -s
# 显示 TCP 协议统计
netstat -st
# 显示 UDP 协议统计
netstat -su
# 显示 ICMP 协议统计
netstat -si
# 显示 IP 协议统计
netstat -sp ip
# 显示详细协议统计
netstat --statistics --verbose
6. 实用组合命令
bash
# 最常用的组合:显示所有 TCP 连接,包含进程信息,数字形式
netstat -tunap
# 显示所有监听端口,包含进程信息
netstat -tunlp
# 显示所有 ESTABLISHED 连接
netstat -tunap | grep ESTABLISHED
# 显示所有 TIME_WAIT 连接
netstat -tunap | grep TIME_WAIT
# 显示所有 LISTEN 连接
netstat -tunap | grep LISTEN
# 显示特定端口的连接
netstat -tunap | grep :80
# 显示特定进程的连接
netstat -tunap | grep nginx
# 显示特定用户的连接
netstat -tunap | grep username
# 显示连接数统计
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
# 实时监控网络连接
watch -n 1 'netstat -tunap'
📊 输出字段解释
连接信息字段
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1234/sshd
tcp 0 0 192.168.1.100:22 192.168.1.50:54321 ESTABLISHED 5678/sshd: user
- Proto:协议类型(tcp、udp、raw)
- Recv-Q:接收队列大小(字节)
- Send-Q:发送队列大小(字节)
- Local Address:本地地址和端口
- Foreign Address:远程地址和端口
- State:连接状态
- PID/Program name:进程 ID 和程序名
TCP 连接状态
| 状态 | 说明 |
|---|---|
LISTEN |
监听状态,等待连接请求。 |
SYN_SENT |
已发送连接请求,等待确认。 |
SYN_RECV |
收到连接请求,等待确认。 |
ESTABLISHED |
连接已建立,数据传输中。 |
FIN_WAIT1 |
已发送关闭请求,等待确认。 |
FIN_WAIT2 |
收到关闭确认,等待对方关闭。 |
TIME_WAIT |
等待足够时间确保远程 TCP 收到连接中断请求。 |
CLOSE_WAIT |
收到关闭请求,等待本地关闭。 |
LAST_ACK |
等待先前发送的关闭请求的确认。 |
CLOSING |
双方同时尝试关闭连接。 |
CLOSED |
连接已关闭。 |
路由表字段
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.1.1 0.0.0.0 UG 100 0 0 eth0
192.168.1.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
- Destination:目标网络或主机
- Gateway:网关地址
- Genmask:网络掩码
- Flags :路由标志
U:路由是活动的G:使用网关H:目标是一台主机D:由重定向创建M:由重定向修改
- Metric:路由距离
- Ref:路由引用计数
- Use:路由查找计数
- Iface:网络接口
接口统计字段
Iface MTU RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0 1500 1234567 0 0 0 987654 0 0 0 BMRU
lo 65536 123456 0 0 0 123456 0 0 0 LRU
- Iface:接口名称
- MTU:最大传输单元
- RX-OK/TX-OK:成功接收/发送的数据包数
- RX-ERR/TX-ERR:接收/发送错误的数据包数
- RX-DRP/TX-DRP:接收/发送丢弃的数据包数
- RX-OVR/TX-OVR:接收/发送溢出的数据包数
- Flg :接口标志
B:广播地址已设置L:回环接口M:混杂模式O:ARP 关闭P:点对点链接R:正在运行U:接口已启动
🔧 实用场景示例
1. 查看端口占用情况
bash
# 查看 80 端口被哪个进程占用
netstat -tunlp | grep :80
# 查看 22 端口(SSH)的连接情况
netstat -tunap | grep :22
# 查看所有监听端口
netstat -tunlp
# 查看特定进程占用的端口
netstat -tunlp | grep nginx
netstat -tunlp | grep apache
netstat -tunlp | grep mysql
# 查看端口范围占用情况
netstat -tunap | awk '$4 ~ /:80$/ || $4 ~ /:443$/ {print}'
2. 监控网络连接状态
bash
# 查看所有 ESTABLISHED 连接
netstat -tunap | grep ESTABLISHED
# 查看所有 TIME_WAIT 连接
netstat -tunap | grep TIME_WAIT
# 查看连接数最多的 IP
netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n
# 查看连接状态统计
netstat -nt | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
# 实时监控连接状态
watch -n 1 'netstat -nt | awk '\''/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'\'''
3. 排查网络问题
bash
# 查看是否有大量 TIME_WAIT 连接
netstat -nt | grep TIME_WAIT | wc -l
# 查看是否有大量 SYN_RECV 连接(可能遭受 SYN 攻击)
netstat -nt | grep SYN_RECV | wc -l
# 查看接收/发送错误
netstat -i
# 查看接口丢包情况
netstat -ie | grep -E "(Iface|errors|dropped)"
# 查看路由表,检查路由是否正确
netstat -rn
# 查看 ARP 表
arp -a
4. 服务监控
bash
# 监控 Web 服务器连接
watch -n 1 'netstat -tunap | grep -E "(nginx|apache|httpd)"'
# 监控数据库连接
watch -n 1 'netstat -tunap | grep -E "(mysql|postgres|mongodb)"'
# 监控 SSH 连接
watch -n 1 'netstat -tunap | grep sshd'
# 监控 FTP 连接
watch -n 1 'netstat -tunap | grep -E "(ftp|vsftpd|proftpd)"'
5. 安全审计
bash
# 查看所有外来连接
netstat -tunap | grep -v "127.0.0.1" | grep -v "::1"
# 查看异常连接
netstat -tunap | grep -E "(SYN_SENT|SYN_RECV|FIN_WAIT|CLOSE_WAIT|LAST_ACK)"
# 查看可疑的监听端口
netstat -tunlp | grep -vE "(127.0.0.1|::1|0.0.0.0)" | grep LISTEN
# 查看 root 用户的网络连接
netstat -tunap | grep root
# 查看非标准端口的监听
netstat -tunlp | grep LISTEN | grep -vE ":($(echo {20..23} {25} {53} {67..69} {80} {110} {123} {137..139} {143} {161..162} {389} {443} {445} {465} {514} {587} {636} {993} {995} {1080} {1194} {1433} {1521} {1723} {2049} {2082..2083} {2222} {3128} {3306} {3389} {3690} {4333} {4444} {5432} {5900..5901} {6000..6001} {6379} {6665..6669} {8000} {8008..8009} {8080..8081} {8443} {8888} {9000} {9090} {9200} {9300} {10000} {11211} {27017} {28017} {50000} | tr ' ' '|'))\s"
🛠️ 实用脚本
1. 网络连接监控脚本
bash
#!/bin/bash
# 网络连接监控脚本
LOG_FILE="/var/log/network_connections.log"
INTERVAL=60 # 检查间隔(秒)
ALERT_THRESHOLD=100 # 连接数警报阈值
ALERT_EMAIL="admin@example.com"
echo "开始网络连接监控 $(date)" >> "$LOG_FILE"
echo "检查间隔: ${INTERVAL}秒" >> "$LOG_FILE"
echo "警报阈值: ${ALERT_THRESHOLD} 个连接" >> "$LOG_FILE"
echo "======================================" >> "$LOG_FILE"
monitor_connections() {
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# 获取连接统计
local total_conn=$(netstat -nt | wc -l)
local established=$(netstat -nt | grep ESTABLISHED | wc -l)
local time_wait=$(netstat -nt | grep TIME_WAIT | wc -l)
local close_wait=$(netstat -nt | grep CLOSE_WAIT | wc -l)
local syn_recv=$(netstat -nt | grep SYN_RECV | wc -l)
# 记录到日志
echo "[$timestamp] 连接统计:" >> "$LOG_FILE"
echo " 总连接数: $total_conn" >> "$LOG_FILE"
echo " ESTABLISHED: $established" >> "$LOG_FILE"
echo " TIME_WAIT: $time_wait" >> "$LOG_FILE"
echo " CLOSE_WAIT: $close_wait" >> "$LOG_FILE"
echo " SYN_RECV: $syn_recv" >> "$LOG_FILE"
# 检查警报条件
if [[ $total_conn -gt $ALERT_THRESHOLD ]]; then
echo "[警报] 连接数超过阈值: $total_conn" >> "$LOG_FILE"
echo "网络连接数异常: $total_conn (阈值: $ALERT_THRESHOLD)" | \
mail -s "网络连接警报 - $timestamp" "$ALERT_EMAIL"
fi
if [[ $syn_recv -gt 10 ]]; then
echo "[警报] SYN_RECV 连接过多: $syn_recv" >> "$LOG_FILE"
echo "可能的 SYN 攻击: SYN_RECV=$syn_recv" | \
mail -s "SYN 攻击警报 - $timestamp" "$ALERT_EMAIL"
fi
# 显示前10个连接最多的IP
echo " 连接最多的IP:" >> "$LOG_FILE"
netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head -10 >> "$LOG_FILE"
echo "--------------------------------------" >> "$LOG_FILE"
}
# 主循环
while true; do
monitor_connections
sleep "$INTERVAL"
done
2. 端口扫描检测脚本
bash
#!/bin/bash
# 端口扫描检测脚本
LOG_FILE="/var/log/port_scan.log"
INTERVAL=10 # 检查间隔(秒)
SCAN_THRESHOLD=20 # 端口扫描阈值(同一IP的连接尝试次数)
BLOCK_TIME=3600 # 屏蔽时间(秒)
BLOCK_LIST="/tmp/blocked_ips.txt"
# 初始化屏蔽列表
touch "$BLOCK_LIST"
echo "开始端口扫描检测 $(date)" >> "$LOG_FILE"
echo "检查间隔: ${INTERVAL}秒" >> "$LOG_FILE"
echo "扫描阈值: ${SCAN_THRESHOLD} 次连接尝试" >> "$LOG_FILE"
echo "======================================" >> "$LOG_FILE"
detect_port_scan() {
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# 分析 SYN_RECV 状态的连接
netstat -nt | grep SYN_RECV | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | \
while read -r count ip; do
if [[ $count -gt $SCAN_THRESHOLD ]]; then
# 检查是否已在屏蔽列表中
if ! grep -q "^$ip$" "$BLOCK_LIST"; then
echo "[$timestamp] 检测到端口扫描: IP=$ip, 尝试次数=$count" >> "$LOG_FILE"
# 添加到屏蔽列表
echo "$ip" >> "$BLOCK_LIST"
# 使用 iptables 屏蔽
if command -v iptables >/dev/null 2>&1; then
iptables -A INPUT -s "$ip" -j DROP
echo " 已使用 iptables 屏蔽 IP: $ip" >> "$LOG_FILE"
fi
# 发送警报
echo "检测到端口扫描攻击" >> "$LOG_FILE"
echo "攻击IP: $ip" >> "$LOG_FILE"
echo "尝试次数: $count" >> "$LOG_FILE"
echo "时间: $timestamp" >> "$LOG_FILE"
fi
fi
done
# 清理过期的屏蔽记录
if [[ -f "$BLOCK_LIST" ]]; then
# 这里简化处理,实际应该记录时间
# 可以使用更复杂的时间管理
echo "当前屏蔽的IP:" >> "$LOG_FILE"
cat "$BLOCK_LIST" >> "$LOG_FILE"
fi
}
# 主循环
while true; do
detect_port_scan
sleep "$INTERVAL"
done
3. 服务健康检查脚本
bash
#!/bin/bash
# 服务健康检查脚本
SERVICES=(
"ssh:22:tcp"
"http:80:tcp"
"https:443:tcp"
"mysql:3306:tcp"
"redis:6379:tcp"
"mongodb:27017:tcp"
)
CHECK_INTERVAL=300 # 检查间隔(秒)
LOG_FILE="/var/log/service_health.log"
ALERT_EMAIL="admin@example.com"
echo "开始服务健康检查 $(date)" >> "$LOG_FILE"
echo "检查间隔: ${CHECK_INTERVAL}秒" >> "$LOG_FILE"
echo "======================================" >> "$LOG_FILE"
check_service() {
local service_name="$1"
local port="$2"
local protocol="$3"
# 检查端口是否在监听
if [[ "$protocol" == "tcp" ]]; then
netstat -ltn | grep -q ":$port "
status=$?
elif [[ "$protocol" == "udp" ]]; then
netstat -lun | grep -q ":$port "
status=$?
else
netstat -lan | grep -q ":$port "
status=$?
fi
if [[ $status -eq 0 ]]; then
echo " ✓ $service_name ($port/$protocol): 正常" >> "$LOG_FILE"
return 0
else
echo " ✗ $service_name ($port/$protocol): 异常" >> "$LOG_FILE"
return 1
fi
}
# 主循环
while true; do
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] 服务状态检查:" >> "$LOG_FILE"
failed_services=()
for service in "${SERVICES[@]}"; do
IFS=':' read -r name port protocol <<< "$service"
if ! check_service "$name" "$port" "$protocol"; then
failed_services+=("$name($port/$protocol)")
fi
done
# 如果有服务异常,发送警报
if [[ ${#failed_services[@]} -gt 0 ]]; then
echo " 异常服务: ${failed_services[*]}" >> "$LOG_FILE"
# 发送邮件警报
echo "以下服务异常: ${failed_services[*]}" | \
mail -s "服务健康检查警报 - $timestamp" "$ALERT_EMAIL"
fi
echo "--------------------------------------" >> "$LOG_FILE"
sleep "$CHECK_INTERVAL"
done
🔄 与 ss 命令对比
ss(socket statistics)是 netstat 的现代替代品,速度更快,功能更强大。
| 特性 | netstat | ss |
|---|---|---|
| 速度 | 较慢(读取 /proc/net/ 文件) | 较快(直接从内核获取) |
| 功能 | 基本功能 | 更多高级功能 |
| 输出格式 | 传统格式 | 更清晰的格式 |
| 过滤能力 | 有限 | 强大的过滤功能 |
| 协议支持 | 基本协议 | 更多协议支持 |
| 系统资源 | 占用较多 | 占用较少 |
ss 命令示例
bash
# 显示所有 TCP 连接
ss -t
# 显示所有 UDP 连接
ss -u
# 显示所有监听端口
ss -l
# 显示进程信息
ss -p
# 显示数字格式
ss -n
# 显示所有连接
ss -a
# 组合使用
ss -tunap
# 过滤功能
ss -t state established
ss -t state listening
ss -t '( dport = :80 or sport = :80 )'
ss -t dst 192.168.1.100
ss -t src 192.168.1.50
⚠️ 注意事项
- 性能影响 :在连接数很多的系统上,
netstat可能较慢,建议使用ss。 - 权限要求:查看进程信息需要 root 权限。
- 过时警告 :一些新系统推荐使用
ss替代netstat。 - 输出解析 :不同 Linux 发行版的
netstat输出格式可能略有不同。 - IPv6 支持:确保系统支持 IPv6 才能看到 IPv6 连接。
📌 最佳实践
- 使用 ss 替代 :在新系统中,优先使用
ss命令。 - 结合使用 :
netstat查看整体状态,ss查看详细信息。 - 定期监控:使用脚本定期监控网络连接状态。
- 安全审计:定期检查异常连接和监听端口。
- 性能优化:关注 TIME_WAIT 和 CLOSE_WAIT 状态连接数量。
🎯 快速参考卡
基本查看:
netstat -tunap # 查看所有连接
netstat -tunlp # 查看监听端口
netstat -rn # 查看路由表
netstat -i # 查看接口统计
netstat -s # 查看协议统计
状态过滤:
netstat -tunap | grep ESTABLISHED # 已建立连接
netstat -tunap | grep LISTEN # 监听端口
netstat -tunap | grep TIME_WAIT # TIME_WAIT 连接
netstat -tunap | grep SYN_RECV # SYN_RECV 连接
端口检查:
netstat -tunlp | grep :80 # 检查80端口
netstat -tunlp | grep nginx # 检查nginx进程
netstat -tunap | grep 192.168.1.1 # 检查特定IP
统计信息:
netstat -s # 所有协议统计
netstat -st # TCP统计
netstat -su # UDP统计
netstat -nt | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
实时监控:
watch -n 1 'netstat -tunap' # 每秒刷新
netstat -c # 连续输出
netstat 是 Linux 网络管理的基础工具,虽然在新系统中逐渐被 ss 替代,但它仍然是排查网络问题的有力工具。掌握 netstat 的使用方法对于系统管理员和网络工程师来说非常重要。