如何用Go实现类Bash的tcpdump流式传输至Wireshark?
问题描述
需要用Go实现一段与以下Bash命令功能相同的代码:
ssh -p 8022 root@${h} -i \~/.ssh/eve -C 'tcpdump -U -i '${i}' -w -' | /Applications/Wireshark.app/Contents/MacOS/Wireshark -i - -k &
该命令通过SSH在远程主机执行tcpdump(-U参数确保完整数据包输出到stdout),再通过管道将数据流传输到本地Wireshark进行实时分析,运行正常。
自行编写的Go代码如下:
func main() { Command := "ssh -i $HOME/.ssh/id_rsa.sbm n@127.0.0.6 -p 21057 -C \"sudo tcpdump -U -i any host 10.1.1.1 -w -\"" cmd := exec.Command("bash", "-c", Command) stdout, _ := cmd.StdoutPipe() reader := bufio.NewReader(stdout) go func(reader io.Reader) { scanner := bufio.NewScanner(reader) for scanner.Scan() { os.Stdout.Write(scanner.Bytes()) } }(reader) if err := cmd.Start(); nil != err { log.Fatalf("Error starting program: %s, %s", cmd.Path, err.Error()) } cmd.Wait() }
编译为stdinoutExample后执行:
./stdinoutExample | /Applications/Wireshark.app/Contents/MacOS/Wireshark -i - -k 2>/dev/null &
Wireshark能接收到数据,但无法解析,显示乱码并提示数据包字段错误。请问如何用Go实现与Bash一致的正确数据传输?
解决方案
问题根源
tcpdump输出的是二进制pcap格式数据流,而非文本行。原代码中使用bufio.Scanner按行读取数据,会将二进制流中的换行符作为分隔符截断数据,破坏pcap的结构化格式,导致Wireshark无法解析。Bash管道是字节级的原样传输,不会对数据流做任何分割处理,这是两者的核心差异。
修复方案
直接通过io.Copy将远程命令的stdout字节流原样复制到本地的os.Stdout,完全模拟Bash管道的行为。修改后的代码如下:
package main import ( "io" "log" "os" "os/exec" ) func main() { command := "ssh -i $HOME/.ssh/id_rsa.sbm n@127.0.0.6 -p 21057 -C \"sudo tcpdump -U -i any host 10.1.1.1 -w -\"" cmd := exec.Command("bash", "-c", command) stdout, err := cmd.StdoutPipe() if err != nil { log.Fatalf("获取stdout管道失败: %v", err) } // 字节级原样复制数据流,与Bash管道行为一致 go func() { _, copyErr := io.Copy(os.Stdout, stdout) if copyErr != nil && copyErr != io.EOF { log.Printf("数据复制出错: %v", copyErr) } }() if err := cmd.Start(); err != nil { log.Fatalf("启动命令失败: %v", err) } if err := cmd.Wait(); err != nil { log.Printf("命令执行退出异常: %v", err) } }
说明
io.Copy会逐字节复制输入流到输出流,完全保留原始二进制数据的结构,不会像bufio.Scanner那样分割数据。- 补充了原代码中忽略的错误检查,避免潜在的隐性问题。
- 编译后执行原有的管道命令,Wireshark即可正常解析pcap数据流。
内容的提问来源于stack exchange,提问作者n1k3
相关产品推荐
相关产品推荐

