路由部分重写,ARP 请求广播测试完成,ARP 收包并存ip-mac入数据库完成,防火墙过滤完成
This commit is contained in:
parent
a21e259272
commit
fe2a027eaa
97
router/db.c
97
router/db.c
|
@ -1,6 +1,10 @@
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
char next_hop_ip[16] = "";
|
||||||
|
char gateway_ip[16] = "";
|
||||||
|
char mac_address[18] = "";
|
||||||
|
|
||||||
int connect_mysql(const char *host, int port, const char *user, const char *pwd, const char *db_name)
|
int connect_mysql(const char *host, int port, const char *user, const char *pwd, const char *db_name)
|
||||||
{
|
{
|
||||||
if (conn_db == NULL)
|
if (conn_db == NULL)
|
||||||
|
@ -179,6 +183,24 @@ void insert_arp_list(const char *ip, const char *mac)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void update_arp_list_by_ip(const char *ip, const char *mac)
|
||||||
|
{
|
||||||
|
char sql[100];
|
||||||
|
sprintf(sql, "update ip_mac set mac = '%s' where ip = '%s'", mac, ip);
|
||||||
|
if (mysql_real_query(conn_db, sql, strlen(sql)) != 0)
|
||||||
|
{
|
||||||
|
printf("更新ARP表失败\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int search_arp_list_if_ip_have(const char *ip)
|
||||||
|
{
|
||||||
|
char sql[100];
|
||||||
|
sprintf(sql, "select * from ip_mac where ip = '%s'", ip);
|
||||||
|
int ret = result_rows(sql);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void print_arp_list()
|
void print_arp_list()
|
||||||
{
|
{
|
||||||
char sql[100];
|
char sql[100];
|
||||||
|
@ -228,4 +250,77 @@ void delete_ip_fw(const char *ip)
|
||||||
{
|
{
|
||||||
printf("删除黑名单失败\n");
|
printf("删除黑名单失败\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int is_in_routing_table(const char *dst_ip)
|
||||||
|
{
|
||||||
|
char sql[100];
|
||||||
|
sprintf(sql, "select * from routing_list where ip = '%s'", dst_ip);
|
||||||
|
int ret = result_rows(sql);
|
||||||
|
return ret > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_next_hop_ip(const char *dst_ip, char *next_hop_ip)
|
||||||
|
{
|
||||||
|
char sql[100];
|
||||||
|
sprintf(sql, "select nexthop from routing_list where ip = '%s'", dst_ip);
|
||||||
|
query(sql, fetch_next_hop_ip); // fetch_next_hop_ip 是一个回调函数,用于从查询结果中获取下一跳 IP
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_default_gateway_ip(char *gateway_ip)
|
||||||
|
{
|
||||||
|
char sql[100];
|
||||||
|
sprintf(sql, "select nexthop from routing_list where ip = '0.0.0.0'");
|
||||||
|
query(sql, fetch_gateway_ip); // fetch_gateway_ip 是一个回调函数,用于从查询结果中获取默认网关 IP
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_in_arp_table(const char *ip)
|
||||||
|
{
|
||||||
|
char sql[100];
|
||||||
|
sprintf(sql, "select * from ip_mac where ip = '%s'", ip);
|
||||||
|
int ret = result_rows(sql);
|
||||||
|
return ret > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_mac_address(const char *ip, char *mac_address)
|
||||||
|
{
|
||||||
|
char sql[100];
|
||||||
|
sprintf(sql, "select mac from ip_mac where ip = '%s'", ip);
|
||||||
|
query(sql, fetch_mac_address); // fetch_mac_address 是一个回调函数,用于从查询结果中获取 MAC 地址
|
||||||
|
}
|
||||||
|
|
||||||
|
void fetch_next_hop_ip(MYSQL_ROW row, char (*columns)[30], int cols)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < cols; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(columns[i], "nexthop") == 0)
|
||||||
|
{
|
||||||
|
strcpy(next_hop_ip, row[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fetch_gateway_ip(MYSQL_ROW row, char (*columns)[30], int cols)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < cols; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(columns[i], "nexthop") == 0)
|
||||||
|
{
|
||||||
|
strcpy(gateway_ip, row[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fetch_mac_address(MYSQL_ROW row, char (*columns)[30], int cols)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < cols; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(columns[i], "mac") == 0)
|
||||||
|
{
|
||||||
|
strcpy(mac_address, row[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
30
router/db.h
30
router/db.h
|
@ -42,6 +42,12 @@ extern void printResult(MYSQL_ROW row, char (*columns)[30], int cols);
|
||||||
// 添加ARP表
|
// 添加ARP表
|
||||||
extern void insert_arp_list(const char *ip, const char *mac);
|
extern void insert_arp_list(const char *ip, const char *mac);
|
||||||
|
|
||||||
|
// 更新ARP表中的一条记录
|
||||||
|
extern void update_arp_list_by_ip(const char *ip, const char *mac);
|
||||||
|
|
||||||
|
// 查询ARP表中是否存在此IP
|
||||||
|
extern int search_arp_list_if_ip_have(const char *ip);
|
||||||
|
|
||||||
// 打印ARP表
|
// 打印ARP表
|
||||||
extern void print_arp_list();
|
extern void print_arp_list();
|
||||||
|
|
||||||
|
@ -57,4 +63,28 @@ extern void print_ip_fw();
|
||||||
// 删除黑名单中的一条记录
|
// 删除黑名单中的一条记录
|
||||||
extern void delete_ip_fw(const char *ip);
|
extern void delete_ip_fw(const char *ip);
|
||||||
|
|
||||||
|
// 判断目的 IP 是否在路由表中
|
||||||
|
extern int is_in_routing_table(const char *dst_ip);
|
||||||
|
|
||||||
|
// 获取下一跳 IP
|
||||||
|
extern void get_next_hop_ip(const char *dst_ip, char *next_hop_ip);
|
||||||
|
|
||||||
|
// 获取默认网关 IP
|
||||||
|
extern void get_default_gateway_ip(char *gateway_ip);
|
||||||
|
|
||||||
|
// 判断 IP 是否在 ARP 表中
|
||||||
|
extern int is_in_arp_table(const char *ip);
|
||||||
|
|
||||||
|
// 获取 MAC 地址
|
||||||
|
extern void get_mac_address(const char *ip, char *mac_address);
|
||||||
|
|
||||||
|
// 回调函数:从查询结果中获取下一跳 IP
|
||||||
|
extern void fetch_next_hop_ip(MYSQL_ROW row, char (*columns)[30], int cols);
|
||||||
|
|
||||||
|
// 回调函数:从查询结果中获取默认网关 IP
|
||||||
|
extern void fetch_gateway_ip(MYSQL_ROW row, char (*columns)[30], int cols);
|
||||||
|
|
||||||
|
// 回调函数:从查询结果中获取 MAC 地址
|
||||||
|
extern void fetch_mac_address(MYSQL_ROW row, char (*columns)[30], int cols);
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -1,209 +1,305 @@
|
||||||
#include "net_task_thread.h"
|
#include "net_task_thread.h"
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
|
|
||||||
|
extern volatile int stop_thread; // 声明
|
||||||
|
|
||||||
void *net_task(void *arg)
|
void *net_task(void *arg)
|
||||||
{
|
{
|
||||||
|
|
||||||
printf("net_task\n");
|
printf("net_task\n");
|
||||||
|
|
||||||
char *dev1 = "ens38"; // 第一个网卡
|
char *dev = pcap_lookupdev(errbuf); // 获取网络接口
|
||||||
char *dev2 = "ens33"; // 第二个网卡
|
if (dev == NULL) // 获取网络接口失败
|
||||||
|
{
|
||||||
|
printf("pcap_lookupdev error: %s\n", errbuf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
printf("网络接口: %s\n", dev);
|
||||||
|
|
||||||
// 打开网卡设备
|
// 获取网卡的网络号,掩码地址
|
||||||
// libnet_context1 使用 open_device 函数打开网卡设备1 后返回的 libnet 上下文
|
bpf_u_int32 netip, netmask;
|
||||||
libnet_context1 = open_device(&device1, dev1);
|
if (pcap_lookupnet(dev, &netip, &netmask, NULL) == 0)
|
||||||
libnet_context2 = open_device(&device2, dev2);
|
{
|
||||||
|
unsigned char ip[INET_ADDRSTRLEN] = "";
|
||||||
|
unsigned char mask[INET_ADDRSTRLEN] = "";
|
||||||
|
|
||||||
// 开始捕获数据包:
|
inet_ntop(AF_INET, &netip, ip, INET_ADDRSTRLEN);
|
||||||
// pcap_loop: 网卡设备、捕获的数据包个数、回调函数、传递给回调函数的参数
|
inet_ntop(AF_INET, &netmask, mask, INET_ADDRSTRLEN);
|
||||||
pcap_loop(device1, -1, process_packet, NULL); // -1 表示无限循环
|
printf("网络地址: %s 掩码地址: %s\n", ip, mask);
|
||||||
pcap_loop(device2, -1, process_packet, NULL); // -1 表示无限循环
|
}
|
||||||
|
|
||||||
return NULL;
|
// 打开网络设备,开始捕获数据
|
||||||
|
pcap_t *pcap_handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);
|
||||||
|
if (pcap_handle == NULL)
|
||||||
|
{
|
||||||
|
printf("pcap_open_live error: %s\n", errbuf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
struct pcap_pkthdr pcap_hdr; // 数据包头
|
||||||
|
memset(&pcap_hdr, 0, sizeof(pcap_hdr)); // 清空结构体
|
||||||
|
const u_char *packet = pcap_next(pcap_handle, &pcap_hdr); // 获取数据包
|
||||||
|
if (packet == NULL)
|
||||||
|
{
|
||||||
|
printf("pcap_next error\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分析 ethernet 报文类型
|
||||||
|
// 如果是 arp 报文,则打印 arp 报文信息
|
||||||
|
// 如果是 ip 报文,则打印 ip 报文信息
|
||||||
|
struct ether_header *eth_hdr = (struct ether_header *)packet;
|
||||||
|
// 拆分源 mac 地址和目的 mac 地址
|
||||||
|
unsigned char src_mac_x[ETHER_ADDR_LEN] = ""; // 源 mac 地址
|
||||||
|
unsigned char dst_mac_x[ETHER_ADDR_LEN] = ""; // 目的 mac 地址
|
||||||
|
memcpy(src_mac_x, eth_hdr->ether_shost, ETHER_ADDR_LEN); // 拷贝源 mac 地址
|
||||||
|
memcpy(dst_mac_x, eth_hdr->ether_dhost, ETHER_ADDR_LEN); // 拷贝目的 mac 地址
|
||||||
|
|
||||||
|
char src_mac[18] = ""; // 存储 MAC 地址的字符串
|
||||||
|
char dst_mac[18] = ""; // 存储 MAC 地址的字符串
|
||||||
|
|
||||||
|
// 将 MAC 地址转换成字符串
|
||||||
|
sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
src_mac_x[0], src_mac_x[1], src_mac_x[2], src_mac_x[3], src_mac_x[4], src_mac_x[5]);
|
||||||
|
|
||||||
|
sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
dst_mac_x[0], dst_mac_x[1], dst_mac_x[2], dst_mac_x[3], dst_mac_x[4], dst_mac_x[5]);
|
||||||
|
|
||||||
|
if (ntohs(eth_hdr->ether_type) == ETHERTYPE_ARP)
|
||||||
|
{
|
||||||
|
// 拆分源 ip 地址和目的 ip 地址
|
||||||
|
unsigned char src_ip[INET_ADDRSTRLEN] = ""; // 源 ip 地址
|
||||||
|
unsigned char dst_ip[INET_ADDRSTRLEN] = ""; // 目的 ip 地址
|
||||||
|
struct ether_arp *arp_hdr = (struct ether_arp *)(packet + sizeof(struct ether_header));
|
||||||
|
inet_ntop(AF_INET, arp_hdr->arp_spa, src_ip, INET_ADDRSTRLEN); // 拷贝源 ip 地址
|
||||||
|
inet_ntop(AF_INET, arp_hdr->arp_tpa, dst_ip, INET_ADDRSTRLEN); // 拷贝目的 ip 地址
|
||||||
|
|
||||||
|
printf("arp 报文\n");
|
||||||
|
printf("源地址: %s\t\t目的地址: %s\n源MAC: %s\t目的MAC: %s\n", src_ip, dst_ip, src_mac, dst_mac); // 打印 arp 报文信息
|
||||||
|
|
||||||
|
// 当 arp 映射表中没有 ip 时,则添加到 arp 映射表中,如果 mac 地址是 00:00:00:00:00:00 则不添加,FF:FF:FF:FF:FF:FF 也不添加
|
||||||
|
if (strcmp(src_mac, "00:00:00:00:00:00") != 0 && strcmp(src_mac, "FF:FF:FF:FF:FF:FF") != 0)
|
||||||
|
{
|
||||||
|
// 查询数据库 arp 表中是否已存在此 IP
|
||||||
|
int ret = search_arp_list_if_ip_have(src_ip);
|
||||||
|
|
||||||
|
if (ret > 0)
|
||||||
|
{
|
||||||
|
// printf("update_ip_mac\n");
|
||||||
|
// 将 IP 地址和 MAC 地址更新到 arp 表中
|
||||||
|
update_arp_list_by_ip(src_ip, src_mac);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// printf("insert_ip_mac\n");
|
||||||
|
// 将 IP 地址和 MAC 地址添加到 arp 表中
|
||||||
|
insert_arp_list(src_ip, src_mac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ntohs(eth_hdr->ether_type) == ETHERTYPE_IP)
|
||||||
|
{
|
||||||
|
// 拆分源 ip 地址和目的 ip 地址
|
||||||
|
unsigned char src_ip[INET_ADDRSTRLEN] = ""; // 源 ip 地址
|
||||||
|
unsigned char dst_ip[INET_ADDRSTRLEN] = ""; // 目的 ip 地址
|
||||||
|
struct ip *ip_hdr = (struct ip *)(packet + sizeof(struct ether_header));
|
||||||
|
inet_ntop(AF_INET, &ip_hdr->ip_src, src_ip, INET_ADDRSTRLEN); // 拷贝源 ip 地址
|
||||||
|
inet_ntop(AF_INET, &ip_hdr->ip_dst, dst_ip, INET_ADDRSTRLEN); // 拷贝目的 ip 地址
|
||||||
|
|
||||||
|
// 检查黑名单
|
||||||
|
ip_blacklist_filter(src_ip);
|
||||||
|
ip_blacklist_filter(dst_ip);
|
||||||
|
|
||||||
|
// 使用 libnet 组装转发
|
||||||
|
// 1. 判断目的 IP 是否在路由表中
|
||||||
|
// 2. 如果在路由表中,则查找下一跳 IP
|
||||||
|
// 3. 如果不在路由表中,则查找默认网关 IP
|
||||||
|
// 4. 如果默认网关 IP 也没有,则丢弃此数据包
|
||||||
|
// 5. 如果有下一跳 IP,则查找下一跳 IP 对应的 MAC 地址
|
||||||
|
// 6. 如果没有下一跳 IP,则查找默认网关 IP 对应的 MAC 地址
|
||||||
|
// 7. 如果没有默认网关 IP 对应的 MAC 地址,则丢弃此数据包
|
||||||
|
// 8. 如果有 MAC 地址,则使用 libnet 发送数据包
|
||||||
|
|
||||||
|
// 1. 判断目的 IP 是否在路由表中
|
||||||
|
char next_hop_ip[INET_ADDRSTRLEN] = ""; // 下一跳 IP 地址
|
||||||
|
char next_hop_mac[18] = ""; // 下一跳 MAC 地址
|
||||||
|
|
||||||
|
if (is_in_routing_table(dst_ip))
|
||||||
|
{
|
||||||
|
// 2. 如果在路由表中,则查找下一跳 IP
|
||||||
|
get_next_hop_ip(dst_ip, next_hop_ip);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 3. 如果不在路由表中,则查找默认网关 IP
|
||||||
|
get_default_gateway_ip(next_hop_ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(next_hop_ip) == 0)
|
||||||
|
{
|
||||||
|
// 4. 如果默认网关 IP 也没有,则丢弃此数据包
|
||||||
|
// printf("No route to host, discarding packet.\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 如果有下一跳 IP,则查找下一跳 IP 对应的 MAC 地址
|
||||||
|
if (is_in_arp_table(next_hop_ip))
|
||||||
|
{
|
||||||
|
get_mac_address(next_hop_ip, next_hop_mac);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 6. 如果没有下一跳 IP,则查找默认网关 IP 对应的 MAC 地址
|
||||||
|
get_mac_address(next_hop_ip, next_hop_mac);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(next_hop_mac) == 0)
|
||||||
|
{
|
||||||
|
// 7. 如果没有默认网关 IP 对应的 MAC 地址,则丢弃此数据包
|
||||||
|
// printf("No MAC address for next hop, discarding packet.\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8. 如果有 MAC 地址,则使用 libnet 发送数据包
|
||||||
|
libnet_t *l;
|
||||||
|
char errbuf[LIBNET_ERRBUF_SIZE];
|
||||||
|
|
||||||
|
l = libnet_init(LIBNET_LINK, NULL, errbuf);
|
||||||
|
if (l == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "libnet_init() failed: %s\n", errbuf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
libnet_ptag_t ptag;
|
||||||
|
ptag = libnet_build_ipv4(
|
||||||
|
LIBNET_IPV4_H, 0, 0, 0, 64, IPPROTO_TCP, 0, src_ip, dst_ip,
|
||||||
|
NULL, 0, l, 0);
|
||||||
|
|
||||||
|
if (ptag == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "libnet_build_ipv4() failed: %s\n", libnet_geterror(l));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t dst_mac_addr[6];
|
||||||
|
sscanf(next_hop_mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &dst_mac_addr[0], &dst_mac_addr[1], &dst_mac_addr[2], &dst_mac_addr[3], &dst_mac_addr[4], &dst_mac_addr[5]);
|
||||||
|
|
||||||
|
ptag = libnet_build_ethernet(
|
||||||
|
dst_mac_addr, src_mac_x, ETHERTYPE_IP,
|
||||||
|
NULL, 0, l, 0);
|
||||||
|
|
||||||
|
if (ptag == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "libnet_build_ethernet() failed: %s\n", libnet_geterror(l));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int c = libnet_write(l);
|
||||||
|
libnet_destroy(l);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("其他报文\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭网络设备
|
||||||
|
pcap_close(pcap_handle);
|
||||||
|
|
||||||
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 打开网卡设备
|
// 发送 ARP 广播
|
||||||
// 如果成功打开网卡设备,就返回 libnet 上下文
|
void send_arp_scan_broadcast()
|
||||||
libnet_t *open_device(pcap_t **device, char *dev_name)
|
|
||||||
{
|
{
|
||||||
// 打开网卡设备: 设备名、最大字节数、混杂模式、超时时间、错误信息缓冲区
|
libnet_t *my_libnet;
|
||||||
*device = pcap_open_live(dev_name, MAX_BYTE, 1, 512, errbuf);
|
char errbuf[LIBNET_ERRBUF_SIZE];
|
||||||
if (*device == NULL)
|
|
||||||
|
// 初始化libnet句柄
|
||||||
|
my_libnet = libnet_init(LIBNET_LINK, NULL, errbuf);
|
||||||
|
if (my_libnet == NULL)
|
||||||
{
|
{
|
||||||
perror("pcap_open_live");
|
fprintf(stderr, "libnet_init() failed: %s\n", errbuf);
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理数据包
|
// 配置源MAC地址、源IP地址和目的IP地址
|
||||||
libnet_t *libnet = libnet_init(LIBNET_LINK, dev_name, errbuf); // 初始化 libnet
|
uint8_t src_mac[6] = {0x00, 0x0c, 0x29, 0x85, 0xcc, 0x53}; // 源MAC地址
|
||||||
if (libnet == NULL)
|
uint8_t src_ip[4] = {192, 168, 32, 133}; // 源IP地址
|
||||||
|
uint8_t dst_ip[4] = {192, 168, 32, 255}; // 目的IP地址(广播地址)
|
||||||
|
|
||||||
|
// 目的MAC地址(广播地址)
|
||||||
|
uint8_t dst_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||||
|
|
||||||
|
// ptag = protocol tag 协议标记
|
||||||
|
libnet_ptag_t arp_tag, ether_tag;
|
||||||
|
|
||||||
|
// 构建ARP数据包
|
||||||
|
arp_tag = libnet_build_arp(ARPHRD_ETHER, ETHERTYPE_IP, 6, 4, ARPOP_REQUEST,
|
||||||
|
src_mac, src_ip, dst_mac, dst_ip,
|
||||||
|
NULL, 0, my_libnet, 0);
|
||||||
|
if (arp_tag == -1)
|
||||||
{
|
{
|
||||||
perror("libnet_init");
|
fprintf(stderr, "libnet_build_arp() failed: %s\n", libnet_geterror(my_libnet));
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return libnet; // 返回 libnet 上下文
|
// 构建以太网数据包
|
||||||
}
|
uint8_t ether_dst_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // 以太网目的MAC地址(广播地址)
|
||||||
|
uint8_t ether_src_mac[6] = {src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5]}; // 以太网源MAC地址
|
||||||
|
uint16_t ether_type = ETHERTYPE_ARP; // 以太网类型(ARP)
|
||||||
|
|
||||||
// 处理数据包
|
ether_tag = libnet_build_ethernet(ether_dst_mac, ether_src_mac, ether_type,
|
||||||
// 参数: 传递给回调函数的参数、数据包头部、数据包
|
NULL, 0, my_libnet, 0);
|
||||||
void process_packet(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet)
|
if (ether_tag == -1)
|
||||||
{
|
|
||||||
// 将数据包从一个网卡发送到另一个网卡
|
|
||||||
// 实际路由中,需要根据路由表进行路由选择
|
|
||||||
|
|
||||||
printf("process_packet\n");
|
|
||||||
/*
|
|
||||||
libnet_ptag_t t; // libnet 标签: 用于标识数据包中的某一部分
|
|
||||||
libnet_t *libnet; // libnet 上下文: 用于发送数据包
|
|
||||||
|
|
||||||
// 根据网卡设备选择 libnet 上下文,以便发送数据包
|
|
||||||
// 规则是: 如果是从网卡1接收到的数据包,就从网卡2发送出去
|
|
||||||
if (arg == (u_char *)device1)
|
|
||||||
{
|
{
|
||||||
libnet = libnet_context2;
|
fprintf(stderr, "libnet_build_ethernet() failed: %s\n", libnet_geterror(my_libnet));
|
||||||
}
|
exit(EXIT_FAILURE);
|
||||||
else if (arg == (u_char *)device2)
|
|
||||||
{
|
|
||||||
libnet = libnet_context1;
|
|
||||||
}
|
|
||||||
|
|
||||||
t = libnet_build_ethernet(
|
|
||||||
((struct libnet_ethernet_hdr *)packet)->ether_dhost, // 目的MAC地址
|
|
||||||
((struct libnet_ethernet_hdr *)packet)->ether_shost, // 源MAC地址
|
|
||||||
((struct libnet_ethernet_hdr *)packet)->ether_type, // 以太网类型
|
|
||||||
packet + LIBNET_ETH_H, // 负载数据(携带的数据)
|
|
||||||
pkthdr->len - LIBNET_ETH_H, // 以太网数据包的数据部分
|
|
||||||
libnet, // libnet 上下文
|
|
||||||
0 // 标记
|
|
||||||
);
|
|
||||||
|
|
||||||
if (t == -1)
|
|
||||||
{
|
|
||||||
perror("libnet_build_ethernet");
|
|
||||||
exit(-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送数据包
|
// 发送数据包
|
||||||
int res = libnet_write(libnet);
|
int bytes_sent = libnet_write(my_libnet);
|
||||||
if (res == -1)
|
if (bytes_sent == -1)
|
||||||
{
|
{
|
||||||
perror("libnet_write");
|
fprintf(stderr, "libnet_write() failed: %s\n", libnet_geterror(my_libnet));
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
} */
|
}
|
||||||
|
else
|
||||||
struct libnet_ethernet_hdr *eth_hdr = (struct libnet_ethernet_hdr *)packet;
|
|
||||||
|
|
||||||
// 如果是IP数据包,就打印源IP地址和目的IP地址
|
|
||||||
if (ntohs(eth_hdr->ether_type) == ETHERTYPE_IP)
|
|
||||||
{
|
{
|
||||||
struct libnet_ipv4_hdr *ip_hdr = (struct libnet_ipv4_hdr *)(packet + LIBNET_ETH_H);
|
printf("ARP scan broadcast sent: %d bytes\n", bytes_sent);
|
||||||
if (ip_hdr->ip_p == IPPROTO_TCP)
|
|
||||||
{
|
|
||||||
struct libnet_tcp_hdr *tcp_hdr = (struct libnet_tcp_hdr *)(packet + LIBNET_ETH_H + LIBNET_IPV4_H);
|
|
||||||
printf("TCP: %s:%d -> %s:%d\n", inet_ntoa(ip_hdr->ip_src), ntohs(tcp_hdr->th_sport), inet_ntoa(ip_hdr->ip_dst), ntohs(tcp_hdr->th_dport));
|
|
||||||
}
|
|
||||||
else if (ip_hdr->ip_p == IPPROTO_UDP)
|
|
||||||
{
|
|
||||||
struct libnet_udp_hdr *udp_hdr = (struct libnet_udp_hdr *)(packet + LIBNET_ETH_H + LIBNET_IPV4_H);
|
|
||||||
printf("UDP: %s:%d -> %s:%d\n", inet_ntoa(ip_hdr->ip_src), ntohs(udp_hdr->uh_sport), inet_ntoa(ip_hdr->ip_dst), ntohs(udp_hdr->uh_dport));
|
|
||||||
}
|
|
||||||
|
|
||||||
libnet_t *libnet;
|
|
||||||
if (arg == (u_char *)device1)
|
|
||||||
{
|
|
||||||
libnet = libnet_context2;
|
|
||||||
}
|
|
||||||
else if (arg == (u_char *)device2)
|
|
||||||
{
|
|
||||||
libnet = libnet_context1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("testssssxxxxs\n");
|
|
||||||
|
|
||||||
libnet_ptag_t t = libnet_build_ethernet(
|
|
||||||
eth_hdr->ether_dhost,
|
|
||||||
eth_hdr->ether_shost,
|
|
||||||
ETHERTYPE_IP,
|
|
||||||
packet + LIBNET_ETH_H,
|
|
||||||
pkthdr->len - LIBNET_ETH_H,
|
|
||||||
libnet,
|
|
||||||
0);
|
|
||||||
|
|
||||||
// 组包测试(如果能打印到这行,则说明组包成功)
|
|
||||||
printf("testssss\n");
|
|
||||||
|
|
||||||
if (t == -1)
|
|
||||||
{
|
|
||||||
perror("libnet_build_ethernet");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int res = libnet_write(libnet);
|
|
||||||
if (res == -1)
|
|
||||||
{
|
|
||||||
perror("libnet_write");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果是ARP数据包,就打印源IP地址和目的IP地址
|
// 销毁libnet句柄
|
||||||
if (ntohs(eth_hdr->ether_type) == ETHERTYPE_ARP)
|
libnet_destroy(my_libnet);
|
||||||
{
|
|
||||||
struct libnet_arp_hdr *arp_hdr = (struct libnet_arp_hdr *)(packet + LIBNET_ETH_H);
|
|
||||||
// printf("ARP: %s -> %s\n", inet_ntoa(*(struct in_addr *)arp_hdr->arp_spa), inet_ntoa(*(struct in_addr *)arp_hdr->arp_tpa));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ARP 数据报处理函数
|
void ip_blacklist_filter(const char *ip)
|
||||||
void process_arp_packet(const u_char *packet)
|
|
||||||
{
|
{
|
||||||
struct ether_header *eth_hdr = (struct ether_header *)packet;
|
// printf("ip_blacklist_filter\n");
|
||||||
struct ether_arp *arp_hdr = (struct ether_arp *)(packet + LIBNET_ETH_H); // packet + 14
|
// printf("ip: %s\n", ip);
|
||||||
|
|
||||||
if (ntohs(eth_hdr->ether_type) == ETHERTYPE_ARP)
|
// 查询数据库黑名单IP表中是否已存在此IP
|
||||||
|
int ret = search_ip_fw(ip);
|
||||||
|
|
||||||
|
if (ret > 0)
|
||||||
{
|
{
|
||||||
char ip_address[INET_ADDRSTRLEN];
|
char iptables_check[256] = "";
|
||||||
char mac_address[ETH_ALEN * 3]; // ETH_ALEN * 3 是为了申请足够的空间存储 MAC 地址
|
sprintf(iptables_check, "iptables -C INPUT -s %s -j DROP", ip);
|
||||||
|
|
||||||
/*
|
// 检查规则是否存在
|
||||||
inet_ntop 用于将二进制的 IP 地址转换为可读的字符串形式
|
// printf("iptables_command: %s\n", iptables_command);
|
||||||
|
if (system(iptables_check) != 0)
|
||||||
参数说明:
|
|
||||||
AF_INET:指定要转换的地址族,这里是 IPv4 地址。
|
|
||||||
arp_hdr->arp_spa:源 IP 地址的指针,它是一个二进制的网络字节序的 IPv4 地址。
|
|
||||||
ip_address:用于存储转换后的 IP 地址字符串的缓冲区。
|
|
||||||
sizeof(ip_address):指定缓冲区的大小,以确保不会发生缓冲区溢出。
|
|
||||||
*/
|
|
||||||
inet_ntop(AF_INET, arp_hdr->arp_spa, ip_address, sizeof(ip_address));
|
|
||||||
snprintf(mac_address, sizeof(mac_address),
|
|
||||||
"%02x:%02x:%02x:%02x:%02x:%02x",
|
|
||||||
arp_hdr->arp_sha[0],
|
|
||||||
arp_hdr->arp_sha[1],
|
|
||||||
arp_hdr->arp_sha[2],
|
|
||||||
arp_hdr->arp_sha[3],
|
|
||||||
arp_hdr->arp_sha[4],
|
|
||||||
arp_hdr->arp_sha[5]);
|
|
||||||
|
|
||||||
// printf("ARP: %s -> %s\n", ip_address, mac_address);
|
|
||||||
|
|
||||||
MYSQL_BIND parmas[2];
|
|
||||||
parmas[0].buffer_type = MYSQL_TYPE_STRING;
|
|
||||||
parmas[0].buffer = ip_address;
|
|
||||||
parmas[0].buffer_length = strlen(ip_address);
|
|
||||||
parmas[0].is_null = 0;
|
|
||||||
parmas[0].length = &parmas[0].buffer_length;
|
|
||||||
parmas[1].buffer_type = MYSQL_TYPE_STRING;
|
|
||||||
parmas[1].buffer = mac_address;
|
|
||||||
parmas[1].buffer_length = strlen(mac_address);
|
|
||||||
parmas[1].is_null = 0;
|
|
||||||
parmas[1].length = &parmas[1].buffer_length;
|
|
||||||
// snprintf(arp_result_sql, sizeof(arp_result_sql), "insert into arp_result(ip, mac) values('%s', '%s')", ip_address, mac_address);
|
|
||||||
char arp_result_sql[1024] = "insert into arp_result(ip, mac) values(?, ?)";
|
|
||||||
int result = insert(arp_result_sql, parmas);
|
|
||||||
|
|
||||||
if (result > 0)
|
|
||||||
{
|
{
|
||||||
printf("ARP: %s -> %s\n", ip_address, mac_address);
|
// 规则不存在,添加规则
|
||||||
|
char iptables_add[256] = "";
|
||||||
|
sprintf(iptables_add, "iptables -I INPUT -s %s -j DROP", ip);
|
||||||
|
// printf("iptables_add: %s\n", iptables_add);
|
||||||
|
system(iptables_add);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,20 +2,23 @@
|
||||||
#define __NET_TASK_THREAD_H__
|
#define __NET_TASK_THREAD_H__
|
||||||
|
|
||||||
#include "router.h"
|
#include "router.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <pcap/pcap.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <string.h> // memset
|
||||||
|
#include <net/ethernet.h> // ether_header
|
||||||
|
#include <netinet/ip.h> // ip
|
||||||
|
#include <netinet/if_ether.h> // ether_arp
|
||||||
|
#include <unistd.h> // sleep
|
||||||
|
#include <libnet.h>
|
||||||
|
|
||||||
#define MAX_BYTE 65535 // 最大字节数
|
#define MAX_BYTE 65535 // 最大字节数
|
||||||
|
|
||||||
char errbuf[PCAP_ERRBUF_SIZE]; // 错误信息缓冲区
|
char errbuf[PCAP_ERRBUF_SIZE]; // 错误信息缓冲区
|
||||||
pcap_t *device1; // 网卡设备1
|
|
||||||
pcap_t *device2; // 网卡设备2
|
|
||||||
|
|
||||||
libnet_t *libnet_context1; // libnet1 上下文
|
void *net_task(void *arg); // 网络任务线程,用于抓包和数据包转发
|
||||||
libnet_t *libnet_context2; // libnet2 上下文
|
void send_arp_scan_broadcast(); // 发送 arp 广播
|
||||||
|
void ip_blacklist_filter(const char *ip); // 黑名单 ip 使用 iptables 过滤
|
||||||
// libpcap 相关函数
|
|
||||||
libnet_t *open_device(pcap_t **device, char *dev_name); // 打开网卡设备
|
|
||||||
void process_packet(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet); // 处理数据包
|
|
||||||
|
|
||||||
void *net_task(void *arg);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -10,31 +10,14 @@ int main(int argc, char const *argv[])
|
||||||
// 打开菜单
|
// 打开菜单
|
||||||
menu_choice();
|
menu_choice();
|
||||||
|
|
||||||
// pthread_t thread_net_task;
|
|
||||||
// pthread_create(&thread_net_task, NULL, net_task, NULL);
|
|
||||||
// pthread_join(thread_net_task, NULL);
|
|
||||||
|
|
||||||
// close(sockfd); // 关闭原始套接字
|
|
||||||
close_mysql(); // 关闭数据库连接
|
close_mysql(); // 关闭数据库连接
|
||||||
|
|
||||||
// // 关闭网络设备
|
|
||||||
// pcap_close(device1);
|
|
||||||
// pcap_close(device2);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_init()
|
void net_init()
|
||||||
{
|
{
|
||||||
// 创建原始套接字
|
|
||||||
// sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); // 参数列表:协议族、套接字类型、协议类型
|
|
||||||
// if (sockfd < 0)
|
|
||||||
// {
|
|
||||||
// perror("socket");
|
|
||||||
// exit(-1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 数据连接测试
|
|
||||||
if (connect_mysql("localhost", 3306, "flykhan", "1202", "router") == 0)
|
if (connect_mysql("localhost", 3306, "flykhan", "1202", "router") == 0)
|
||||||
printf("数据库连接成功\n");
|
printf("数据库连接成功\n");
|
||||||
else
|
else
|
||||||
|
@ -97,7 +80,6 @@ int is_ip_valid(const char *ip)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
// 编译正则表达式
|
// 编译正则表达式
|
||||||
// /^((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])(?::(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?$/
|
|
||||||
ret = regcomp(®ex, "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$", REG_EXTENDED); // REG_EXTENDED 扩展正则表达式
|
ret = regcomp(®ex, "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$", REG_EXTENDED); // REG_EXTENDED 扩展正则表达式
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
{
|
{
|
||||||
|
@ -126,9 +108,7 @@ int is_ip_valid(const char *ip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送ARP请求方法
|
// 终端控制菜单
|
||||||
|
|
||||||
// 后台菜单
|
|
||||||
void menu_choice()
|
void menu_choice()
|
||||||
{
|
{
|
||||||
// 选择标志位
|
// 选择标志位
|
||||||
|
@ -223,8 +203,10 @@ void menu_choice()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 发送 ARP 广播
|
||||||
else if (5 == choice)
|
else if (5 == choice)
|
||||||
{
|
{
|
||||||
|
send_arp_scan_broadcast();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示 ARP 表
|
// 显示 ARP 表
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
#include "router_firewall.h"
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
#ifndef __ROUTER_FIREWALL_H__
|
|
||||||
#define __ROUTER_FIREWALL_H__
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue