Linux网络抓包

Linux网络抓包

  • 一、以太网帧格式
  • 二、IP报文格式
  • 三、代码实现
  • 四、总结


一、以太网帧格式

Linux网络抓包_第1张图片

以太网帧以7字节前导码和1字节帧开始符开头(物理层),紧跟源地址和目的地址(MAC层)。
IP数据包在DATA字段中,数据段最小为46字节。


二、IP报文格式

Linux网络抓包_第2张图片
IP包的源IP地址和目的IP地址从格式中看出分别从第12字节、第16字节开始(序号从0字节数起)。


三、代码实现

#include 
#include 
#include 
#include 
#include 

typedef unsigned char uchar;

#define BUF_SIZE 2048
#define MIN_ETH_PAYLOAD 46
#define MAC_ADDR_OFFSET (6+6+2)

int main()
{
    int len = 0;
    uchar buff[BUF_SIZE] = {0};

    //AF_PACKET     /* Packet family.  */
    //SOCK_RAW      /* Raw protocol interface.  */
    //ETH_P_ALL     /* Every packet (be careful!!!) */
    int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if(sock < 0)
    {
        printf("create socket failed!");
        return -1;
    }

    while (true)
    {
        len = recvfrom(sock, buff, BUF_SIZE, 0, NULL, NULL);
        if(len < MIN_ETH_PAYLOAD)
        {
            printf("catch invalid data!");
            return -1;
        }

        //打印MAC信息
        printf("Source MAC %X:%X:%X:%X:%X:%X",
               (uchar)buff[6], (uchar)buff[7], (uchar)buff[8], 
               (uchar)buff[9], (uchar)buff[10], (uchar)buff[11]);
        printf("  ---> Dest MAC %X:%X:%X:%X:%X:%X\n",
               (uchar)buff[0], (uchar)buff[1], (uchar)buff[2], 
               (uchar)buff[3], (uchar)buff[4], (uchar)buff[5]);

        //打印IP信息
        printf("Source IP  %d.%d.%d.%d",
               (uchar)buff[MAC_ADDR_OFFSET + 12], (uchar)buff[MAC_ADDR_OFFSET + 13],
               (uchar)buff[MAC_ADDR_OFFSET + 14], (uchar)buff[MAC_ADDR_OFFSET + 15]);
        printf("  ---> Dest IP  %d.%d.%d.%d\n",
               (uchar)buff[MAC_ADDR_OFFSET + 16], (uchar)buff[MAC_ADDR_OFFSET + 17],
               (uchar)buff[MAC_ADDR_OFFSET + 18], (uchar)buff[MAC_ADDR_OFFSET + 19]);
    }

    return 0;
}

四、总结

抓包的方法简洁有效,相对的我们需要了解以太网帧和IP包的格式,才能知道数据包字段值的意义。
值得注意的是,不同版本的协议格式略有不同。

你可能感兴趣的:(C++,linux,udp,tcp/ip)