Linux/C语言实现网卡报文获取与内容修改转发
该实例实现ARP反向代理
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <pcap.h>
#include <assert.h>
#include <stdbool.h>
#define RECV_SEND_DEVICE "ens38"
#define RECV_FILTER "arp or icmp"
const char proxy_mac[6] = {0x00, 0x0c, 0x29, 0x93, 0x19, 0x97};
#define SNAP_LEN 65536
#define Host_Size 1024
#define uchar unsigned char
#define dPrint(fmt, ...) do{fprintf(stderr, "[%s:%d] " fmt "\r\n", __FUNCTION__, __LINE__, ##__VA_ARGS__);}while(0)
#define HexPrint(_buf, _len) \
{\
int _m_i = 0;\
char *_m_buf = (char *)(_buf);\
int _m_len = (int)(_len);\
printf("[%s:%d] \r\n", __FUNCTION__, __LINE__);\
printf("*****************************\n");\
for(_m_i = 0; _m_i < _m_len; _m_i++)\
{\
printf("\033[32m%02x \033[0m", _m_buf[_m_i] & 0xff);\
if(!((_m_i+1) % 10)) printf("\n");\
}\
printf("\nsize = %d\n*****************************\n", _m_len);\
}
typedef struct Ethernet_Head_S
{
uchar dmac[6];
uchar smac[6];
uchar ftype[2];
}Ethernet_Head_T;
typedef struct Arp_Frame_S
{
uchar hw_type[2];
uchar pro_type[2];
uchar hw_size;
uchar pro_size;
uchar opcode[2];
uchar send_mac[6];
uchar send_ip[4];
uchar target_mac[6];
uchar target_ip[4];
}Arp_Frame_T;
typedef struct Ipv4_Frame_S
{
uchar ver_ihl;
uchar tos;
uchar total_len[2];
uchar ident[2];
uchar flags[2];
uchar ttl;
uchar protocol;
uchar head_checksum[2];
uchar src_ip[4];
uchar dst_ip[4];
}Ipv4_Frame_T;
typedef struct Host_Ip_Mac_S
{
uchar ip[4];
uchar mac[6];
}Host_Ip_Mac_T;
Host_Ip_Mac_T host_ip[Host_Size];
unsigned int host_num = 0;
char err_buf[PCAP_ERRBUF_SIZE];
struct bpf_program fp_recv; /* The compiled filter expression */
char filter_recv[] = RECV_FILTER; /* The filter expression (filter 53 port)*/
pcap_t *handle_recv;
bpf_u_int32 mask_recv; /* The netmask of our sniffing device */
bpf_u_int32 net_recv; /* The IP of our sniffing device */
bool is_broadcast(char *dmac, int len)
{
int i;
for(i=0;i<len;i++)
{
uchar x = dmac[i];
if(x != 0xff)
{
return false;
}
}
return true;
}
int is_host_exist(char *src_ip, size_t len)
{
int i;
if(host_num)
{
for(i=0; i<host_num; i++)
{
if(memcmp(src_ip, &host_ip[i].ip, len) == 0)
return i+1;
}
return 0;
}
return 0;
}
void make_arp_frame(const struct pcap_pkthdr *header, const u_char *pkt_data)
{
int ret = 0;
char dst_ip[4] = {0};
memcpy(dst_ip, pkt_data+38, sizeof(dst_ip));
ret = is_host_exist(dst_ip, sizeof(dst_ip));
if(ret)
{
u_char pkt_send[header->caplen];
memset(pkt_send, 0x00, sizeof(pkt_send));
memcpy(pkt_send, pkt_data, header->caplen);
memcpy(pkt_send, host_ip[ret-1].mac, sizeof(proxy_mac));
memcpy(pkt_send+32, host_ip[ret-1].mac, sizeof(proxy_mac));
memcpy(pkt_send+6, proxy_mac, sizeof(proxy_mac));
memcpy(pkt_send+22, proxy_mac, sizeof(proxy_mac));
pcap_sendpacket(handle_recv, pkt_send, sizeof(pkt_send));
}
}
void make_icmp_frame(const struct pcap_pkthdr *header, const u_char *pkt_data)
{
int ret = 0;
char dst_ip[4] = {0};
memcpy(dst_ip, pkt_data+30, sizeof(dst_ip));
ret = is_host_exist(dst_ip, sizeof(dst_ip));
if(ret)
{
u_char pkt_send[header->caplen];
memset(pkt_send, 0x00, sizeof(pkt_send));
memcpy(pkt_send, pkt_data, header->caplen);
memcpy(pkt_send, host_ip[ret-1].mac, sizeof(proxy_mac));
memcpy(pkt_send+6, proxy_mac, sizeof(proxy_mac));
pcap_sendpacket(handle_recv, pkt_send, sizeof(pkt_send));
}
}
void recv_dispatcher_handler(u_char *temp1, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
//HexPrint((const char *)pkt_data, header->caplen);
char dst_mac[6] = {0};
char src_mac[6] = {0};
memcpy(dst_mac, pkt_data, sizeof(dst_mac));
memcpy(src_mac, pkt_data+6, sizeof(src_mac));
if(memcmp(src_mac, proxy_mac, sizeof(proxy_mac)) != 0)
{
int ret = is_broadcast(dst_mac,sizeof(dst_mac));
if(ret)
{
char src_ip[4] = {0};
memcpy(src_ip, pkt_data+28, sizeof(src_ip));
ret = is_host_exist(src_ip, sizeof(src_ip));
if(ret == 0)
{
memcpy(&host_ip[host_num].ip, pkt_data+28, sizeof(int));
memcpy(&host_ip[host_num].mac, pkt_data+22, sizeof(proxy_mac));
host_num++;
}
u_char pkt_send[header->caplen];
memset(pkt_send, 0x00, sizeof(pkt_send));
memcpy(pkt_send, pkt_data, header->caplen);
memcpy(pkt_send+6, proxy_mac, sizeof(proxy_mac));
memcpy(pkt_send+22, proxy_mac, sizeof(proxy_mac));
pcap_sendpacket(handle_recv, pkt_send, sizeof(pkt_send));
}
else
{
if(memcmp(dst_mac, proxy_mac, sizeof(proxy_mac)) == 0)
{
if(pkt_data[12] == 0x08 && pkt_data[13] == 0x06)
{
//arp
char src_ip[4] = {0};
memcpy(src_ip, pkt_data+28, sizeof(src_ip));
ret = is_host_exist(src_ip, sizeof(src_ip));
if(ret == 0)
{
memcpy(&host_ip[host_num].ip, pkt_data+28, sizeof(int));
memcpy(&host_ip[host_num].mac, pkt_data+22, sizeof(proxy_mac));
host_num++;
}
make_arp_frame(header, pkt_data);
}
if(pkt_data[12] == 0x08 && pkt_data[13] == 0x00)
{
make_icmp_frame(header, pkt_data);
}
}
}
}
}
void *pcakage_recv(void *args)
{
pcap_loop(handle_recv, -1, recv_dispatcher_handler, NULL);
return NULL;
}
int main()
{
int ret = 0;
printf("Recv Device: %s\n", RECV_SEND_DEVICE);
printf("Send Device: %s\n", RECV_SEND_DEVICE);
/*get network mask*/
if (pcap_lookupnet(RECV_SEND_DEVICE, &net_recv, &mask_recv, err_buf) == -1) {
fprintf(stderr, "Can't get netmask for device %s\n", RECV_SEND_DEVICE);
net_recv = 0;
mask_recv = 0;
}
/*Open the session in promiscuous mode*/
handle_recv = pcap_open_live(RECV_SEND_DEVICE, SNAP_LEN, 1, 1, err_buf);
if (handle_recv == NULL) {
fprintf(stderr, "Couldn't open device %s: %s\n", RECV_SEND_DEVICE, err_buf);
return -1;
}
/* Compile and apply the filter */
if (pcap_compile(handle_recv, &fp_recv, filter_recv, 0, net_recv) == -1) {
fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_recv, pcap_geterr(handle_recv));
return -1;
}
if (pcap_setfilter(handle_recv, &fp_recv) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n", filter_recv, pcap_geterr(handle_recv));
return -1;
}
pthread_t recv_thread;
ret = (pthread_create(&recv_thread, NULL, pcakage_recv, NULL) == 0);
assert(ret == true);
pthread_join(recv_thread,NULL);
/* cleanup */
pcap_freecode(&fp_recv);
pcap_close(handle_recv);
dPrint("Capture complete.");
return 0;
}