You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PLC场景下Linux管道TCPDump转存pcap文件失败问题求助

问题分析与解决方案

原脚本的核心问题

  1. cat mypipe阻塞无法退出:cat会一直等待管道写端关闭才会终止,但tcpdump持续向管道写入数据,导致第一个文件无限增大,永远无法进入sleep环节;强制停止时文件没有完整的pcap结尾,Wireshark无法识别。
  2. 未处理数据包截断与流量过滤:既没过滤OPC UA流量,也没实现丢弃前54字节的需求。

无依赖解决方案脚本

以下脚本仅使用Linux基础命令(tcpdump/dd/xxd/od/timeout),适配无包管理器的PLC环境:

#!/bin/bash

output_dir="/opt/plcnext/"
output_base_name="capture"
interval=300
pipe_name="mypipe"
opcua_port="4840" # OPC UA默认端口,若使用其他端口请修改

# 确保输出目录存在
mkdir -p "$output_dir"

# 清理旧管道并创建新管道
rm -f "$pipe_name"
mkfifo "$pipe_name"

# 处理pcap数据包:丢弃前54字节并修正pcap记录头
process_pcap() {
    # 读取并输出pcap文件头(固定24字节)
    dd bs=24 count=1 2>/dev/null
    
    # 循环处理每个数据包记录
    while true; do
        # 读取16字节的数据包记录头
        read -r -n 16 rec_header || break
        
        # 解析记录头中的捕获长度与原始长度(小端序)
        cap_len=$(echo "$rec_header" | dd bs=1 skip=8 count=4 2>/dev/null | xxd -p -r | od -t u4 -An | tr -d ' ')
        orig_len=$(echo "$rec_header" | dd bs=1 skip=12 count=4 2>/dev/null | xxd -p -r | od -t u4 -An | tr -d ' ')
        
        # 仅处理长度≥54字节的数据包
        if [ "$cap_len" -ge 54 ] && [ "$orig_len" -ge 54 ]; then
            new_cap_len=$((cap_len - 54))
            new_orig_len=$((orig_len - 54))
            
            # 生成修改后的记录头(替换长度字段为截断后的值)
            new_rec_header=$(echo -n "${rec_header:0:8}" \
                && echo -n "$new_cap_len" | od -t u4 -An -w4 --endian=little | xxd -r -p \
                && echo -n "$new_orig_len" | od -t u4 -An -w4 --endian=little | xxd -r -p)
            
            # 输出修改后的记录头
            echo -n "$new_rec_header"
            # 读取数据包内容,跳过前54字节并输出剩余部分
            dd bs=1 skip=54 count="$new_cap_len" 2>/dev/null
        else
            # 长度不足的数据包直接丢弃
            dd bs=1 count="$cap_len" 2>/dev/null >/dev/null
        fi
    done
}

# 后台启动tcpdump:过滤OPC UA流量,处理后写入命名管道
tcpdump -i any -w - port "$opcua_port" 2>/dev/null | process_pcap > "$pipe_name" &
tcpdump_pid=$!

# 捕获中断信号,清理进程与管道
trap "kill $tcpdump_pid; rm -f $pipe_name; exit" INT TERM

# 循环每5分钟保存一次管道内容
while true; do
    current_time=$(date +"%Y%m%d%H%M%S")
    output_file="${output_dir}/${output_base_name}_${current_time}.pcap"
    
    # 读取管道内容300秒后自动终止,写入目标文件
    timeout "$interval" cat "$pipe_name" > "$output_file"
    
    # 清理空文件
    if [ -s "$output_file" ]; then
        echo "Saved capture to $output_file"
    else
        rm -f "$output_file"
        echo "No data captured in this interval, skipped file creation"
    fi
done

关键逻辑说明

  1. 流量过滤:通过tcpdump port 4840仅捕获OPC UA默认端口的流量。
  2. 数据包截断:解析pcap记录头,修改数据包长度字段后,丢弃每个以太网帧的前54字节(以太网头14+IP头20+TCP头20),保留IP地址与OPC UA消息内容。
  3. 定时转存:用timeout 300 cat mypipe实现每5分钟读取一次管道内容,避免阻塞;生成的文件是完整的pcap格式,可直接在Wireshark中打开。
  4. 资源清理:通过trap捕获中断信号,自动停止tcpdump并删除管道,避免残留进程。

内容的提问来源于stack exchange,提问作者BrenDs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 01:12:28