【Golang】嗅探抓包工具,解決線上偶現問題來不及抓包的情況


背景

測試群里經常看到客戶端的同學反饋發現了偶現Bug,但是來不及抓包,最后不了了之,最近出現得比較頻繁,所以寫個小腳本解決這個問題。

實現思路

之前寫過一個埋點工具,輔助測試埋點的數據,解決多個端的埋點需要打開不同的抓包軟件,並且需要肉眼去比對的的不便,也是使用的抓包分析數據並在界面(pyqt5)展示的方式,這一次主要是進行日志的管理,保存請求記錄,所以實現的思路比較簡單:

  • 抓包
  • 存日志
  • 做日志管理

具體實現

此前使用過優步的號稱性能最好的golang日志管理包zap,結合lumberjack對日志的管理特別的方便,幾個配置參數就能滿足需求,比如一鍵日志壓縮壓縮后1M只占20Kb。所以拿來即用,

lumberjack常見的配置參數

參數 含義
Filename: // 日志文件路徑
MaxSize: // 每個日志文件保存的最大尺寸 單位:M
MaxBackups: // 日志文件最多保存多少個備份
MaxAge: // 文件最多保存多少天
Compress: // 是否壓縮, 壓縮后1M約占20Kb

Go build 成不同操作系統可執行文件

而且golang可以很簡單的把代碼編譯成不同系統都能執行的程序或者二進制包。

Mac下編譯Linux, Windows平台的64位可執行程序:

$ CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build test.go  # Mac
$ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build test.go  # linux
$ CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build test.go  # windows

具體代碼

package main

import (
	"fmt"
	"os"
	"time"

	"github.com/google/gopacket"
	"github.com/google/gopacket/pcap"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
)

var (
	device            = "en0" // 指定監控網卡名稱信息
	snapshotLen int32 = 10000000
	promiscuous       = false
	err         error
	timeout     = 30 * time.Second
	handle      *pcap.Handle
)

func main() {
	handle, err = pcap.OpenLive(device, snapshotLen, promiscuous, timeout)
	filter := "host test.baidu.com" // 指定抓取域名
	err = handle.SetBPFFilter(filter)
	defer handle.Close()
	log := initLog()
	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
	for packet := range packetSource.Packets() {
		applicationLayer := packet.ApplicationLayer()
		if applicationLayer != nil {
			log.Info(string(applicationLayer.LayerContents()))
		}
		if err := packet.ErrorLayer(); err != nil {
			fmt.Println("Error decoding some part of the packet:", err)
		}
	}
}

func initLog() *zap.Logger {
	hook := lumberjack.Logger{
		Filename:   "./logs/package.log", // 日志文件路徑
		MaxSize:    10,                   // 每個日志文件保存的最大尺寸 單位:M
		MaxBackups: 5,                    // 日志文件最多保存多少個備份
		MaxAge:     7,                    // 文件最多保存多少天
		Compress:   true,                 // 是否壓縮, 壓縮后1M約占20Kb
	}

	encoderConfig := zapcore.EncoderConfig{
		TimeKey:        "time",
		LevelKey:       "level",
		NameKey:        "logger",
		MessageKey:     "msg",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.LowercaseLevelEncoder,  // 小寫編碼器
		EncodeTime:     zapcore.ISO8601TimeEncoder,     // ISO8601 UTC 時間格式
		EncodeDuration: zapcore.SecondsDurationEncoder, //
	}

	// 設置日志級別
	atomicLevel := zap.NewAtomicLevel()
	atomicLevel.SetLevel(zap.InfoLevel)

	core := zapcore.NewCore(
		zapcore.NewConsoleEncoder(encoderConfig),                                        // 編碼器配置
		zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(&hook)), // 打印到控制台和文件
		atomicLevel, // 日志級別
	)
	logger := zap.New(core)

	logger.Info("log 初始化成功")
	return logger
}

Python 抓包

Python使用scapy也能很簡單的完成抓包操作:

from scapy.all import *


def _print(_packet):
    """
    指定抓包信息打印規則
    :param _packet: 
    :return: 
    """
    return "\n".join((
        "\n".join(_packet.sprintf("{Raw:%Raw.load%}").split(r"\r\n")),
    ))


sniff(
    iface='en0',
    prn=_print,
    filter="host test.baidu.com"  # 指定過濾域名
)

配上日志管理模塊也能很快的完成實現。

總結

抓包,日志管理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM