Go语言Ubuntu下打印网络请求报文信息
来源:互联网 发布:前瞻网数据 编辑:程序博客网 时间:2024/06/05 15:59
package mainimport ( "time" "github.com/google/gopacket/pcap" "log" "fmt" "github.com/google/gopacket" "github.com/google/gopacket/layers" "strings" "vprobe/rawtransaction" "sync" "encoding/json" "vprobe/metric" "strconv")var ( device string = "eth1" snapshot_len int32 = 1024 promiscuous bool = false timeout time.Duration = 30 * time.Second //handle *pcap.Handle localAddress string errorNumber int = 0 channel chan bool = make(chan bool) lock = &sync.RWMutex{} // Metrics到ops-agent的上报周期(30s)或其他值,可配置,范围为1-60s // ops-agent到kafka的上报周期以分钟为粒度,可配置,范围为1-5分钟 noresp int = 30000 // 指标上报周期为30秒,即30000毫秒 requestList []rawtransaction.RequestIdentification = make([]rawtransaction.RequestIdentification, 0, 50) // 30个元素,预留20个元素 rawTransactions []rawtransaction.Transaction = make([]rawtransaction.Transaction, 0, 50) // 未处理的事务 transactionList []metric.Transaction = make([]metric.Transaction, 0, 50) // 经过处理的事务)func main() { // 查找设备 devices, err := pcap.FindAllDevs() if err != nil { log.Fatal(err) } MainThread: for _, dev := range devices { if strings.EqualFold(dev.Name, device) { for _, address := range dev.Addresses { // 获取到了本地IP localAddress = address.IP.To4().String() break MainThread } } } go capturePacket() go submitTrans() go formMetrics() <-channel}/** * 抓取报文 */func capturePacket() { // 实时监控 handle, err: = pcap.OpenLive(device, snapshot_len, promiscuous, timeout) if err != nil { log.Fatal(err) } defer handle.Close() // 设置过滤80==========================80端口 var filter string = "tcp and port 80" err = handle.SetBPFFilter(filter) if err != nil { log.Fatal(err) } fmt.Println("Only capturing TCP port 80 packets.") packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for packet := range packetSource.Packets() { // 直接打印抓到的数据包 //fmt.Println(packet) // 打印解析之后的数据包信息 printPacketInfo(packet) } channel <- true}/** * 解析报文 */func printPacketInfo(packet gopacket.Packet) { ipLayer := packet.Layer(layers.LayerTypeIPv4) if ipLayer != nil { // 包含IP包 ip, _ := ipLayer.(*layers.IPv4) tcpLayer := packet.Layer(layers.LayerTypeTCP) if tcpLayer != nil { // 包含TCP包 tcp, _ := tcpLayer.(*layers.TCP) applicationLayer := packet.ApplicationLayer() if applicationLayer != nil { payload := string(applicationLayer.Payload()) if strings.Contains(payload, "HTTP") { //fmt.Printf("源IP地址:%s -----目的IP地址:%s\n", ip.SrcIP, ip.DstIP) //fmt.Printf("源端口:%d --------目的端口:%d\n", tcp.SrcPort, tcp.DstPort) // 时间戳 timestamp := int(packet.Metadata().Timestamp.Unix()) //fmt.Println("时间戳:" + timestamp) // 报文内容 //packetContent := packet.Data() //fmt.Println("报文内容:" + string(packetContent)) // 报文总长度 //packetLength := packet.Metadata().CaptureLength //fmt.Println("报文长度:" + strconv.Itoa(packetLength)) //fmt.Println("协议类型: ", ip.Protocol) lock.Lock() if strings.EqualFold(localAddress, ip.SrcIP.String()) { // 这个包代表的是HTTP请求,添加到请求列表 iden := ip.SrcIP.String() + tcp.SrcPort.String() + ip.DstIP.String() + tcp.DstPort.String() reqiden := rawtransaction.RequestIdentification{ timestamp, -1, iden, false, 0, } requestList = append(requestList, reqiden) } else { // 这个包代表的是HTTP响应,查看是否有请求与其对应 iden := ip.DstIP.String() + tcp.DstPort.String() + ip.SrcIP.String() + tcp.SrcPort.String() for i, _ := range requestList { if strings.EqualFold(requestList[i].Identification, iden) { // 那么这个响应就是请求reqiden的 if timestamp - requestList[i].Timestamp > noresp { // 超时了,形成异常事务。在这里,不去修改这个请求,说明这个请求在规定的时间内没有收到响应 } else { // 没有超时,形成正常事务,请求时间戳,响应时间戳,响应码 contents := strings.Split(payload, " ") if len(contents) >=2 { code, err := strconv.Atoi(contents[1]) if err == nil { // 没有错误,可以获取响应码 requestList[i].Modify = true requestList[i].RespTimestamp = timestamp requestList[i].Code = code } else { // 没有获取到响应码 } } } } else { // 这是只有响应,没有请求与之对应,暂时先不管? } } } lock.Unlock() } } } }}/** * 每隔30秒就将这30秒之内产生的原始请求进行解析,形成“事务”,缓存到“事务”列表 */func submitTrans() { c := time.Tick(30 * time.Second) for _ = range c { lock.Lock() // 用一个临时变量来记住请求,减少锁的持有时间 tempRequestList := requestList requestList = requestList[:0] lock.Unlock() for _, reqiden := range tempRequestList{ if reqiden.Modify { // 该请求是被修改过了的,也就是说有响应 rawtra := rawtransaction.Transaction { rawtransaction.Request{reqiden.Timestamp}, rawtransaction.Response{reqiden.RespTimestamp, reqiden.Code}, } rawTransactions = append(rawTransactions, rawtra) } else { // 异常事务+1 errorNumber++ } } }}/** * 每隔5分钟就将这5分钟之内收集到的“事务”形成一个“记录” */func formMetrics() { c := time.Tick(300 * time.Second) for _ = range c { for _, rawTransaction := range rawTransactions { transaction := metric.Transaction{ rawTransaction.Request.Timestamp, rawTransaction.Response.Timestamp - rawTransaction.Request.Timestamp, rawTransaction.Response.Code, } transactionList = append(transactionList, transaction) } metric := metric.Metric{ len(transactionList), transactionList, errorNumber, } // 把“记录”打印出来 metricJson, _ := json.Marshal(metric) fmt.Println(string(metricJson)) //操作之后,清空requestList和rawTransactions lock.Lock() transactionList = transactionList[:0] rawTransactions = rawTransactions[:0] errorNumber = 0 lock.Unlock() }}
0 0
- Go语言Ubuntu下打印网络请求报文信息
- Ubuntu下安装go语言
- Ubuntu下GO语言实践
- Ubuntu下安装go语言
- Ubuntu 下安装Go语言
- Ubuntu 下安装Go语言
- Ubuntu下Go语言环境安装
- go语言打印九九乘法表
- Webservice axis2打印请求、响应报文方法
- Ubuntu go语言环境
- Ubuntu go语言环境
- Ubuntu go语言环境
- Ubuntu安装Go语言
- Go语言网络编程
- go语言网络编程
- Go语言打印调用堆栈
- Go语言打印调用堆栈
- Ubuntu 10.x下安装go语言开发环境
- 图像处理之形态学梯度计算
- 数据库30条军规解读
- 电脑更换硬盘 如何保护信息安全?
- 关于SQL Server将一列的多行内容拼接成一行的问题讨论
- Linux和Windows链接动态库的区别
- Go语言Ubuntu下打印网络请求报文信息
- onvif_discovery_client搜索多个网段内的onvif设备(IPC)
- java 为pdf添加水印图片
- 用到了bash的几个知识点,记录一下
- UNIX再学习 -- 文件描述符
- ubuntu中关于python学习深度学习 pip Theano Tensorflow
- C++中关于windows窗体的编程
- 欢迎使用CSDN-markdown编辑器
- linux管道