找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4033

积分

0

好友

521

主题
发表于 1 小时前 | 查看: 3| 回复: 0

一、概述

1.1 网络故障排查方法论

网络故障排查是运维工程师最核心的技能之一。当应用出现连接超时、响应延迟、数据丢包等问题时,网络抓包分析是最直接、最有效的诊断手段。通过捕获和分析网络数据包,工程师可以精确还原通信过程,定位问题发生在哪一层、哪个环节。

tcpdump和Wireshark是网络抓包领域最经典、最强大的两个工具。tcpdump是命令行的packet analyzer,适合快速捕获和初步过滤;Wireshark是图形化的protocol analyzer,适合深度分析和问题定位。两者配合使用,可以应对从简单到复杂的各种网络故障场景。

根据SharkFest和Packet Pushers的联合调研,2025年网络工程师日常工作中,76%的故障排查需要使用抓包分析;在复杂的微服务架构中,这个比例达到89%。然而,能熟练使用这两个工具的工程师不足30%,能进行深度协议分析的不足15%。本文将从一线运维工程师的视角,系统讲解tcpdump和Wireshark的配合使用技巧,提供可直接复用的脚本和案例。

1.2 证据链:网络故障与抓包分析

故障类型 占比 抓包解决率 平均排查时间
连接超时 34% 92% 8分钟
响应延迟 27% 85% 15分钟
数据丢包 18% 88% 12分钟
DNS异常 12% 95% 5分钟
加密握手失败 9% 78% 20分钟

数据来源:Packet Pushers Network Troubleshooting Survey 2025,样本量N=2500

关键结论:抓包分析可以解决超过85%的网络层故障,平均可将排查时间从小时级压缩到分钟级。

1.3 本文结构

第一部分:tcpdump命令行详解
    ├── 基础语法与常用选项
    ├── 过滤器表达式
    ├── 进阶捕获技巧
    └── 性能优化与常见错误

第二部分:Wireshark高级功能
    ├── 界面布局与快捷键
    ├── 过滤器语法
    ├── 统计与专家信息
    └── 追踪流与导出

第三部分:典型故障场景
    ├── TCP连接问题
    ├── HTTP/HTTPS问题
    ├── DNS解析问题
    └── 应用层协议问题

第四部分:自动化与脚本
    ├── 自动抓包触发
    ├── 批量包分析
    └── 报告生成

第五部分:最佳实践
    ├── 抓包点选择
    ├── 性能与存储
    └── 团队协作规范

二、tcpdump命令行详解

2.1 基础语法与常用选项

2.1.1 tcpdump核心选项速查

tcpdump [ -adeflnNOpqRStuUvxX ] [ -c count ] [ -C file_size ] [ -F file ]
         [ -i interface ] [ -m module ] [ -r file ] [ -s snaplen ]
         [ -T type ] [ -w file ] [ -E algo:secret ] [ expression ]

常用选项说明:

选项 说明 示例
-i 指定网卡 tcpdump -i eth0
-i any 监听所有网卡 tcpdump -i any
-c 捕获数据包数量 tcpdump -c 100
-w 写入文件 tcpdump -w capture.pcap
-r 读取文件 tcpdump -r capture.pcap
-n 不解析域名 tcpdump -n
-nn 不解析端口和服务 tcpdump -nn
-v 详细输出 tcpdump -v
-vv 更详细 tcpdump -vv
-X 十六进制和ASCII显示 tcpdump -X
-s 捕获长度 tcpdump -s 0 (完整)

2.1.2 基础捕获脚本

#!/bin/bash
# tcpdump_basics.sh
# tcpdump基础使用演示脚本

set -e

echo "===== tcpdump 基础使用 ====="

# 1. 捕获指定网卡的所有数据包
echo -e "\n[示例1] 捕获eth0网卡的前100个包"
echo "命令: tcpdump -i eth0 -c 100 -n"
echo "说明: -i指定网卡, -c捕获数量, -n不解析域名"
sudo tcpdump -i eth0 -c 100 -n 2>/dev/null | head -20

# 2. 捕获TCP流量
echo -e "\n[示例2] 只捕获TCP流量"
echo "命令: tcpdump -i eth0 tcp -c 50"
sudo tcpdump -i eth0 tcp -c 50 -n 2>/dev/null | head -15

# 3. 捕获特定端口流量
echo -e "\n[示例3] 捕获80端口(HTTP)流量"
echo "命令: tcpdump -i eth0 port 80 -c 20"
sudo tcpdump -i eth0 port 80 -c 20 -n 2>/dev/null | head -15

# 4. 捕获特定主机流量
echo -e "\n[示例4] 捕获与192.168.1.100通信的流量"
echo "命令: tcpdump -i eth0 host 192.168.1.100 -c 20"
sudo tcpdump -i eth0 host 192.168.1.100 -c 20 -n 2>/dev/null | head -15

# 5. 捕获并保存到文件
echo -e "\n[示例5] 保存捕获到文件"
CAPTURE_FILE="/tmp/capture_$(date +%Y%m%d_%H%M%S).pcap"
echo "命令: tcpdump -i eth0 -w $CAPTURE_FILE -c 1000"
timeout 5 sudo tcpdump -i eth0 -w "$CAPTURE_FILE" -c 100 2>/dev/null &
sleep 3

if [ -f "$CAPTURE_FILE" ]; then
    echo "文件大小: $(du -h "$CAPTURE_FILE" | cut -f1)"
    echo "包数量: $(sudo tcpdump -r "$CAPTURE_FILE" 2>/dev/null | wc -l)"
fi

echo -e "\n===== 基础演示完成 ====="

2.1.3 输出格式解析

tcpdump的标准输出格式:

时间戳          协议  源地址.端口    ->  目标地址.端口    [标志位]  其他信息
---------------- ---- ------------------- ------------------- ----- --------------------
21:23:45.123456 IP   192.168.1.10.443 -> 192.168.1.100.54321  Flags [P.], ack 123, win 502, length 1420
21:23:45.123789 IP   192.168.1.100.54321 -> 192.168.1.10.443   Flags [.], ack 14563, win 501, length 0

TCP标志位说明:

标志 说明 含义
S SYN 连接建立请求
F FIN 连接关闭请求
P PSH 数据推送
R RST 复位连接
. ACK 确认应答

2.2 过滤器表达式

2.2.1 BPF过滤语法

tcpdump使用Berkeley Packet Filter (BPF)语法,支持三种原语类型:类型限定、方向限定、协议限定。

类型限定:
  host <ip>          - 特定主机
  net <cidr>        - 网络段
  port <port>        - 端口
  portrange <p1-p2> - 端口范围

方向限定:
  src <qualifier>   - 源限定
  dst <qualifier>   - 目标限定

协议限定:
  ip, tcp, udp, icmp, arp, etc.

2.2.2 复合过滤表达式

#!/bin/bash
# tcpdump_filters.sh
# tcpdump过滤器表达式演示

set -e

echo "===== tcpdump 过滤器表达式 ====="

# 常用过滤场景
declare -A FILTER_SCENARIOS=(
    ["HTTP流量"]="tcp port 80 or tcp port 8080"
    ["HTTPS流量"]="tcp port 443"
    ["SSH流量"]="tcp port 22"
    ["DNS流量"]="udp port 53 or tcp port 53"
    ["MySQL流量"]="tcp port 3306"
    ["Redis流量"]="tcp port 6379"
    ["HTTP POST请求"]="tcp port 80 and tcp[tcpflags] & tcp-ack != 0 and (tcp[20:4] = 0x504f5354)"
    ["TCP SYN包"]="tcp[tcpflags] & tcp-syn != 0"
    ["TCP RST包"]="tcp[tcpflags] & tcp-rst != 0"
    ["大于1000字节的包"]="greater 1000"
    ["特定子网流入"]="src net 192.168.1.0/24"
    ["特定子网流出"]="dst net 192.168.1.0/24"
    ["非ICMP流量"]="ip and not icmp"
    ["非本地流量"]="ip and not net 127.0.0.1"
)

for scenario in "${!FILTER_SCENARIOS[@]}"; do
    echo -e "\n[场景] $scenario"
    echo "过滤表达式: ${FILTER_SCENARIOS[$scenario]}"
    echo "验证命令: sudo tcpdump -i lo -n '${FILTER_SCENARIOS[$scenario]}' -c 1 2>/dev/null"
done

# 逻辑运算符
echo -e "\n===== 逻辑运算符 ====="
echo "and / &&     - 逻辑与"
echo "or / ||      - 逻辑或"
echo "not / !      - 逻辑非"
echo "括号()       - 优先级控制"

# 高级过滤示例
echo -e "\n===== 高级过滤示例 ====="

echo -e "\n[1] 捕获源端口大于1024的SSH流量"
echo "tcpdump 'tcp port 22 and src port > 1024'"

echo -e "\n[2] 捕获包含特定字符串的HTTP请求"
echo "tcpdump -i eth0 'tcp port 80 and (tcp[20:4] = 0x47455420 or tcp[20:4] = 0x504f5354)'"

echo -e "\n[3] 捕获TTL小于10的ICMP包"
echo "tcpdump 'icmp and ip[8] < 10'"

echo -e "\n[4] 捕获TCP窗口大小为0的包(可能表示缓冲区满)"
echo "tcpdump 'tcp[14:2] = 0'"

echo -e "\n[5] 捕获设置了URG标志的TCP包"
echo "tcpdump 'tcp[tcpflags] & tcp-urg != 0'"

2.2.3 常用过滤脚本库

#!/bin/bash
# network_filter_lib.sh
# 网络故障排查常用过滤脚本库

set -e

# 加载常用过滤函数
source /dev/stdin << 'EOF'

# 输出带颜色的诊断信息
info() { echo -e "\033[1;34m[INFO]\033[0m $1"; }
warn() { echo -e "\033[1;33m[WARN]\033[0m $1"; }
error() { echo -e "\033[1;31m[ERROR]\033[0m $1"; }

# 1. TCP连接状态分析
analyze_tcp_connections() {
    local interface=${1:-eth0}
    local duration=${2:-10}

    info "TCP连接状态分析 (捕获${duration}秒)..."

    echo -e "\n=== SYN包统计 ==="
    sudo tcpdump -i "$interface" "tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0" -c 10 -nn 2>/dev/null

    echo -e "\n=== SYN-ACK包统计 ==="
    sudo tcpdump -i "$interface" "tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack != 0" -c 10 -nn 2>/dev/null

    echo -e "\n=== RST包统计 ==="
    sudo tcpdump -i "$interface" "tcp[tcpflags] & tcp-rst != 0" -c 10 -nn 2>/dev/null

    echo -e "\n=== FIN包统计 ==="
    sudo tcpdump -i "$interface" "tcp[tcpflags] & tcp-fin != 0" -c 10 -nn 2>/dev/null
}

# 2. HTTP流量分析
analyze_http_traffic() {
    local interface=${1:-eth0}
    local host=${2:-""}

    info "HTTP流量分析..."

    if [ -n "$host" ]; then
        FILTER="tcp port 80 or tcp port 8080 and host $host"
    else
        FILTER="tcp port 80 or tcp port 8080"
    fi

    echo -e "\n=== HTTP请求方法统计 ==="
    sudo tcpdump -i "$interface" "$FILTER and tcp[tcpflags] & tcp-push != 0" -nn 2>/dev/null | \
        awk '{print $NF}' | sort | uniq -c | sort -rn | head -10

    echo -e "\n=== HTTP状态码分布 ==="
    sudo tcpdump -i "$interface" "$FILTER" -nn -vv 2>/dev/null | \
        grep -oE "Http.*[0-9]{3}" | awk '{print $NF}' | sort | uniq -c | sort -rn
}

# 3. DNS查询分析
analyze_dns_queries() {
    local interface=${1:-eth0}
    local duration=${2:-5}

    info "DNS查询分析 (捕获${duration}秒)..."

    echo -e "\n=== DNS查询 ==="
    sudo timeout "$duration" tcpdump -i "$interface" "udp port 53" -nn 2>/dev/null | head -30

    echo -e "\n=== DNS响应码统计 ==="
    sudo timeout "$duration" tcpdump -i "$interface" "udp port 53" -nn 2>/dev/null | \
        grep -oE "QUERY|NOERROR|NXDOMAIN|SERVFAIL" | sort | uniq -c | sort -rn
}

# 4. 延迟分析
analyze_latency() {
    local interface=${1:-eth0}
    local target=${2:-8.8.8.8}

    info "延迟分析 (ping目标: $target)..."

    echo -e "\n=== Ping统计 ==="
    ping -c 10 "$target" 2>&1 | tail -2

    echo -e "\n=== TCP延迟采样 ==="
    sudo tcpdump -i "$interface" "host $target and tcp" -nn 2>/dev/null | \
        awk '{print $1}' | while read ts; do
            echo "${ts#*.}"
        done | head -20
}

# 5. 包大小分布
analyze_packet_sizes() {
    local interface=${1:-eth0}

    info "包大小分布分析..."

    echo -e "\n=== 包大小统计 ==="
    sudo tcpdump -i "$interface" -nn 2>/dev/null | \
        awk '{print NF, $0}' | sort -n | \
        awk '{print $NF}' | \
        grep -oE "[0-9]+" | sort -n | \
        awk 'BEGIN {b[0]=0;b[1]=0;b[2]=0;b[3]=0;b[4]=0;b[5]=0} {
            if ($1 < 64) b[0]++
            else if ($1 < 128) b[1]++
            else if ($1 < 256) b[2]++
            else if ($1 < 1024) b[3]++
            else if ($1 < 1518) b[4]++
            else b[5]++
        } END {
            print "  <64B:", b[0]
            print "  64-127B:", b[1]
            print "  128-255B:", b[2]
            print "  256-1023B:", b[3]
            print "  1024-1517B:", b[4]
            print "  >1518B:", b[5]
        }'
}

# 6. 连接数统计
analyze_connection_count() {
    local interface=${1:-eth0}

    info "活动连接数统计..."

    echo -e "\n=== 按源IP统计连接数 ==="
    sudo tcpdump -i "$interface" -nn 2>/dev/null | \
        awk '{print $3}' | cut -d. -f1-4 | sort | uniq -c | sort -rn | head -10

    echo -e "\n=== 按目标端口统计 ==="
    sudo tcpdump -i "$interface" -nn 2>/dev/null | \
        grep -oE "(\.[0-9]+\.[0-9]+)->" | grep -oE "[0-9]+" | sort | uniq -c | sort -rn | head -10
}

# 7. 丢包检测
detect_packet_loss() {
    local interface=${1:-eth0}

    info "丢包检测分析..."

    echo -e "\n=== 重传包分析 ==="
    sudo tcpdump -i "$interface" "tcp[tcpflags] & tcp-ack != 0" -nn 2>/dev/null | \
        grep -E "retransmission|duplicate" | head -10

    echo -e "\n=== Seq号跳跃分析 ==="
    echo "检查是否有Seq号跳跃(可能表示丢包)"
}

# 8. TCP窗口分析
analyze_tcp_window() {
    local interface=${1:-eth0}

    info "TCP窗口分析..."

    echo -e "\n=== 零窗口检测 ==="
    sudo tcpdump -i "$interface" "tcp[tcpflags] & tcp-ack != 0" -nn 2>/dev/null | \
        awk '/win 0/ {print $0}' | head -10

    echo -e "\n=== 小窗口检测 ==="
    sudo tcpdump -i "$interface" "tcp[tcpflags] & tcp-ack != 0" -nn 2>/dev/null | \
        awk '/win [0-9]{1,3}/ {print $0}' | head -10
}

EOF

# 执行演示
echo "===== 过滤脚本库演示 ====="
analyze_tcp_connections lo 3
analyze_dns_queries lo 3

2.3 进阶捕获技巧

2.3.1 条件触发捕获

#!/bin/bash
# conditional_capture.sh
# 条件触发式抓包脚本

set -e

CAPTURE_DIR="/var/log/captures"
mkdir -p "$CAPTURE_DIR"

echo "===== 条件触发式抓包 ====="

# 1. 基于错误的自动捕获
auto_capture_on_error() {
    local interface=${1:-eth0}
    local error_threshold=${2:-5}
    local capture_duration=${3:-30}

    echo "监控 $interface 上的错误,阈值: $error_threshold errors/$capture_duration 秒"

    # 监控TCP重传
    echo -e "\n[1] 启动TCP重传监控..."
    (
        while true; do
            RETRANS_COUNT=$(sudo tcpdump -i "$interface" "tcp[tcpflags] & tcp-retransmission" 2>/dev/null | \
                awk '{print $1}' | sort | uniq -c | wc -l)

            if [ "$RETRANS_COUNT" -gt "$error_threshold" ]; then
                TIMESTAMP=$(date +%Y%m%d_%H%M%S)
                CAPTURE_FILE="$CAPTURE_DIR/retrans_$TIMESTAMP.pcap"
                echo "检测到TCP重传激增,开始捕获..."
                sudo tcpdump -i "$interface" -w "$CAPTURE_FILE" -c 10000 &
                CAPTURE_PID=$!
                sleep "$capture_duration"
                kill "$CAPTURE_PID" 2>/dev/null
                echo "捕获已保存: $CAPTURE_FILE"
            fi
            sleep "$capture_duration"
        done
    ) &
    MONITOR_PID=$!

    echo "监控进程PID: $MONITOR_PID"
    echo "停止监控: kill $MONITOR_PID"
}

# 2. 基于延迟的自动捕获
auto_capture_on_latency() {
    local interface=${1:-eth0}
    local latency_threshold=${2:-100}  # ms
    local target=${3:-8.8.8.8}

    echo "监控到 $target 的延迟,阈值: ${latency_threshold}ms"

    (
        while true; do
            LATENCY=$(ping -c 1 -W 1 "$target" 2>/dev/null | \
                grep "time=" | awk -F'time=' '{print $2}' | awk '{print $1}')

            if [ -n "$LATENCY" ] && (( $(echo "$LATENCY > $latency_threshold" | bc -l) )); then
                TIMESTAMP=$(date +%Y%m%d_%H%M%S)
                CAPTURE_FILE="$CAPTURE_DIR/latency_$TIMESTAMP.pcap"
                echo "检测到延迟升高 (${LATENCY}ms),开始捕获..."
                sudo tcpdump -i "$interface" -w "$CAPTURE_FILE" -c 5000 &
                CAPTURE_PID=$!
                sleep 10
                kill "$CAPTURE_PID" 2>/dev/null
                echo "捕获已保存: $CAPTURE_FILE"
            fi
            sleep 5
        done
    ) &
}

# 3. 基于特定事件的捕获
capture_on_specific_event() {
    local interface=${1:-eth0}
    local event_pattern=${2:-"RST"}
    local capture_duration=${3:-60}

    echo "监控包含 '$event_pattern' 的包,捕获时长: ${capture_duration}s"

    (
        while true; do
            TIMESTAMP=$(date +%Y%m%d_%H%M%S)
            CAPTURE_FILE="$CAPTURE_DIR/event_${event_pattern}_$TIMESTAMP.pcap"

            echo "开始捕获..."
            sudo tcpdump -i "$interface" -w "$CAPTURE_FILE" -c 1000 2>/dev/null &
            CAPTURE_PID=$!

            sleep "$capture_duration"

            kill "$CAPTURE_PID" 2>/dev/null
            wait "$CAPTURE_PID" 2>/dev/null

            # 检查是否捕获到目标事件
            EVENTS=$(sudo tcpdump -r "$CAPTURE_FILE" 2>/dev/null | grep -c "$event_pattern" || echo 0)

            if [ "$EVENTS" -gt 0 ]; then
                echo "捕获到 $EVENTS 个 '$event_pattern' 事件"
                echo "文件: $CAPTURE_FILE"
                break
            else
                echo "未捕获到目标事件,继续..."
                rm -f "$CAPTURE_FILE"
            fi
        done
    ) &
}

# 4. 环形缓冲区捕获
ring_buffer_capture() {
    local interface=${1:-eth0}
    local ring_size=${2:-10}   # 文件数量
    local file_size=${3:-100}  # MB
    local total_size=$((ring_size * file_size))

    echo "环形缓冲区捕获: $ring_size 个文件,每个 ${file_size}MB,总计 ${total_size}MB"

    TIMESTAMP=$(date +%Y%m%d_%H%M%S)
    PREFIX="$CAPTURE_DIR/ring_${TIMESTAMP}"

    sudo tcpdump -i "$interface" \
        -w "${PREFIX}_%Y%m%d%H%M%S.pcap" \
        -C "$file_size" \
        -W "$ring_size" \
        -Z root &

    echo "捕获进程已启动"
    echo "前缀: $PREFIX"
    echo "停止: pkill -f 'tcpdump.*$PREFIX'"
}

# 5. 并行捕获(多网卡同时)
parallel_capture() {
    local interfaces=("eth0" "eth1" "lo")
    TIMESTAMP=$(date +%Y%m%d_%H%M%S)

    echo "并行捕获: ${interfaces
  • }"     for iface in "${interfaces[@]}"; do         CAPTURE_FILE="$CAPTURE_DIR/parallel_${iface}_$TIMESTAMP.pcap"         echo "启动 $iface 捕获: $CAPTURE_FILE"         sudo tcpdump -i "$iface" -w "$CAPTURE_FILE" -c 1000 2>/dev/null &     done     echo "所有接口捕获已启动"     echo "停止所有: pkill -f 'tcpdump.*parallel'" } # 主菜单 case "${1:-demo}" in     retrans)         auto_capture_on_error eth0 5 30         ;;     latency)         auto_capture_on_latency eth0 100 8.8.8.8         ;;     event)         capture_on_specific_event eth0 "RST" 60         ;;     ring)         ring_buffer_capture eth0 10 100         ;;     parallel)         parallel_capture         ;;     demo|*)         echo "===== 条件触发捕获演示 ====="         echo "用法: $0 {retrans|latency|event|ring|parallel}"         echo ""         echo "示例:"         echo "  $0 retrans    # TCP重传时自动捕获"         echo "  $0 latency    # 延迟升高时自动捕获"         echo "  $0 event      # 检测到RST时捕获"         echo "  $0 ring       # 环形缓冲区持续捕获"         echo "  $0 parallel   # 多网卡并行捕获"         ;; esac
  • 2.3.2 远程抓包与传输

    #!/bin/bash
    # remote_capture.sh
    # 远程抓包与安全传输脚本
    
    set -e
    
    REMOTE_HOST=${REMOTE_HOST:-""}
    REMOTE_USER=${REMOTE_USER:-"root"}
    CAPTURE_DIR="/var/log/captures"
    
    echo "===== 远程抓包系统 ====="
    
    # 1. SSH远程抓包(实时传输)
    remote_capture_stream() {
        local host=$1
        local interface=${2:-eth0}
        local filter=${3:-"tcp"}
        local count=${4:-1000}
    
        echo "远程抓包: $host:$interface"
        echo "过滤器: $filter"
        echo "包数量: $count"
    
        # 通过SSH远程执行tcpdump,结果通过管道传输
        ssh "$REMOTE_USER@$host" "sudo tcpdump -i $interface -n -c $count '$filter'" 2>/dev/null | head -50
    }
    
    # 2. 远程抓包并保存到本地
    remote_capture_save() {
        local host=$1
        local interface=${2:-eth0}
        local filter=${3:-"tcp"}
        local local_file=$4
    
        echo "远程抓包并保存到本地: $local_file"
    
        # 使用SSH隧道 + tcpdump
        ssh "$REMOTE_USER@$host" "sudo tcpdump -i $interface -n -w - '$filter'" 2>/dev/null | \
            sudo tee "$local_file" > /dev/null &
    
        echo "捕获中... Ctrl+C 停止"
        wait
    }
    
    # 3. 使用SCP安全传输抓包文件
    transfer_capture_file() {
        local remote_file=$1
        local local_dir=${2:-$CAPTURE_DIR}
        local host=$3
    
        local filename=$(basename "$remote_file")
        local timestamp=$(date +%Y%m%d_%H%M%S)
    
        echo "传输抓包文件: $host:$remote_file -> $local_dir/${timestamp}_$filename"
    
        scp "$REMOTE_USER@$host:$remote_file" "$local_dir/${timestamp}_$filename"
    
        echo "传输完成: $local_dir/${timestamp}_$filename"
        echo "文件大小: $(du -h "$local_dir/${timestamp}_$filename" | cut -f1)"
    }
    
    # 4. 远程抓包自动化脚本(在远程主机上执行)
    generate_remote_script() {
        local output_file="/tmp/remote_capture_$$.sh"
    
        cat > "$output_file" << 'REMOTE_EOF'
    #!/bin/bash
    # 远程抓包代理脚本
    # 在远程主机上执行
    
    INTERFACE=${1:-eth0}
    FILTER=${2:-"tcp"}
    COUNT=${3:-1000}
    OUTPUT_DIR="/var/log/captures"
    TIMESTAMP=$(date +%Y%m%d_%H%M%S)
    OUTPUT_FILE="$OUTPUT_DIR/capture_${TIMESTAMP}.pcap"
    
    # 确保输出目录存在
    mkdir -p "$OUTPUT_DIR"
    
    # 执行抓包
    echo "开始抓包: $(date)"
    tcpdump -i "$INTERFACE" -n -w "$OUTPUT_FILE" -c "$COUNT" "$FILTER" 2>&1
    
    # 计算文件大小
    if [ -f "$OUTPUT_FILE" ]; then
        SIZE=$(du -h "$OUTPUT_FILE" | cut -f1)
        echo "抓包完成: $(date)"
        echo "文件: $OUTPUT_FILE"
        echo "大小: $SIZE"
        echo "包数量: $(tcpdump -r "$OUTPUT_FILE" 2>/dev/null | wc -l)"
    else
        echo "抓包失败"
        exit 1
    fi
    REMOTE_EOF
    
        chmod +x "$output_file"
        echo "远程脚本已生成: $output_file"
    }
    
    # 5. WireGuard隧道抓包
    wireguard_capture() {
        local wg_interface=${1:-wg0}
        local target_host=$2
    
        echo "WireGuard隧道抓包: $wg_interface -> $target_host"
    
        # 监控WireGuard接口
        sudo tcpdump -i "$wg_interface" -nn -c 100 2>/dev/null | head -30
    
        # 同时抓取物理网卡
        echo -e "\n同时抓取物理网卡..."
        sudo tcpdump -i eth0 "host $target_host" -nn -c 100 2>/dev/null | head -30
    }
    
    # 菜单
    case "${1:-menu}" in
        stream)
            remote_capture_stream "$REMOTE_HOST" eth0 tcp 100
            ;;
        save)
            remote_capture_save "$REMOTE_HOST" eth0 tcp "/tmp/remote_capture.pcap"
            ;;
        transfer)
            transfer_capture_file "/var/log/captures/capture.pcap" "$CAPTURE_DIR" "$REMOTE_HOST"
            ;;
        generate)
            generate_remote_script
            ;;
        menu|*)
            echo "用法: $0 {stream|save|transfer|generate}"
            ;;
    esac

    2.4 性能优化与常见错误

    2.4.1 tcpdump性能优化

    #!/bin/bash
    # tcpdump_performance.sh
    # tcpdump性能优化与最佳实践
    
    set -e
    
    echo "===== tcpdump 性能优化 ====="
    
    # 1. 内核缓冲区优化
    optimize_kernel_buffer() {
        echo "[1] 内核缓冲区优化"
    
        # 查看当前缓冲区大小
        echo "当前环形缓冲区大小:"
        ifconfig eth0 2>/dev/null | grep -E "ring" || ip link show eth0 | grep -E "ring"
    
        # 设置更大的缓冲区(需要root)
        echo "设置缓冲区..."
        # ifconfig eth0 txqueuelen 10000
        # ip link set eth0 txqueuelen 10000
    }
    
    # 2. BPF优化
    optimize_bpf() {
        echo -e "\n[2] BPF过滤器优化"
    
        echo "BPF优化原则:"
        echo "  1. 尽量在捕获前过滤,减少内核拷贝"
        echo "  2. 使用精确的协议和端口过滤"
        echo "  3. 避免在过滤器中使用函数调用"
        echo "  4. 优先匹配低层协议"
    
        echo -e "\n示例对比:"
        echo "  低效: tcpdump 'ip and tcp and port 80'"
        echo "  高效: tcpdump 'tcp port 80'"
    
        echo -e "\nBPF编译器验证:"
        echo "使用 -ddd 选项查看编译后的BPF指令"
    }
    
    # 3. 快照长度优化
    optimize_snaplen() {
        echo -e "\n[3] 快照长度优化"
    
        echo "默认快照长度: 262144 bytes (262KB)"
        echo "优化建议:"
    
        echo "  - 使用 -s 0 自动选择合适长度"
        echo "  - 只需要头部时: -s 68 (TCP/IP头)"
        echo "  - UDP诊断: -s 512"
        echo "  - 完整包: -s 65535"
    
        echo -e "\n示例:"
        echo "  sudo tcpdump -i eth0 -s 68 -c 100 'tcp port 80'"
    }
    
    # 4. 多核并行处理
    optimize_multicore() {
        echo -e "\n[4] 多核并行处理"
    
        echo "使用pf_ring加速:"
        echo "  1. 安装PF_RING: apt install pf_ring"
        echo "  2. 加载驱动: modprobe pf_ring"
        echo "  3. 使用pfcount替代tcpdump"
    
        echo -e "\n使用dpdk优化:"
        echo "  dpdk-pdump工具支持DPDK加速抓包"
    }
    
    # 5. 捕获文件压缩
    optimize_compression() {
        echo -e "\n[5] 捕获文件压缩"
    
        echo "方法1: 使用 gzip 实时压缩"
        echo "  sudo tcpdump -i eth0 -w - | gzip > capture.pcap.gz"
    
        echo -e "\n方法2: 使用管道输出到压缩工具"
        echo "  sudo tcpdump -i eth0 -nn -c 1000 | gzip > capture.txt.gz"
    }
    
    # 6. 常见错误避免
    echo -e "\n[6] 常见错误避免"
    cat << 'EOF'
    错误1: 捕获的文件无法打开
      原因: 写入时使用了管道但格式不对
      解决: 确保使用 -w 选项写入文件
    
    错误2: 捕获不到任何包
      原因: 网卡混杂模式未启用、过滤器语法错误
      解决: 使用 ip link set eth0 promisc 启用混杂
    
    错误3: 捕获性能差,丢包严重
      原因: 缓冲区不足、过滤器太复杂
      解决: 增加缓冲区、优化过滤器
    
    错误4: 文件过大
      原因: 未限制包数量或文件大小
      解决: 使用 -c count, -C size, -W count 限制
    
    错误5: 权限问题
      原因: 普通用户无法直接访问网卡
      解决: sudo 运行,或设置 pcap 组权限
    EOF
    
    # 执行优化检查
    echo -e "\n===== 当前系统状态 ====="
    optimize_kernel_buffer
    optimize_bpf
    optimize_snaplen
    
    echo -e "\n===== 优化完成 ====="

    三、Wireshark高级功能

    3.1 界面布局与快捷键

    3.1.1 Wireshark界面布局

    ┌─────────────────────────────────────────────────────────────────────────────┐
    │  Menu Bar (菜单栏)                                                          │
    ├─────────────────────────────────────────────────────────────────────────────┤
    │  Main Toolbar (主工具栏)  [Start] [Stop] [Open] [Save] [Print] [Find] ... │
    ├───────────────────────────────────┬─────────────────────────────────────────┤
    │  Filter Toolbar (过滤器工具栏)     │  Interface List (接口列表)             │
    │  ip.addr == 192.168.1.100        │  □ eth0  [Start]                       │
    ├───────────────────────────────────┴─────────────────────────────────────────┤
    │                                                                             │
    │  Packet List Pane (包列表面板) - 主区域                                      │
    │  ┌──────┬────────┬──────────┬────────────┬─────────────┬────────────────┐ │
    │  │ No.  │ Time   │ Source  │ Destination│ Protocol   │ Length │ Info   │ │
    │  ├──────┼────────┼──────────┼────────────┼─────────────┼────────────────┤ │
    │  │ 1    │ 0.000  │ 192.168  │ 8.8.8.8    │ DNS         │ 72      │ ...   │ │
    │  │ 2    │ 0.023  │ 8.8.8.8  │ 192.168    │ DNS         │ 104     │ ...   │ │
    │  └──────┴────────┴──────────┴────────────┴─────────────┴────────────────┘ │
    │                                                                             │
    ├─────────────────────────────────────────────────────────────────────────────┤
    │  Packet Details Pane (包详情面板)                                           │
    │  ┌─ Frame 1 ─────────────────────────────────────────────────────────────┐ │
    │  │   Ethernet II, Src: ..., Dst: ...                                     │ │
    │  │ ► Internet Protocol Version 4, Src: 192.168.1.100, Dst: 8.8.8.8     │ │
    │  │ ► User Datagram Protocol, Src Port: 54321, Dst Port: 53             │ │
    │  │ ► Domain Name System (query)                                         │ │
    │  └──────────────────────────────────────────────────────────────────────┘ │
    │                                                                             │
    ├─────────────────────────────────────────────────────────────────────────────┤
    │  Packet Bytes Pane (包字节面板)                                             │
    │  ┌─ 0000 │ 45 00 00 48 01 23 40 00 40 11 a1 b7 c0 a8 01 64 │               │
    │  │ 0010 │ c0 a8 01 01 d4 35 00 35 00 34 12 34 01 00 00 01 │               │
    │  └──────────────────────────────────────────────────────────────────┘      │
    └─────────────────────────────────────────────────────────────────────────────┘
    │  Status Bar (状态栏)                                                        │
    │  [Capturing: eth0] [Packets: 1000] [Displayed: 500] [Marked: 0] [Dropped: 0]│
    └─────────────────────────────────────────────────────────────────────────────┘

    3.1.2 常用快捷键速查

    快捷键 功能 说明
    Ctrl+F 查找包 搜索包列表
    Ctrl+G 跳转到包 转到指定包号
    Ctrl+B 查找字节 在十六进制中搜索
    Ctrl+Shift+B 查找字符串 搜索字符串
    F5 开始捕获 重新开始抓包
    Ctrl+E 停止捕获 停止抓包
    Ctrl+O 打开文件 打开抓包文件
    Ctrl+S 保存文件 保存当前捕获
    Ctrl+W 关闭文件 关闭当前文件
    Tab 展开选中 展开当前字段
    Enter 展开/折叠 切换展开状态
    +/= 放大时间 增加时间精度
    - 缩小时间 减少时间精度
    Ctrl++ 下一面板 跳到包详情
    Ctrl+0-9 书签 设置/跳转到书签
    Ctrl+M 标记包 标记/取消标记
    Ctrl+Shift+M 标记所有 标记所有匹配包
    Ctrl+D 忽略包 忽略当前包
    Ctrl+Shift+D 取消忽略 取消忽略
    Ctrl+T 设置时间参考 设置时间参考点
    T 下一个时间参考 跳转到下一个时间参考
    : 过滤器输入框 快速输入过滤器

    3.2 过滤器语法

    3.2.1 捕获过滤器与显示过滤器

    捕获过滤器(Capture Filter) - 在抓包时生效,减少捕获数据量

    语法: <protocol> <direction> <host(s)> <value> <port>
    示例: tcp dst port 80 and host 192.168.1.100

    显示过滤器(Display Filter) - 在分析时生效,不丢失原始数据

    语法: <protocol>.<field> <operator> <value>
    示例: ip.addr == 192.168.1.100 and tcp.port == 80

    3.2.2 显示过滤器操作符

    操作符 说明 示例
    == 等于 ip.addr == 192.168.1.1
    != 不等于 ip.addr != 192.168.1.1
    > 大于 tcp.len > 1000
    < 小于 tcp.len < 100
    >= 大于等于 tcp.window_size >= 8192
    <= 小于等于 tcp.window_size <= 8192
    contains 包含 http.request.uri contains "/api"
    matches 正则匹配 http.host matches ".*.example.com"
    and / && 逻辑与 ip.addr == 192.168.1.1 and tcp.port == 80
    or / 逻辑或 tcp.port == 80 or tcp.port == 443
    not / ! 逻辑非 not arp

    3.2.3 常用显示过滤器模板

    #!/bin/bash
    # wireshark_filters.sh
    # Wireshark常用显示过滤器模板
    
    set -e
    
    echo "===== Wireshark 显示过滤器模板 ====="
    
    declare -A FILTER_TEMPLATES=(
        # HTTP相关
        ["HTTP请求"]="http.request"
        ["HTTP响应"]="http.response"
        ["HTTP POST"]="http.request.method == POST"
        ["HTTP GET"]="http.request.method == GET"
        ["404响应"]="http.response.code == 404"
        ["500错误"]="http.response.code == 500"
        ["特定URL"]="http.request.uri contains \"/api/v1\""
        ["特定Host"]="http.host == \"api.example.com\""
    
        # TCP相关
        ["TCP重传"]="tcp.analysis.retransmission"
        ["TCP快速重传"]="tcp.analysis.fast_retransmission"
        ["TCP重复ACK"]="tcp.analysis.duplicate_ack"
        ["TCP零窗口"]="tcp.analysis.zero_window"
        ["TCP窗口满"]="tcp.analysis.window_full"
        ["TCP RST"]="tcp.flags.reset == 1"
        ["TCP SYN"]="tcp.flags.syn == 1"
        ["TCP FIN"]="tcp.flags.fin == 1"
    
        # UDP相关
        ["DNS查询"]="dns.qry.name"
        ["DNS响应"]="dns.resp.name"
        ["NTP查询"]="ntp"
    
        # IP相关
        ["源IP"]="ip.src == 192.168.1.100"
        ["目标IP"]="ip.dst == 192.168.1.100"
        ["IP段"]="ip.addr in {192.168.1.0/24}"
        ["TTL异常"]="ip.ttl < 10"
    
        # 应用层
        ["SSH流量"]="ssh"
        ["MySQL查询"]="mysql.query"
        ["Redis命令"]="redis"
        ["HTTP2流量"]="http2"
        ["TLS握手"]="tls.handshake"
    
        # 性能分析
        ["响应时间>1s"]="frame.time_delta > 1"
        ["大文件传输"]="tcp.len > 100000"
        ["异常包大小"]="frame.len > 1500"
    )
    
    # 生成过滤器文件
    FILTER_FILE="/tmp/wireshark_filters.txt"
    
    echo "# Wireshark Display Filter Templates" > "$FILTER_FILE"
    echo "# Generated: $(date)" >> "$FILTER_FILE"
    echo "" >> "$FILTER_FILE"
    
    for name in "${!FILTER_TEMPLATES[@]}"; do
        printf "%-30s | %s\n" "$name" "${FILTER_TEMPLATES[$name]}" >> "$FILTER_FILE"
    done
    
    echo "过滤器文件已生成: $FILTER_FILE"
    cat "$FILTER_FILE"
    
    # 导出为Wireshark配置文件
    CONF_FILE="/tmp/dfilter_dfilters"
    
    cat > "$CONF_FILE" << 'EOF'
    # Wireshark Display Filter Expressions
    # Copy to ~/.config/wireshark/dfilter_dfilters
    
    [HTTP]
    http.request=HTTP request
    http.response=HTTP Response
    http.request.method==POST=HTTP POST
    http.request.method==GET=HTTP GET
    http.response.code==404=HTTP 404
    http.response.code==500=HTTP 500
    
    [TCP]
    tcp.analysis.retransmission=TCP Retransmission
    tcp.flags.reset==1=TCP RST
    tcp.flags.syn==1=TCP SYN
    tcp.flags.fin==1=TCP FIN
    tcp.analysis.zero_window=TCP Zero Window
    
    [IP]
    ip.addr==192.168.1.100=Local Host
    ip.ttl<10=Low TTL
    
    [DNS]
    dns.qry.name=DNS Query
    dns.resp.name=DNS Response
    EOF
    
    echo -e "\nWireshark配置文件已生成: $CONF_FILE"

    3.3 统计与专家信息

    3.3.1 统计分析工具

    #!/bin/bash
    # wireshark_stats.sh
    # Wireshark统计分析自动化
    
    set -e
    
    PCAP_FILE=${1:-""}
    
    if [ -z "$PCAP_FILE" ]; then
        echo "用法: $0 <pcap文件>"
        echo "使用示例: $0 /tmp/capture.pcap"
        exit 1
    fi
    
    if [ ! -f "$PCAP_FILE" ]; then
        echo "文件不存在: $PCAP_FILE"
        exit 1
    fi
    
    echo "===== Wireshark 统计分析 ====="
    echo "分析文件: $PCAP_FILE"
    echo "文件大小: $(du -h "$PCAP_FILE" | cut -f1)"
    echo "包数量: $(tshark -r "$PCAP_FILE" 2>/dev/null | wc -l)"
    
    # 使用tshark进行统计分析
    echo -e "\n[1] 协议分布"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    tshark -r "$PCAP_FILE" -q -z io,phs 2>/dev/null | head -20
    
    echo -e "\n[2] IP地址统计"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo "最活跃的源IP (Top 10):"
    tshark -r "$PCAP_FILE" -q -z ip_src_stat,10 2>/dev/null
    
    echo -e "\n[3] TCP会话统计"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    tshark -r "$PCAP_FILE" -q -z conv,tcp 2>/dev/null | head -20
    
    echo -e "\n[4] HTTP请求统计"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    tshark -r "$PCAP_FILE" -q -z http_req,ref 2>/dev/null | head -20
    
    echo -e "\n[5] HTTP状态码分布"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    tshark -r "$PCAP_FILE" -Y "http.response" -q -z http_srv,stat 2>/dev/null | head -20
    
    echo -e "\n[6] TCP问题分析"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo "重传包:"
    tshark -r "$PCAP_FILE" -Y "tcp.analysis.retransmission" -q 2>/dev/null | wc -l
    
    echo "重复ACK:"
    tshark -r "$PCAP_FILE" -Y "tcp.analysis.duplicate_ack" -q 2>/dev/null | wc -l
    
    echo "零窗口:"
    tshark -r "$PCAP_FILE" -Y "tcp.analysis.zero_window" -q 2>/dev/null | wc -l
    
    echo -e "\n[7] 专家信息摘要"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    tshark -r "$PCAP_FILE" -q -z expert 2>/dev/null | grep -A2 "Error\|Warning" | head -30
    
    echo -e "\n[8] 包长度分布"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    tshark -r "$PCAP_FILE" -q -z ptype,addr 2>/dev/null | head -10
    
    echo -e "\n===== 分析完成 ====="

    3.3.2 专家信息解读

    Wireshark的专家信息(Expert Information)是自动分析协议问题的核心功能,分为以下级别:

    级别 颜色 说明 常见原因
    Error 红色 严重问题 畸形包、解密失败
    Warning 黄色 警告 重传、重复ACK、窗口满
    Note 青色 注意 连接建立/关闭、Keepalive
    Chat 灰色 对话信息 正常协议交互

    常见专家信息解读:

    [Error] Malformed Packet
      原因: 包格式损坏或无法解析
      排查: 检查该包的原始数据,确认是否被抓包损坏
    
    [Warning] TCP Retransmission
      原因: 包在网络中丢失或延迟
      排查: 检查丢包位置、分析网络拥塞或路径问题
    
    [Warning] TCP duplicate ACK
      原因: 接收端未收到期望的包
      排查: 可能是重传或乱序
    
    [Warning] TCP Zero Window
      原因: 接收端缓冲区满
      排查: 检查接收端应用状态
    
    [Warning] TCP Window Full
      原因: 发送端已达到接收端窗口限制
      排查: 评估滑动窗口机制
    
    [Note] Connection finish (FIN)
      原因: 正常连接关闭
      排查: 分析连接生命周期
    
    [Note] Connection reset (RST)
      原因: 连接被重置
      排查: 检查是否异常断开

    3.4 追踪流与导出

    3.4.1 追踪流脚本

    #!/bin/bash
    # trace_stream.sh
    # 追踪流与数据导出脚本
    
    set -e
    
    PCAP_FILE=${1:-""}
    
    if [ ! -f "$PCAP_FILE" ]; then
        echo "用法: $0 <pcap文件>"
        exit 1
    fi
    
    OUTPUT_DIR="/tmp/wireshark_extract"
    mkdir -p "$OUTPUT_DIR"
    
    echo "===== 追踪流与数据导出 ====="
    echo "输入文件: $PCAP_FILE"
    echo "输出目录: $OUTPUT_DIR"
    
    # 1. 追踪TCP流
    trace_tcp_stream() {
        local src_ip=$1
        local dst_ip=$2
        local src_port=$3
        local dst_port=$4
    
        echo -e "\n[1] 追踪TCP流: $src_ip:$src_port -> $dst_ip:$dst_port"
    
        local filter="tcp.stream eq $(( RANDOM % 100 ))"
        tshark -r "$PCAP_FILE" -Y "$filter" -w "$OUTPUT_DIR/tcp_stream_${src_port}_${dst_port}.pcap" 2>/dev/null
    
        # 导出为文本
        tshark -r "$PCAP_FILE" -Y "$filter" -T fields -e data 2>/dev/null | \
            xxd -r -p > "$OUTPUT_DIR/tcp_data_${src_port}_${dst_port}.bin"
    }
    
    # 2. 追踪HTTP流
    trace_http_stream() {
        echo -e "\n[2] 追踪HTTP流"
    
        # 提取所有HTTP请求
        echo "HTTP请求:"
        tshark -r "$PCAP_FILE" -Y "http.request" -T fields \
            -e http.request.method \
            -e http.host \
            -e http.request.uri 2>/dev/null | head -20
    
        # 提取所有HTTP响应
        echo -e "\nHTTP响应:"
        tshark -r "$PCAP_FILE" -Y "http.response" -T fields \
            -e http.response.code \
            -e http.host 2>/dev/null | head -20
    
        # 导出完整HTTP流
        tshark -r "$PCAP_FILE" -Y "http" -w "$OUTPUT_DIR/http_streams.pcap" 2>/dev/null
    }
    
    # 3. 提取HTTP对象
    extract_http_objects() {
        echo -e "\n[3] 提取HTTP对象 (图片、文件等)"
    
        # 使用editcap或chaosreader提取
        if command -v chaosreader &> /dev/null; then
            chaosreader "$PCAP_FILE" -d "$OUTPUT_DIR/http_objects" 2>/dev/null
            echo "HTTP对象已提取到: $OUTPUT_DIR/http_objects"
        else
            echo "提示: 安装 chaosreader 以提取HTTP对象"
            echo "  apt install chaosreader"
        fi
    }
    
    # 4. 追踪DNS流
    trace_dns_stream() {
        echo -e "\n[4] 追踪DNS查询"
    
        echo "DNS查询:"
        tshark -r "$PCAP_FILE" -Y "dns.qry.name" -T fields \
            -e dns.qry.name \
            -e dns.qry.type \
            -e ip.src 2>/dev/null | head -30
    
        echo -e "\nDNS响应:"
        tshark -r "$PCAP_FILE" -Y "dns.resp.name" -T fields \
            -e dns.resp.name \
            -e dns.a \
            -e ip.dst 2>/dev/null | head -30
    
        # 导出DNS流量
        tshark -r "$PCAP_FILE" -Y "dns" -w "$OUTPUT_DIR/dns_streams.pcap" 2>/dev/null
    }
    
    # 5. 提取TLS会话
    trace_tls_stream() {
        echo -e "\n[5] 提取TLS会话"
    
        # 提取TLS握手信息
        tshark -r "$PCAP_FILE" -Y "tls.handshake" -T fields \
            -e ip.src \
            -e tls.handshake.type \
            -e tls.handshake.version \
            -e x509sat.printableString 2>/dev/null | head -30
    }
    
    # 6. 导出为CSV
    export_to_csv() {
        echo -e "\n[6] 导出为CSV格式"
    
        local csv_file="$OUTPUT_DIR/packet_data.csv"
    
        tshark -r "$PCAP_FILE" -T fields \
            -e frame.number \
            -e frame.time \
            -e ip.src \
            -e ip.dst \
            -e tcp.srcport \
            -e tcp.dstport \
            -e _ws.col.Protocol \
            -e frame.len \
            -e tcp.len \
            -e tcp.flags \
            -E separator=',' > "$csv_file"
    
        echo "CSV已导出: $csv_file"
        echo "行数: $(wc -l < "$csv_file")"
    }
    
    # 7. 导出payload数据
    extract_payloads() {
        echo -e "\n[7] 导出应用层Payload"
    
        # 提取HTTP body
        tshark -r "$PCAP_FILE" -Y "http" -T fields \
            -e http.file_data 2>/dev/null | head -10
    
        # 提取自定义端口数据
        echo -e "\n提取自定义端口(9000)数据:"
        tshark -r "$PCAP_FILE" -Y "tcp.port == 9000" -T fields \
            -e data 2>/dev/null | xxd -r -p | head -20
    }
    
    # 执行所有操作
    trace_http_stream
    trace_dns_stream
    export_to_csv
    
    echo -e "\n===== 导出完成 ====="
    echo "输出目录: $OUTPUT_DIR"
    ls -la "$OUTPUT_DIR"

    四、典型故障场景与排查脚本

    4.1 TCP连接问题

    4.1.1 TCP三次握手问题

    #!/bin/bash
    # tcp_handshake_analysis.sh
    # TCP三次握手问题分析脚本
    
    set -e
    
    PCAP_FILE=${1:-""}
    
    echo "===== TCP三次握手分析 ====="
    
    if [ -n "$PCAP_FILE" ] && [ -f "$PCAP_FILE" ]; then
        echo "分析文件: $PCAP_FILE"
    else
        echo "执行实时捕获分析..."
        CAPTURE_FILE="/tmp/handshake_$(date +%Y%m%d_%H%M%S).pcap"
        echo "捕获文件: $CAPTURE_FILE"
        echo "捕获5秒TCP流量..."
        sudo tcpdump -i any "tcp" -w "$CAPTURE_FILE" -c 100 2>/dev/null &
        sleep 5
        PCAP_FILE="$CAPTURE_FILE"
    fi
    
    # 1. 分析SYN包
    echo -e "\n[1] SYN包统计"
    echo "发送SYN但未收到SYN-ACK:"
    tshark -r "$PCAP_FILE" -Y "tcp.flags.syn == 1 and tcp.flags.ack == 0" -T fields \
        -e ip.src \
        -e tcp.srcport \
        -e ip.dst \
        -e tcp.dstport 2>/dev/null | \
        while IFS=$'\t' read src sport dst dport; do
            echo "  $src:$sport -> $dst:$dport (SYN未响应)"
        done | head -20
    
    # 2. 分析SYN-ACK包
    echo -e "\n[2] SYN-ACK包统计"
    echo "收到SYN-ACK:"
    tshark -r "$PCAP_FILE" -Y "tcp.flags.syn == 1 and tcp.flags.ack == 1" -T fields \
        -e ip.src \
        -e tcp.srcport \
        -e ip.dst \
        -e tcp.dstport 2>/dev/null | head -10
    
    # 3. 分析握手延迟
    echo -e "\n[3] 握手延迟分析"
    echo "SYN -> SYN-ACK 延迟 > 100ms:"
    tshark -r "$PCAP_FILE" -Y "tcp.flags.syn == 1 and tcp.flags.ack == 0" -T fields \
        -e frame.time_delta_displayed \
        -e ip.src \
        -e ip.dst \
        -e tcp.srcport 2>/dev/null | awk -F'\t' '$1 > 0.1 {print}' | head -10
    
    # 4. 分析连接失败原因
    echo -e "\n[4] 连接失败分析"
    echo "RST包(连接被拒绝):"
    tshark -r "$PCAP_FILE" -Y "tcp.flags.reset == 1" -T fields \
        -e ip.src \
        -e tcp.srcport \
        -e ip.dst \
        -e tcp.dstport 2>/dev/null | head -10
    
    # 5. TCP窗口问题
    echo -e "\n[5] TCP窗口问题"
    echo "零窗口包:"
    tshark -r "$PCAP_FILE" -Y "tcp.window_size == 0" -T fields \
        -e ip.src \
        -e tcp.window_size \
        -e ip.dst 2>/dev/null | head -10
    
    echo -e "\n===== 分析完成 ====="

    4.1.2 TCP重传问题分析

    #!/bin/bash
    # tcp_retrans_analysis.sh
    # TCP重传问题分析脚本
    
    set -e
    
    PCAP_FILE=${1:-""}
    
    echo "===== TCP重传问题分析 ====="
    
    if [ -n "$PCAP_FILE" ] && [ -f "$PCAP_FILE" ]; then
        echo "分析文件: $PCAP_FILE"
    else
        echo "用法: $0 <pcap文件>"
        exit 1
    fi
    
    # 1. 重传统计
    echo -e "\n[1] 重传包统计"
    echo "总重传包数:"
    tshark -r "$PCAP_FILE" -Y "tcp.analysis.retransmission" 2>/dev/null | wc -l
    
    echo -e "\n按源IP统计重传:"
    tshark -r "$PCAP_FILE" -Y "tcp.analysis.retransmission" -T fields \
        -e ip.src 2>/dev/null | sort | uniq -c | sort -rn | head -10
    
    echo -e "\n按目标IP统计重传:"
    tshark -r "$PCAP_FILE" -Y "tcp.analysis.retransmission" -T fields \
        -e ip.dst 2>/dev/null | sort | uniq -c | sort -rn | head -10
    
    # 2. 重传时序分析
    echo -e "\n[2] 重传时序分析"
    echo "首次重传延迟 > 200ms 的连接:"
    tshark -r "$PCAP_FILE" -Y "tcp.analysis.retransmission" -T fields \
        -e frame.time_delta_displayed \
        -e ip.src \
        -e ip.dst \
        -e tcp.srcport \
        -e tcp.dstport 2>/dev/null | \
        awk -F'\t' '$1 > 0.2 {printf "%.3fs %s:%s -> %s:%s\n", $1, $2, $3, $4, $5}' | \
        head -10
    
    # 3. 快速重传分析
    echo -e "\n[3] 快速重传分析"
    echo "快速重传包数:"
    tshark -r "$PCAP_FILE" -Y "tcp.analysis.fast_retransmission" 2>/dev/null | wc -l
    
    # 4. 重复ACK分析
    echo -e "\n[4] 重复ACK分析"
    echo "重复ACK包数:"
    tshark -r "$PCAP_FILE" -Y "tcp.analysis.duplicate_ack" 2>/dev/null | wc -l
    
    echo -e "\n重复ACK最多的连接:"
    tshark -r "$PCAP_FILE" -Y "tcp.analysis.duplicate_ack" -T fields \
        -e ip.src \
        -e ip.dst \
        -e tcp.srcport \
        -e tcp.dstport 2>/dev/null | sort | uniq -c | sort -rn | head -5
    
    # 5. 重传模式分析
    echo -e "\n[5] 重传模式分析"
    echo "判断重传原因:"
    
    # 计算重传率
    TOTAL_TCP=$(tshark -r "$PCAP_FILE" -Y "tcp" 2>/dev/null | wc -l)
    TOTAL_RETRANS=$(tshark -r "$PCAP_FILE" -Y "tcp.analysis.retransmission" 2>/dev/null | wc -l)
    
    if [ "$TOTAL_TCP" -gt 0 ]; then
        RETRANS_RATE=$(echo "scale=2; $TOTAL_RETRANS * 100 / $TOTAL_TCP" | bc)
        echo "TCP重传率: ${RETRANS_RATE}%"
    
        if (( $(echo "$RETRANS_RATE > 5" | bc -l) )); then
            echo "[警告] 重传率超过5%,可能存在网络问题"
        fi
    fi
    
    # 6. 建议
    echo -e "\n[6] 诊断建议"
    cat << 'EOF'
    重传原因判断:
    1. 单点重传 -> 可能是随机丢包,网络质量不稳定
    2. 连续重传 -> 可能是网络拥塞或链路带宽不足
    3. 特定时段重传 -> 可能是流量高峰或限速触发
    4. 特定方向重传 -> 可能是对端处理能力问题
    
    排查方向:
    1. 检查网络设备CPU/内存是否正常
    2. 检查链路带宽利用率
    3. 检查是否有流量限速配置
    4. 检查对端服务健康状态
    EOF
    
    echo -e "\n===== 分析完成 ====="

    4.2 HTTP/HTTPS问题

    4.2.1 HTTP问题诊断脚本

    #!/bin/bash
    # http_diagnosis.sh
    # HTTP问题诊断脚本
    
    set -e
    
    PCAP_FILE=${1:-""}
    
    echo "===== HTTP/HTTPS问题诊断 ====="
    
    if [ -n "$PCAP_FILE" ] && [ -f "$PCAP_FILE" ]; then
        echo "分析文件: $PCAP_FILE"
    else
        echo "用法: $0 <pcap文件>"
        exit 1
    fi
    
    # 1. HTTP方法统计
    echo -e "\n[1] HTTP方法统计"
    tshark -r "$PCAP_FILE" -Y "http.request.method" -T fields \
        -e http.request.method 2>/dev/null | sort | uniq -c | sort -rn
    
    # 2. HTTP状态码分布
    echo -e "\n[2] HTTP状态码分布"
    tshark -r "$PCAP_FILE" -Y "http.response.code" -T fields \
        -e http.response.code 2>/dev/null | sort | uniq -c | sort -rn
    
    # 3. 错误响应分析
    echo -e "\n[3] 错误响应详情"
    echo "4xx错误:"
    tshark -r "$PCAP_FILE" -Y "http.response.code >= 400 and http.response.code < 500" -T fields \
        -e http.response.code \
        -e http.host \
        -e http.request.uri 2>/dev/null | head -20
    
    echo -e "\n5xx错误:"
    tshark -r "$PCAP_FILE" -Y "http.response.code >= 500" -T fields \
        -e http.response.code \
        -e http.host \
        -e http.request.uri 2>/dev/null | head -20
    
    # 4. 慢请求分析
    echo -e "\n[4] 慢请求分析 (响应时间 > 1秒)"
    tshark -r "$PCAP_FILE" -Y "http" -T fields \
        -e frame.time_delta_displayed \
        -e http.request.method \
        -e http.host \
        -e http.request.uri 2>/dev/null | \
        awk -F'\t' '$1 > 1 {printf "%.3fs %s %s%s\n", $1, $2, $3, $4}' | \
        sort -rn | head -20
    
    # 5. HTTPS/TLS问题
    echo -e "\n[5] TLS握手问题"
    echo "TLS版本统计:"
    tshark -r "$PCAP_FILE" -Y "tls.handshake.version" -T fields \
        -e tls.handshake.version 2>/dev/null | sort | uniq -c | sort -rn
    
    echo -e "\nTLS错误:"
    tshark -r "$PCAP_FILE" -Y "tls.alert_message" -T fields \
        -e ip.src \
        -e tls.alert_message 2>/dev/null | head -10
    
    echo -e "\nTLS证书问题:"
    tshark -r "$PCAP_FILE" -Y "tls.handshake.type == 11" -T fields \
        -e ip.src \
        -e x509sat.printableString 2>/dev/null | head -10
    
    # 6. 连接复用分析
    echo -e "\n[6] HTTP连接复用分析"
    echo "Keep-Alive连接:"
    tshark -r "$PCAP_FILE" -Y "http.connection" -T fields \
        -e http.connection 2>/dev/null | sort | uniq -c | sort -rn | head -10
    
    # 7. 并发请求分析
    echo -e "\n[7] 并发请求分析"
    echo "同一主机并发请求数 (Top 10):"
    tshark -r "$PCAP_FILE" -Y "http.request" -T fields \
        -e http.host \
        -e frame.number \
        -e frame.time 2>/dev/null | \
        awk -F'\t' '{print $1}' | sort | uniq -c | sort -rn | head -10
    
    # 8. Transfer-Encoding分析
    echo -e "\n[8] Transfer-Encoding分析"
    echo "分块传输编码:"
    tshark -r "$PCAP_FILE" -Y "http.transfer_encoding" -T fields \
        -e http.transfer_encoding 2>/dev/null | sort | uniq -c
    
    echo -e "\n===== 诊断完成 ====="

    4.3 DNS解析问题

    4.3.1 DNS问题诊断脚本

    #!/bin/bash
    # dns_diagnosis.sh
    # DNS解析问题诊断脚本
    
    set -e
    
    PCAP_FILE=${1:-""}
    
    echo "===== DNS解析问题诊断 ====="
    
    if [ -n "$PCAP_FILE" ] && [ -f "$PCAP_FILE" ]; then
        echo "分析文件: $PCAP_FILE"
    else
        echo "执行实时捕获..."
        CAPTURE_FILE="/tmp/dns_$(date +%Y%m%d_%H%M%S).pcap"
        sudo tcpdump -i any "port 53" -w "$CAPTURE_FILE" -c 500 2>/dev/null &
        sleep 10
        PCAP_FILE="$CAPTURE_FILE"
    fi
    
    # 1. DNS查询统计
    echo -e "\n[1] DNS查询统计"
    echo "查询类型分布:"
    tshark -r "$PCAP_FILE" -Y "dns.qry.type" -T fields \
        -e dns.qry.type 2>/dev/null | sort | uniq -c | sort -rn
    
    # 2. 最常见查询
    echo -e "\n[2] 最常见查询 (Top 20)"
    tshark -r "$PCAP_FILE" -Y "dns.qry.name" -T fields \
        -e dns.qry.name 2>/dev/null | sort | uniq -c | sort -rn | head -20
    
    # 3. 响应码分析
    echo -e "\n[3] DNS响应码分析"
    echo "响应状态分布:"
    tshark -r "$PCAP_FILE" -Y "dns.flags.rcode" -T fields \
        -e dns.flags.rcode 2>/dev/null | sort | uniq -c | sort -rn
    
    # 4. 失败查询分析
    echo -e "\n[4] DNS失败查询分析"
    echo "NXDOMAIN (域名不存在):"
    tshark -r "$PCAP_FILE" -Y "dns.flags.rcode == 3" -T fields \
        -e dns.qry.name \
        -e ip.src 2>/dev/null | head -20
    
    echo -e "\nSERVFAIL (服务器失败):"
    tshark -r "$PCAP_FILE" -Y "dns.flags.rcode == 2" -T fields \
        -e dns.qry.name \
        -e ip.src 2>/dev/null | head -10
    
    # 5. 解析延迟分析
    echo -e "\n[5] DNS解析延迟分析"
    echo "查询响应时间 > 500ms:"
    tshark -r "$PCAP_FILE" -Y "dns" -T fields \
        -e frame.time_delta_displayed \
        -e dns.qry.name \
        -e dns.resp.name 2>/dev/null | \
        awk -F'\t' '$1 > 0.5 {printf "%.3fs %s -> %s\n", $1, $2, $3}' | \
        sort -rn | head -15
    
    # 6. DNS隧道检测
    echo -e "\n[6] DNS隧道/异常检测"
    echo "大量相同查询 (可能是隧道):"
    tshark -r "$PCAP_FILE" -Y "dns.qry.type == 1" -T fields \
        -e dns.qry.name 2>/dev/null | sort | uniq -c | \
        awk '$1 > 50 {print}' | head -10
    
    echo -e "\n异常长的子域名 (可能是隧道):"
    tshark -r "$PCAP_FILE" -Y "dns" -T fields \
        -e dns.qry.name 2>/dev/null | \
        awk '{print length($1), $1}' | sort -rn | head -10
    
    # 7. DNSSEC验证
    echo -e "\n[7] DNSSEC验证状态"
    tshark -r "$PCAP_FILE" -Y "dns.ds" -T fields \
        -e dns.dnskey 2>/dev/null | wc -l
    echo "DNSSEC记录数: $(tshark -r "$PCAP_FILE" -Y "dns.dnskey" 2>/dev/null | wc -l)"
    
    # 8. 解析路径追踪
    echo -e "\n[8] 解析路径追踪"
    echo "查询 -> 响应 追踪:"
    tshark -r "$PCAP_FILE" -Y "dns" -T fields \
        -e dns.id \
        -e dns.qry.name \
        -e ip.src \
        -e ip.dst 2>/dev/null | head -30
    
    echo -e "\n===== 诊断完成 ====="

    4.4 应用层协议问题

    4.4.1 数据库协议分析

    #!/bin/bash
    # db_protocol_analysis.sh
    # 数据库协议分析脚本
    
    set -e
    
    PCAP_FILE=${1:-""}
    
    echo "===== 数据库协议分析 ====="
    
    if [ -n "$PCAP_FILE" ] && [ -f "$PCAP_FILE" ]; then
        echo "分析文件: $PCAP_FILE"
    else
        echo "用法: $0 <pcap文件>"
        exit 1
    fi
    
    # 1. MySQL分析
    echo -e "\n[1] MySQL协议分析"
    echo "MySQL命令统计:"
    tshark -r "$PCAP_FILE" -Y "mysql.query" -T fields \
        -e mysql.query 2>/dev/null | cut -d' ' -f1 | sort | uniq -c | sort -rn | head -10
    
    echo -e "\n慢查询 (执行时间 > 1s):"
    tshark -r "$PCAP_FILE" -Y "mysql" -T fields \
        -e frame.time_delta_displayed \
        -e mysql.query 2>/dev/null | \
        awk -F'\t' '$1 > 1 {printf "%.3fs %s\n", $1, $2}' | head -20
    
    echo -e "\nMySQL错误:"
    tshark -r "$PCAP_FILE" -Y "mysql.errcode" -T fields \
        -e mysql.errcode \
        -e mysql.errmsg 2>/dev/null | head -10
    
    # 2. PostgreSQL分析
    echo -e "\n[2] PostgreSQL协议分析"
    echo "PostgreSQL命令统计:"
    tshark -r "$PCAP_FILE" -Y "postgresql" -T fields \
        -e postgresql.query 2>/dev/null | cut -d' ' -f1 | sort | uniq -c | sort -rn | head -10
    
    # 3. Redis分析
    echo -e "\n[3] Redis协议分析"
    echo "Redis命令统计:"
    tshark -r "$PCAP_FILE" -Y "redis" -T fields \
        -e redis.command 2>/dev/null | sort | uniq -c | sort -rn | head -15
    
    echo -e "\n大Key操作 (响应 > 1MB):"
    tshark -r "$PCAP_FILE" -Y "redis" -T fields \
        -e frame.len \
        -e redis.keyspace \
        -e redis.command 2>/dev/null | \
        awk -F'\t' '$1 > 1000000 {printf "%.2fMB %s %s\n", $1/1024/1024, $2, $3}' | head -10
    
    # 4. 连接分析
    echo -e "\n[4] 数据库连接分析"
    echo "连接建立统计:"
    echo "MySQL:"
    tshark -r "$PCAP_FILE" -Y "mysql.packet_length" 2>/dev/null | wc -l
    echo "PostgreSQL:"
    tshark -r "$PCAP_FILE" -Y "postgresql.packet_type" 2>/dev/null | wc -l
    echo "Redis:"
    tshark -r "$PCAP_FILE" -Y "redis" 2>/dev/null | wc -l
    
    # 5. 性能问题
    echo -e "\n[5] 性能问题汇总"
    echo "总数据库查询数:"
    echo "MySQL: $(tshark -r "$PCAP_FILE" -Y "mysql.query" 2>/dev/null | wc -l)"
    echo "PostgreSQL: $(tshark -r "$PCAP_FILE" -Y "postgresql" 2>/dev/null | wc -l)"
    echo "Redis: $(tshark -r "$PCAP_FILE" -Y "redis" 2>/dev/null | wc -l)"
    
    echo -e "\n===== 分析完成 ====="

    五、自动化与脚本

    5.1 自动抓包触发

    5.1.1 智能抓包脚本

    #!/bin/bash
    # smart_capture.sh
    # 智能自动抓包脚本
    
    set -e
    
    CONFIG_FILE="/etc/network-capture.conf"
    LOG_DIR="/var/log/captures"
    mkdir -p "$LOG_DIR"
    
    # 加载配置
    load_config() {
        if [ -f "$CONFIG_FILE" ]; then
            source "$CONFIG_FILE"
        else
            # 默认配置
            INTERFACE="eth0"
            TRIGGER_ERRORS=5
            TRIGGER_LATENCY=100
            CAPTURE_DURATION=30
            MAX_FILE_SIZE=100
        fi
    }
    
    # 日志函数
    log() {
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_DIR/capture.log"
    }
    
    # 错误条件检测
    detect_errors() {
        local count=0
    
        # 检测TCP错误
        count=$(sudo tcpdump -i "$INTERFACE" "tcp[tcpflags] & tcp-rst != 0" -c 10 2>/dev/null | wc -l)
    
        # 检测ICMP不可达
        count=$((count + $(sudo tcpdump -i "$INTERFACE" "icmp[icmptype] == 3" -c 10 2>/dev/null | wc -l)))
    
        echo $count
    }
    
    # 延迟检测
    detect_latency() {
        local target=${1:-"8.8.8.8"}
        local latency=$(ping -c 1 -W 1 "$target" 2>/dev/null | \
            grep "time=" | awk -F'time=' '{print $2}' | awk '{print $1}')
    
        if [ -z "$latency" ]; then
            echo "999"
        else
            echo "$latency"
        fi
    }
    
    # 执行抓包
    execute_capture() {
        local trigger_type=$1
        local capture_file="${LOG_DIR}/auto_${trigger_type}_$(date +%Y%m%d_%H%M%S).pcap"
    
        log "触发抓包: $trigger_type"
        log "保存到: $capture_file"
    
        # 后台执行捕获
        sudo tcpdump -i "$INTERFACE" \
            -w "$capture_file" \
            -C "$MAX_FILE_SIZE" \
            -W 10 \
            -c 10000 &
    
        CAPTURE_PID=$!
        log "捕获进程PID: $CAPTURE_PID"
    
        # 等待指定时间
        sleep "$CAPTURE_DURATION"
    
        # 停止捕获
        kill "$CAPTURE_PID" 2>/dev/null
        wait "$CAPTURE_PID" 2>/dev/null
    
        # 分析捕获文件
        log "分析捕获文件..."
        ANALYSIS_FILE="${capture_file%.pcap}_analysis.txt"
    
        {
            echo "===== 自动捕获分析报告 ====="
            echo "触发类型: $trigger_type"
            echo "捕获时间: $(date)"
            echo "文件: $capture_file"
    
            echo -e "\n[1] 协议分布"
            tshark -r "$capture_file" -q -z io,phs 2>/dev/null | head -15
    
            echo -e "\n[2] TCP问题"
            echo "重传包: $(tshark -r "$capture_file" -Y 'tcp.analysis.retransmission' 2>/dev/null | wc -l)"
            echo "RST包: $(tshark -r "$capture_file" -Y 'tcp.flags.reset==1' 2>/dev/null | wc -l)"
    
            echo -e "\n[3] 统计摘要"
            tshark -r "$capture_file" -q -z conv,tcp 2>/dev/null | head -10
    
        } > "$ANALYSIS_FILE"
    
        log "分析报告: $ANALYSIS_FILE"
    }
    
    # 主监控循环
    main() {
        load_config
    
        log "===== 智能抓包监控启动 ====="
        log "接口: $INTERFACE"
        log "错误阈值: $TRIGGER_ERRORS"
        log "延迟阈值: ${TRIGGER_LATENCY}ms"
    
        while true; do
            # 检测错误条件
            ERRORS=$(detect_errors)
            if [ "$ERRORS" -ge "$TRIGGER_ERRORS" ]; then
                log "检测到错误激增: $ERRORS"
                execute_capture "errors"
            fi
    
            # 检测延迟
            LATENCY=$(detect_latency)
            if (( $(echo "$LATENCY > $TRIGGER_LATENCY" | bc -l) )); then
                log "检测到延迟升高: ${LATENCY}ms"
                execute_capture "latency"
            fi
    
            sleep 10
        done
    }
    
    # 信号处理
    trap 'log "收到停止信号,退出..."; exit 0' SIGINT SIGTERM
    
    # 运行
    case "${1:-start}" in
        start)
            main
            ;;
        stop)
            pkill -f smart_capture.sh
            log "已停止"
            ;;
        *)
            echo "用法: $0 {start|stop}"
            ;;
    esac

    5.2 批量包分析

    #!/bin/bash
    # batch_analysis.sh
    # 批量抓包文件分析脚本
    
    set -e
    
    ANALYSIS_DIR=${1:-"/var/log/captures"}
    
    echo "===== 批量抓包分析 ====="
    echo "分析目录: $ANALYSIS_DIR"
    
    if [ ! -d "$ANALYSIS_DIR" ]; then
        echo "目录不存在: $ANALYSIS_DIR"
        exit 1
    fi
    
    # 创建输出报告
    REPORT_FILE="/tmp/batch_analysis_$(date +%Y%m%d_%H%M%S).html"
    
    cat > "$REPORT_FILE" << 'EOF'
    <!DOCTYPE html>
    <html>
    <head>
        <title>批量抓包分析报告</title>
        <style>
            body { font-family: Arial, sans-serif; margin: 20px; }
            table { border-collapse: collapse; width: 100%; }
            th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
            th { background-color: #4CAF50; color: white; }
            .error { color: red; }
            .warning { color: orange; }
            .success { color: green; }
        </style>
    </head>
    <body>
        <h1>批量抓包分析报告</h1>
    EOF
    
    echo "<p>生成时间: $(date)</p>" >> "$REPORT_FILE"
    echo "<p>分析目录: $ANALYSIS_DIR</p>" >> "$REPORT_FILE"
    
    # 统计摘要
    echo "<h2>文件列表</h2>" >> "$REPORT_FILE"
    echo "<table>" >> "$REPORT_FILE"
    echo "<tr><th>文件名</th><th>大小</th><th>包数</th><th>TCP重传</th><th>RST</th><th>问题级别</th></tr>" >> "$REPORT_FILE"
    
    # 分析每个pcap文件
    for pcap_file in $(find "$ANALYSIS_DIR" -name "*.pcap" -type f 2>/dev/null); do
        filename=$(basename "$pcap_file")
        filesize=$(du -h "$pcap_file" | cut -f1)
    
        # 统计包数
        packet_count=$(tshark -r "$pcap_file" 2>/dev/null | wc -l)
    
        # 统计TCP问题
        retrans=$(tshark -r "$pcap_file" -Y "tcp.analysis.retransmission" 2>/dev/null | wc -l)
        rst=$(tshark -r "$pcap_file" -Y "tcp.flags.reset==1" 2>/dev/null | wc -l)
    
        # 判断问题级别
        if [ "$retrans" -gt 100 ] || [ "$rst" -gt 50 ]; then
            level="<span class='error'>严重</span>"
        elif [ "$retrans" -gt 20 ] || [ "$rst" -gt 10 ]; then
            level="<span class='warning'>警告</span>"
        else
            level="<span class='success'>正常</span>"
        fi
    
        echo "<tr><td>$filename</td><td>$filesize</td><td>$packet_count</td><td>$retrans</td><td>$rst</td><td>$level</td></tr>" >> "$REPORT_FILE"
    done
    
    echo "</table>" >> "$REPORT_FILE"
    
    # 总体统计
    echo "<h2>总体统计</h2>" >> "$REPORT_FILE"
    TOTAL_FILES=$(find "$ANALYSIS_DIR" -name "*.pcap" | wc -l)
    TOTAL_SIZE=$(du -sh "$ANALYSIS_DIR" 2>/dev/null | cut -f1)
    TOTAL_PACKETS=$(find "$ANALYSIS_DIR" -name "*.pcap" -exec tshark -r {} 2>/dev/null \; | wc -l)
    
    cat >> "$REPORT_FILE" << EOF
    <ul>
    <li>文件总数: $TOTAL_FILES</li>
    <li>总大小: $TOTAL_SIZE</li>
    <li>总包数: $TOTAL_PACKETS</li>
    </ul>
    EOF
    
    echo "</body></html>" >> "$REPORT_FILE"
    
    echo "报告已生成: $REPORT_FILE"
    echo "打开方式: firefox $REPORT_FILE"

    六、最佳实践

    6.1 抓包点选择

    6.1.1 网络拓扑与抓包点

    网络拓扑示例:
    ┌─────────┐    ┌─────────┐    ┌─────────┐
    │  客户端  │───▶│   L4    │───▶│  服务器  │
    │         │◀───│  负载均衡 │◀───│         │
    └─────────┘    └─────────┘    └─────────┘
         │                               │
         │                               │
         ▼                               ▼
    ┌─────────────────────────────────────────┐
    │              抓包点选择指南               │
    ├─────────────────────────────────────────┤
    │  抓包点   │  能看到的问题    │  适用场景     │
    ├─────────────────────────────────────────┤
    │  客户端   │  应用层问题     │  端到端延迟   │
    │           │  TLS问题       │  协议兼容性   │
    ├─────────────────────────────────────────┤
    │  负载均衡  │  连接分发问题   │  健康检查     │
    │           │  流量不均       │  端口映射     │
    ├─────────────────────────────────────────┤
    │  服务器网卡│  服务层问题     │  后端处理     │
    │           │  资源争用       │  数据库延迟   │
    ├─────────────────────────────────────────┤
    │  交换机镜像│  全网流量       │  分布式问题   │
    │           │  流量分析       │  性能监控     │
    └─────────────────────────────────────────┘

    6.1.2 不同场景的抓包策略

    #!/bin/bash
    # capture_strategy.sh
    # 不同场景的抓包策略
    
    set -e
    
    echo "===== 网络抓包策略指南 ====="
    
    # 场景1: 客户端到服务器延迟
    scenario_client_to_server() {
        echo -e "\n[场景1] 客户端到服务器延迟"
        echo "推荐抓包点: 客户端 + 服务器端"
        echo "过滤条件: host <目标IP> and tcp.port == <端口>"
        echo ""
        echo "客户端抓包命令:"
        echo "  sudo tcpdump -i eth0 -w client_capture.pcap 'host 192.168.1.100 and tcp.port 443'"
        echo ""
        echo "服务器抓包命令:"
        echo "  sudo tcpdump -i eth0 -w server_capture.pcap 'host 203.0.113.50 and tcp.port 443'"
    }
    
    # 场景2: 负载均衡问题
    scenario_load_balancer() {
        echo -e "\n[场景2] 负载均衡问题"
        echo "推荐抓包点: 客户端 + 负载均衡器入口 + 后端服务器"
        echo "过滤条件: tcp.port == 80 or tcp.port == 443"
        echo ""
        echo "分析要点:"
        echo "  1. 对比客户端请求与负载均衡器收到的请求"
        echo "  2. 检查负载均衡器到后端的连接分发"
        echo "  3. 验证健康检查是否正常"
    }
    
    # 场景3: 数据库性能问题
    scenario_database() {
        echo -e "\n[场景3] 数据库性能问题"
        echo "推荐抓包点: 应用服务器 + 数据库服务器"
        echo "过滤条件: tcp.port == 3306 or tcp.port == 5432 or tcp.port == 6379"
        echo ""
        echo "分析要点:"
        echo "  1. 查询响应时间"
        echo "  2. 连接池耗尽"
        echo "  3. 慢查询模式"
    }
    
    # 场景4: 微服务间通信
    scenario_microservices() {
        echo -e "\n[场景4] 微服务间通信问题"
        echo "推荐抓包点: 每个服务的出入口"
        echo "过滤条件: tcp.port == <服务端口>"
        echo ""
        echo "分析要点:"
        echo "  1. 服务调用链追踪"
        echo "  2. gRPC/HTTP2问题"
        echo "  3. mTLS证书问题"
    }
    
    # 场景5: DNS问题
    scenario_dns() {
        echo -e "\n[场景5] DNS解析问题"
        echo "推荐抓包点: DNS服务器或客户端"
        echo "过滤条件: port 53"
        echo ""
        echo "分析要点:"
        echo "  1. 查询响应时间"
        echo "  2. NXDOMAIN模式"
        echo "  3. DNS劫持检测"
    }
    
    # 场景6: TLS/SSL问题
    scenario_tls() {
        echo -e "\n[场景6] TLS/SSL问题"
        echo "推荐抓包点: 客户端终止点"
        echo "过滤条件: tcp.port == 443 and tls"
        echo ""
        echo "分析要点:"
        echo "  1. 握手失败原因"
        echo "  2. 证书验证"
        echo "  3. 协议版本不匹配"
    }
    
    # 显示所有场景
    scenario_client_to_server
    scenario_load_balancer
    scenario_database
    scenario_microservices
    scenario_dns
    scenario_tls
    
    echo -e "\n===== 策略指南结束 ====="

    6.2 性能与存储

    6.2.1 抓包存储策略

    #!/bin/bash
    # capture_storage.sh
    # 抓包存储与生命周期管理
    
    set -e
    
    STORAGE_BASE="/var/log/captures"
    RETENTION_DAYS=${RETENTION_DAYS:-30}
    
    echo "===== 抓包存储管理 ====="
    echo "存储目录: $STORAGE_BASE"
    echo "保留天数: $RETENTION_DAYS"
    
    # 创建目录结构
    create_dirs() {
        echo -e "\n[1] 创建目录结构"
        mkdir -p "$STORAGE_BASE"/{daily,incidents,debug,archive}
        echo "目录已创建:"
        ls -la "$STORAGE_BASE"
    }
    
    # 自动清理
    auto_cleanup() {
        echo -e "\n[2] 清理过期文件"
    
        find "$STORAGE_BASE" -name "*.pcap" -mtime +$RETENTION_DAYS -type f -delete
        echo "已删除 ${RETENTION_DAYS} 天前的pcap文件"
    
        find "$STORAGE_BASE/archive" -name "*.pcap.gz" -mtime +365 -type f -delete
        echo "已删除 1 年前的压缩归档"
    }
    
    # 压缩归档
    compress_old_files() {
        echo -e "\n[3] 压缩归档"
    
        find "$STORAGE_BASE/daily" -name "*.pcap" -mtime +7 -type f | while read file; do
            gzip "$file"
            echo "已压缩: $file"
        done
    }
    
    # 存储使用统计
    storage_stats() {
        echo -e "\n[4] 存储统计"
    
        echo "按目录大小:"
        du -sh "$STORAGE_BASE"/* 2>/dev/null | sort -hr
    
        echo -e "\n总大小:"
        du -sh "$STORAGE_BASE" 2>/dev/null
    
        echo -e "\n文件数量:"
        find "$STORAGE_BASE" -name "*.pcap*" -type f | wc -l
    }
    
    # 告警阈值
    check_threshold() {
        echo -e "\n[5] 存储告警检查"
    
        MAX_SIZE_GB=100
        CURRENT_SIZE=$(du -sm "$STORAGE_BASE" 2>/dev/null | awk '{print $1}')
        CURRENT_GB=$(echo "scale=2; $CURRENT_SIZE / 1024" | bc)
    
        echo "当前使用: ${CURRENT_GB}GB / ${MAX_SIZE_GB}GB"
    
        USAGE_PCT=$(echo "scale=0; $CURRENT_SIZE * 100 / ($MAX_SIZE_GB * 1024)" | bc)
    
        if [ "$USAGE_PCT" -gt 90 ]; then
            echo "[告警] 存储使用率超过90%,请清理"
        elif [ "$USAGE_PCT" -gt 70 ]; then
            echo "[警告] 存储使用率超过70%"
        else
            echo "[正常] 存储使用率正常"
        fi
    }
    
    # 执行维护任务
    main() {
        create_dirs
        auto_cleanup
        compress_old_files
        storage_stats
        check_threshold
    }
    
    # 计划任务示例
    # 0 2 * * * /usr/local/bin/capture_storage.sh  # 每天凌晨2点执行
    
    main

    6.3 团队协作规范

    6.3.1 抓包分析协作流程

    #!/bin/bash
    # capture_workflow.sh
    # 抓包分析团队协作脚本
    
    set -e
    
    WORKFLOW_DIR="/var/log/captures/workflow"
    TEMPLATE_DIR="/etc/capture-templates"
    
    echo "===== 抓包分析协作流程 ====="
    
    # 创建标准命名规范
    naming_convention() {
        echo -e "\n[1] 命名规范"
        cat << 'EOF'
    抓包文件命名:
      {日期}_{场景}_{IP范围}_{捕获方向}_{序号}.pcap
    
    示例:
      20260328_http_api_192.168.1.0_client_001.pcap
      20260328_tls_handshake_203.0.113.0_both_001.pcap
      20260328_dns_resolve_8.8.8.8_server_001.pcap
    
    分析报告命名:
      {抓包文件}_analysis_{日期}.txt
    
    示例:
      20260328_http_api_192.168.1.0_client_001_analysis_20260328.txt
    EOF
    }
    
    # 生成分析报告模板
    generate_template() {
        echo -e "\n[2] 分析报告模板"
        local template_file="$WORKFLOW_DIR/analysis_template.txt"
    
        cat > "$template_file" << 'EOF'
    ===== 网络抓包分析报告 =====
    
    基本信息:
    --------
    文件名:
    捕获时间:
    捕获位置:
    分析时间:
    分析人员:
    
    问题描述:
    --------
    [详细描述遇到的网络问题]
    
    分析摘要:
    --------
    [总结发现的关键问题]
    
    详细分析:
    --------
    1. 协议分布
    2. 连接统计
    3. 异常发现
    4. 时间线
    
    根本原因:
    --------
    [分析得出的根本原因]
    
    建议措施:
    --------
    [针对问题的解决方案]
    
    附件:
    ----
    - 抓包文件: xxx.pcap
    - 关键包截图: xxx.png
    EOF
    
        echo "模板已生成: $template_file"
    }
    
    # 导出协作包
    export_bundle() {
        local incident_id=$1
        local output_dir=$2
    
        echo -e "\n[3] 导出协作包"
        echo "事件ID: $incident_id"
        echo "输出目录: $output_dir"
    
        mkdir -p "$output_dir"
    
        # 复制相关抓包文件
        cp "$WORKFLOW_DIR"/${incident_id}_*.pcap "$output_dir/" 2>/dev/null || true
    
        # 复制分析报告
        cp "$WORKFLOW_DIR"/${incident_id}_*.txt "$output_dir/" 2>/dev/null || true
    
        # 复制截图
        cp "$WORKFLOW_DIR"/${incident_id}_*.png "$output_dir/" 2>/dev/null || true
    
        # 创建索引文件
        cat > "$output_dir/README.txt" << EOF
    事件 $incident_id 协作包
    生成时间: $(date)
    包含文件:
    $(ls -la "$output_dir")
    EOF
    
        echo "协作包已导出: $output_dir"
    }
    
    # 导入审查
    import_review() {
        local bundle_dir=$1
    
        echo -e "\n[4] 审查抓包协作包"
        echo "目录: $bundle_dir"
    
        # 检查必要文件
        if [ ! -f "$bundle_dir"/*.pcap ]; then
            echo "[错误] 缺少抓包文件"
            return 1
        fi
    
        # 生成审查清单
        cat > "$bundle_dir/review_checklist.txt" << 'EOF'
    审查清单:
    [ ] 抓包文件完整可读
    [ ] 分析报告结构完整
    [ ] 问题描述清晰
    [ ] 根本原因分析合理
    [ ] 建议措施可行
    [ ] 截图清晰可辨
    EOF
    
        echo "审查清单已生成: $bundle_dir/review_checklist.txt"
    }
    
    naming_convention
    generate_template
    
    echo -e "\n===== 协作流程说明 ====="
    echo "1. 捕获时使用标准命名"
    echo "2. 分析后生成报告模板"
    echo "3. 使用 export_bundle 导出协作包"
    echo "4. 接收方使用 import_review 进行审查"

    七、总结

    7.1 核心要点回顾

    tcpdump和Wireshark是企业网络故障排查的两大核心工具,各有优劣:

    tcpdump优势:轻量、远程友好、适合自动化、高性能抓包
    Wireshark优势:可视化、深度分析、统计强大、专家系统

    两者配合使用的最佳实践:

    1. tcpdump负责捕获和预处理,Wireshark负责深度分析
    2. 使用BPF过滤减少数据量
    3. 熟练掌握显示过滤器是关键
    4. 统计功能和专家信息是快速定位问题的利器
    5. 自动化脚本可以大幅提升效率

    7.2 证据链总结

    技术点 效能数据 来源
    抓包解决率 85%+ Packet Pushers 2025
    排查时间节省 从小时到分钟 行业实践
    协议分析准确率 >90% SharkFest统计

    7.3 快速参考表

    场景 tcpdump命令 Wireshark过滤器
    HTTP问题 tcpdump -i eth0 port 80 -w http.pcap http
    TCP重传 tcpdump -i eth0 'tcp[tcpflags] & tcp-retransmission' tcp.analysis.retransmission
    DNS问题 tcpdump -i eth0 port 53 -w dns.pcap dns
    TLS握手 tcpdump -i eth0 port 443 -w tls.pcap tls.handshake
    延迟分析 tcpdump -i eth0 -tttt frame.time_delta

    更多网络抓包实战,尽在云栈社区的网络技术板块




    上一篇:字节员工自曝想回流:外面没那么好玩,脉脉评论区热议
    下一篇:CPO(共封装光学)是什么?工作原理、优劣与厂商全景解析
    您需要登录后才可以回帖 登录 | 立即注册

    手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

    GMT+8, 2026-7-15 06:16 , Processed in 0.730120 second(s), 39 queries , Gzip On.

    Powered by Discuz! X3.5

    © 2025-2026 云栈社区.

    快速回复 返回顶部 返回列表