上回博客我们讲到了内核抓包内核端的实现,通过上篇博客的例子我们就能够开始抓包了,整个抓包的拓扑图如下:

当开始抓包后,抓包机器将抓到的报文送到服务器上,假设服务器地址是192.168.199.123:8099,如果在抓包服务器上打开wireshark可以看到送过来的报文,如下图这样子:

可以看到抓包服务器上收到了报文,但是这样子的报文我们是无法直接拿来分析的,因为实际的报文是封装起来的,需要把数据提取出来封装成wireshark能够识别的格式才行,本篇博客就介绍一下抓包服务器的实现原理。

在看实际的代码之前,我们先来看一下抓包服务器开启后的样子,首先监听本地8099端口

其次将送到该端口的数据封装成pcap格式,使用wireshark打开后如下:

这是实际抓到的报文,能够清楚看到报文里面的各项数据。

下面介绍抓包服务器实现的原理。

抓包服务器功能大致如下:

1. 启动后监听报文送来的地址,在本例中是8099

2. 收到数据后将数据保存到文件中并以wireshark可识别的格式保存。

通常使用wireshark抓包保存的文件都已.pcap为后缀名。里面存储报文的实际数据。pcap文件格式如下:

每个pcap文件都有一个pcap首部,占24字节,之后就是pcap报文头和报文数据,报文头存储了抓包的时间戳等信息。

抓包服务器的任务就是新建一个pcap文件,写入pcap文件头后,之后每收到一个数据就写入一个pcap报文头和报文数据。这样等保存文件后就可以直接使用wireshark打开了。

winpcap是windows版本的开源抓包库,里面提供了包括pcap文件创建、保存等一系列接口,可以直接拿来使用,我这里的例子是windows64位的 golang版本的,Linux版本下有libpcap库可供使用。

代码如下:

// main.go
package mainimport ("fmt""net""os""os/signal""strconv""syscall""time""github.com/google/gopacket""github.com/google/gopacket/layers"//"github.com/google/gopacket/pcap""github.com/google/gopacket/pcapgo"
)type CaptureManager struct {F    *os.File       //抓包文件W    *pcapgo.Writer //用于写文件conn *net.UDPConn   //udp连接
}func CaptureSaveFile() {for {//套接字接收缓存buffer := make([]byte, 65535)//接收数据num, _, err := CapMng.conn.ReadFromUDP(buffer)if nil != err {continue} else {captureInfo := gopacket.CaptureInfo{Timestamp:      time.Now().UTC(),CaptureLength:  num,Length:         num,InterfaceIndex: 0,}//写入pcap数据包头以及数据CapMng.W.WritePacket(captureInfo, buffer[:num])CapMng.F.Seek(0, os.SEEK_END)}}
}var CapMng *CaptureManagerfunc main() {//全局管理控制块CapMng = &CaptureManager{}//创建目录os.MkdirAll("capture_packet", 0777)//创建文件名字t := time.Now()fil := "capture_packet" + "/" + "capture" + "_" + t.Format("20060102150405") + ".pcap"//创建文件CapMng.F, _ = os.Create(fil)//填充pcap文件头部24字节CapMng.W = pcapgo.NewWriter(CapMng.F)CapMng.W.WriteFileHeader(1024, layers.LinkTypeEthernet)//设置监听地址Addr, err := net.ResolveUDPAddr("udp", "0.0.0.0:"+strconv.Itoa(8099))if nil != err {fmt.Println("resulve udp addr fail")return} else {//创建udp连接CapMng.conn, err = net.ListenUDP("udp", Addr)if nil != err {fmt.Println("create conn fail")return} else {fmt.Println("Capture Start")go CaptureSaveFile()}}chSignal := make(chan os.Signal, 5)//signal.Notify(chSignal)//监听指定信号signal.Notify(chSignal, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT,syscall.SIGSEGV, syscall.SIGABRT)fmt.Println("capture server start")//阻塞直至有信号传入sig := <-chSignalswitch sig {case syscall.SIGSEGV, syscall.SIGABRT:default:}fmt.Println("*************Server Recive signal %s, program exit", sig.String())CapMng.F.Close()CapMng.conn.Close()fmt.Println("CLOSE")time.After(1 * time.Second)
}

代码在github上,下载后可在安装了go环境下的windows上直接运行。

git@github.com:FuYuanDe/capture_demo.git

编译go程序可能有点麻烦,但既然都看到这了,估计这点麻烦也不会难道你

到目前位置,内核抓包功能基本的框架已经搭起来了,但是和tcpdump相比,还有很多不足之处,比方说能否根据过滤条件抓取报文?其次,送到远端服务器上的时候如果mtu值很小怎么办?要不要分片?还有就是在POST_ROUTING上的hook函数抓到的报文是没有mac地址的!!!啥?没MAC地址! 没错,本机出去的报文在IP层还没有填写MAC地址,这时候抓包的话是无法得到目的mac地址的。有空的话再聊聊这些问题的解决方法。有问题的同志想要交流的话可以加群讨论一下奥

参考资料:

1.

Winpcap的安装使用方法和问题总结

https://blog.csdn.net/yu314092706/article/details/52937189

2.

golang使用gopacket包进行数据包捕获,注入和分析

https://blog.csdn.net/ptmozhu/article/details/72652310?utm_source=itdadao&utm_medium=referral

3. pcap文件格式分析

https://www.cnblogs.com/2017Crown/p/7162303.html

またね!

Linux 内核抓包功能实现基础(三) 抓包服务器的实现相关推荐

  1. 嵌入式系统Linux内核开发工程师必须掌握的三十道题

    嵌入式系统Linux内核开发工程师必须掌握的三十道题 如果你能正确回答以下问题并理解相关知识点原理,那么你就可以算得上是基本合格的Linux内核开发工程师,试试看! 1) Linux中主要有哪几种内核 ...

  2. Linux内核管理之分配掩码(三)

    Linux内核管理之分配掩码(三) 分配掩码是linux内存管理中非常重要的一个参数,它影响着页面分配的整个流程. 分配掩码gfp_mask定义在include/linux/gfp.h文件中,这些标志 ...

  3. linux 适配电脑内核,Linux内核实践 如何添加网络协议[三]:实现 -电脑资料

    内核版本:2.6.34 接上篇<添加网络协议>, 为了用户方便查看brcm设备的工作状态,使用proc文件系统是很好的方 式.一个网络协议模块可以注册到网络空间中register_pern ...

  4. linux内核中的文件描述符(三)--fd的回收

    linux内核中的文件描述符(三)--fd的回收 Kernel version:2.6.14 CPU architecture:ARM920T Author:ce123(http://blog.csd ...

  5. linux 内核抓包功能实现基础(一)设计思路

    linux平台下面已经有了抓包工具tcpdump, 非常经典,使用起来也非常方便.但是因为某些系统架构上或者其它方面的原因,有时候tcpdump并不能满足产品实际需要,公司的产品是电信运营商相关的软硬 ...

  6. Linux 内核抓包功能实现基础(四) 手动查找邻居缓存填充MAC地址

    之前写了三篇关于内核抓包功能的实现,包括抓包原理.实现以及抓包服务器的实现.基本的功能都已经有了,但是还有些小问题有待解决.今天有空就解决一下. 开发版本基于内核3.4.39. 先介绍一下问题背景,抓 ...

  7. Linux 内核抓包功能实现基础(五) 常见问题解析

    之前在部门产品上开发了内核抓包模块,基于openwrt平台,通过netfilter框架实现相关功能.核心功能就是在netfilter 的PRE_ROUTING 和 POST_ROUTING链上增加两个 ...

  8. linux内核4.0,新闻|Linux内核4.0功能:实时内核补丁,支持PS3

    Linux Torvalds 在Linux内核邮件列表里发布了Linux内核新的稳定版. Linux 4.0,代号为'Hurr durr I'm a sheep',带来了一小系列新硬件支持,驱动改进, ...

  9. 2018-2019-1 20189204《Linux内核原理与分析》第三周作业

    OS是如何工作的 学习任务: 阅读学习教材「庖丁解牛Linux 」第2章 学习蓝墨云班课中第三周视频「操作系统是如何工作的?」,并完成实验楼上配套实验二. 云班课学习笔记: 计算机三大法宝 程序存储计 ...

最新文章

  1. CB Insights发布2017全球AI企业100强,出门问问、碳云智能入选
  2. VTK:网格质量用法实战
  3. numpy 的基本使用1
  4. 牛客题霸 单链表的选择排序 C++题解/答案
  5. ios程序 调试log宏的添加
  6. 使用AIR运行另外的程序。
  7. Spring RestTemplate的使用示例
  8. rabbitMQ概念详细介绍
  9. 常用汉字3500——文字识别数据准备
  10. 消息队列简介-原理与应用
  11. 7-2 Rank a Linked List (25 分)
  12. notepad++之正则表达式的使用
  13. Linux系统和程序中的DEP和ASLR保护机制
  14. Win7系统服务优化攻略
  15. 虚幻4 UE4 蓝图C++混合编程
  16. 图片填充整个PictureBox
  17. 《从你的全世界路过》之稻城
  18. 天猫店群玩法有流量销售额却上不去?可能是转化率出了问题。
  19. 读《孙悟空是个好员工》有感(2005-5-23)
  20. 武汉Java培训机构排名最新数据,这家机构始终名列前茅

热门文章

  1. 求职过程记录(5)——黎明到来
  2. 神经网络调参---权重对分类性能的影响
  3. Minst 0-9特征迭代次数曲线表达式
  4. Loss Function , Cost Function and Kernel Function in ML(To be continued)
  5. 3.2 选择最可能的句子-深度学习第五课《序列模型》-Stanford吴恩达教授
  6. ubuntu 10.10开机自启动svn服务
  7. 第1章 Qt概述和下载安装及创建工程
  8. 简单算法题:leetcode-2 两数相加
  9. Spring Cloud -Zuul
  10. php调用以太坊geth API说明