c写socket网络抓包功能带过滤,不用libpcap,直接使用socket抓包
时间: 2024-05-09 17:16:27 浏览: 86
基于C语言使用 libpcap 对 IPv4 抓包实现【100011873】
要使用socket来抓包,需要在程序中创建一个原始套接字。下面是一个简单的示例程序,可以抓取指定IP地址和端口号的网络数据包:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#define BUFSIZE 65536
int main(int argc, char *argv[]) {
int sock_raw, sock_tcp, recv_len;
char buffer[BUFSIZE];
struct sockaddr_in saddr;
struct iphdr *iph;
struct tcphdr *tcph;
if (argc != 3) {
printf("Usage: %s <source IP> <destination IP>\n", argv[0]);
exit(1);
}
// 创建原始套接字
sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
if (sock_raw < 0) {
perror("socket() error");
exit(1);
}
// 绑定原始套接字到指定源IP地址
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = inet_addr(argv[1]);
if (bind(sock_raw, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
perror("bind() error");
close(sock_raw);
exit(1);
}
// 过滤指定目的IP地址和端口号的数据包
struct sockaddr_in daddr;
daddr.sin_family = AF_INET;
daddr.sin_addr.s_addr = inet_addr(argv[2]);
struct sock_filter filter[] = {
{0x28, 0, 0, 0x0000000c},
{0x15, 0, 5, 0x00000800},
{0x20, 0, 0, 0x0000001e},
{0x15, 0, 3, daddr.sin_addr.s_addr},
{0x20, 0, 0, 0x00000022},
{0x15, 0, 1, 0x0000006f},
{0x6, 0, 0, 0x0000ffff},
{0x6, 0, 0, 0x00000000},
};
struct sock_fprog fprog;
fprog.len = sizeof(filter)/sizeof(filter[0]);
fprog.filter = filter;
if (setsockopt(sock_raw, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)) < 0) {
perror("setsockopt() error");
close(sock_raw);
exit(1);
}
// 创建TCP套接字
sock_tcp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock_tcp < 0) {
perror("socket() error");
close(sock_raw);
exit(1);
}
// 接收网络数据包并分析
while (1) {
recv_len = recv(sock_raw, buffer, BUFSIZE, 0);
if (recv_len < 0) {
perror("recv() error");
close(sock_raw);
close(sock_tcp);
exit(1);
}
iph = (struct iphdr *)buffer;
if (iph->protocol == IPPROTO_TCP) {
tcph = (struct tcphdr *)(buffer + iph->ihl*4);
if (ntohs(tcph->dest) == 80) {
printf("Source IP: %s\n", inet_ntoa(*(struct in_addr *)&iph->saddr));
printf("Destination IP: %s\n", inet_ntoa(*(struct in_addr *)&iph->daddr));
printf("Source port: %d\n", ntohs(tcph->source));
printf("Destination port: %d\n", ntohs(tcph->dest));
}
}
}
close(sock_raw);
close(sock_tcp);
return 0;
}
```
该示例程序使用了一个过滤器来过滤指定目的IP地址和端口号的数据包。过滤器是一个由一组过滤规则组成的程序,用于过滤网络数据包。在本示例中,过滤器使用了Linux内核提供的BPF虚拟机进行解释和执行。可以通过修改过滤器规则来实现更复杂的过滤功能。
阅读全文