From fe2a027eaa43c66f287829149fea1f0978a433e5 Mon Sep 17 00:00:00 2001 From: flykhan Date: Sat, 23 Sep 2023 16:25:12 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B7=AF=E7=94=B1=E9=83=A8=E5=88=86=E9=87=8D?= =?UTF-8?q?=E5=86=99=EF=BC=8CARP=20=E8=AF=B7=E6=B1=82=E5=B9=BF=E6=92=AD?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E5=AE=8C=E6=88=90=EF=BC=8CARP=20=E6=94=B6?= =?UTF-8?q?=E5=8C=85=E5=B9=B6=E5=AD=98ip-mac=E5=85=A5=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93=E5=AE=8C=E6=88=90=EF=BC=8C=E9=98=B2=E7=81=AB=E5=A2=99?= =?UTF-8?q?=E8=BF=87=E6=BB=A4=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- router/db.c | 97 ++++++++- router/db.h | 30 +++ router/net_task_thread.c | 440 ++++++++++++++++++++++++--------------- router/net_task_thread.h | 23 +- router/router.c | 24 +-- router/router_firewall.c | 2 - router/router_firewall.h | 4 - 7 files changed, 410 insertions(+), 210 deletions(-) delete mode 100644 router/router_firewall.c delete mode 100644 router/router_firewall.h diff --git a/router/db.c b/router/db.c index 3b89bd6..c93ee93 100644 --- a/router/db.c +++ b/router/db.c @@ -1,6 +1,10 @@ #include "db.h" #include +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) { 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() { char sql[100]; @@ -228,4 +250,77 @@ void delete_ip_fw(const char *ip) { printf("删除黑名单失败\n"); } -} \ No newline at end of file +} + +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; + } + } +} diff --git a/router/db.h b/router/db.h index 8c82571..c10d7cc 100644 --- a/router/db.h +++ b/router/db.h @@ -42,6 +42,12 @@ extern void printResult(MYSQL_ROW row, char (*columns)[30], int cols); // 添加ARP表 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表 extern void print_arp_list(); @@ -57,4 +63,28 @@ extern void print_ip_fw(); // 删除黑名单中的一条记录 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 \ No newline at end of file diff --git a/router/net_task_thread.c b/router/net_task_thread.c index 8da980b..13eb97f 100644 --- a/router/net_task_thread.c +++ b/router/net_task_thread.c @@ -1,209 +1,305 @@ #include "net_task_thread.h" #include "db.h" +extern volatile int stop_thread; // 声明 + void *net_task(void *arg) { + printf("net_task\n"); - char *dev1 = "ens38"; // 第一个网卡 - char *dev2 = "ens33"; // 第二个网卡 + char *dev = pcap_lookupdev(errbuf); // 获取网络接口 + if (dev == NULL) // 获取网络接口失败 + { + printf("pcap_lookupdev error: %s\n", errbuf); + return NULL; + } + printf("网络接口: %s\n", dev); - // 打开网卡设备 - // libnet_context1 使用 open_device 函数打开网卡设备1 后返回的 libnet 上下文 - libnet_context1 = open_device(&device1, dev1); - libnet_context2 = open_device(&device2, dev2); + // 获取网卡的网络号,掩码地址 + bpf_u_int32 netip, netmask; + if (pcap_lookupnet(dev, &netip, &netmask, NULL) == 0) + { + unsigned char ip[INET_ADDRSTRLEN] = ""; + unsigned char mask[INET_ADDRSTRLEN] = ""; - // 开始捕获数据包: - // pcap_loop: 网卡设备、捕获的数据包个数、回调函数、传递给回调函数的参数 - pcap_loop(device1, -1, process_packet, NULL); // -1 表示无限循环 - pcap_loop(device2, -1, process_packet, NULL); // -1 表示无限循环 + inet_ntop(AF_INET, &netip, ip, INET_ADDRSTRLEN); + inet_ntop(AF_INET, &netmask, mask, INET_ADDRSTRLEN); + printf("网络地址: %s 掩码地址: %s\n", ip, mask); + } - 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); } -// 打开网卡设备 -// 如果成功打开网卡设备,就返回 libnet 上下文 -libnet_t *open_device(pcap_t **device, char *dev_name) +// 发送 ARP 广播 +void send_arp_scan_broadcast() { - // 打开网卡设备: 设备名、最大字节数、混杂模式、超时时间、错误信息缓冲区 - *device = pcap_open_live(dev_name, MAX_BYTE, 1, 512, errbuf); - if (*device == NULL) + libnet_t *my_libnet; + char errbuf[LIBNET_ERRBUF_SIZE]; + + // 初始化libnet句柄 + my_libnet = libnet_init(LIBNET_LINK, NULL, errbuf); + if (my_libnet == NULL) { - perror("pcap_open_live"); - exit(-1); + fprintf(stderr, "libnet_init() failed: %s\n", errbuf); + exit(EXIT_FAILURE); } - // 处理数据包 - libnet_t *libnet = libnet_init(LIBNET_LINK, dev_name, errbuf); // 初始化 libnet - if (libnet == NULL) + // 配置源MAC地址、源IP地址和目的IP地址 + uint8_t src_mac[6] = {0x00, 0x0c, 0x29, 0x85, 0xcc, 0x53}; // 源MAC地址 + 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"); - exit(-1); + fprintf(stderr, "libnet_build_arp() failed: %s\n", libnet_geterror(my_libnet)); + 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) -// 处理数据包 -// 参数: 传递给回调函数的参数、数据包头部、数据包 -void process_packet(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet) -{ - // 将数据包从一个网卡发送到另一个网卡 - // 实际路由中,需要根据路由表进行路由选择 - - printf("process_packet\n"); - /* - libnet_ptag_t t; // libnet 标签: 用于标识数据包中的某一部分 - libnet_t *libnet; // libnet 上下文: 用于发送数据包 - - // 根据网卡设备选择 libnet 上下文,以便发送数据包 - // 规则是: 如果是从网卡1接收到的数据包,就从网卡2发送出去 - if (arg == (u_char *)device1) + ether_tag = libnet_build_ethernet(ether_dst_mac, ether_src_mac, ether_type, + NULL, 0, my_libnet, 0); + if (ether_tag == -1) { - libnet = libnet_context2; - } - 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); + fprintf(stderr, "libnet_build_ethernet() failed: %s\n", libnet_geterror(my_libnet)); + exit(EXIT_FAILURE); } // 发送数据包 - int res = libnet_write(libnet); - if (res == -1) + int bytes_sent = libnet_write(my_libnet); + if (bytes_sent == -1) { - perror("libnet_write"); - exit(-1); - } */ - - struct libnet_ethernet_hdr *eth_hdr = (struct libnet_ethernet_hdr *)packet; - - // 如果是IP数据包,就打印源IP地址和目的IP地址 - if (ntohs(eth_hdr->ether_type) == ETHERTYPE_IP) + fprintf(stderr, "libnet_write() failed: %s\n", libnet_geterror(my_libnet)); + exit(EXIT_FAILURE); + } + else { - struct libnet_ipv4_hdr *ip_hdr = (struct libnet_ipv4_hdr *)(packet + LIBNET_ETH_H); - 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); - } + printf("ARP scan broadcast sent: %d bytes\n", bytes_sent); } - // 如果是ARP数据包,就打印源IP地址和目的IP地址 - if (ntohs(eth_hdr->ether_type) == ETHERTYPE_ARP) - { - 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)); - } + // 销毁libnet句柄 + libnet_destroy(my_libnet); } -// ARP 数据报处理函数 -void process_arp_packet(const u_char *packet) +void ip_blacklist_filter(const char *ip) { - struct ether_header *eth_hdr = (struct ether_header *)packet; - struct ether_arp *arp_hdr = (struct ether_arp *)(packet + LIBNET_ETH_H); // packet + 14 + // printf("ip_blacklist_filter\n"); + // 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 mac_address[ETH_ALEN * 3]; // ETH_ALEN * 3 是为了申请足够的空间存储 MAC 地址 + char iptables_check[256] = ""; + sprintf(iptables_check, "iptables -C INPUT -s %s -j DROP", ip); - /* - inet_ntop 用于将二进制的 IP 地址转换为可读的字符串形式 - - 参数说明: - 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("iptables_command: %s\n", iptables_command); + if (system(iptables_check) != 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); } } -} +} \ No newline at end of file diff --git a/router/net_task_thread.h b/router/net_task_thread.h index c50c2c4..f9be08b 100644 --- a/router/net_task_thread.h +++ b/router/net_task_thread.h @@ -2,20 +2,23 @@ #define __NET_TASK_THREAD_H__ #include "router.h" +#include +#include +#include +#include +#include // memset +#include // ether_header +#include // ip +#include // ether_arp +#include // sleep +#include #define MAX_BYTE 65535 // 最大字节数 char errbuf[PCAP_ERRBUF_SIZE]; // 错误信息缓冲区 -pcap_t *device1; // 网卡设备1 -pcap_t *device2; // 网卡设备2 -libnet_t *libnet_context1; // libnet1 上下文 -libnet_t *libnet_context2; // libnet2 上下文 - -// 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); +void *net_task(void *arg); // 网络任务线程,用于抓包和数据包转发 +void send_arp_scan_broadcast(); // 发送 arp 广播 +void ip_blacklist_filter(const char *ip); // 黑名单 ip 使用 iptables 过滤 #endif \ No newline at end of file diff --git a/router/router.c b/router/router.c index 1993cfa..6c2f474 100644 --- a/router/router.c +++ b/router/router.c @@ -10,31 +10,14 @@ int main(int argc, char const *argv[]) // 打开菜单 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(); // 关闭数据库连接 - // // 关闭网络设备 - // pcap_close(device1); - // pcap_close(device2); - return 0; } 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) printf("数据库连接成功\n"); else @@ -97,7 +80,6 @@ int is_ip_valid(const char *ip) 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 扩展正则表达式 if (ret != 0) { @@ -126,9 +108,7 @@ int is_ip_valid(const char *ip) } } -// 发送ARP请求方法 - -// 后台菜单 +// 终端控制菜单 void menu_choice() { // 选择标志位 @@ -223,8 +203,10 @@ void menu_choice() } } + // 发送 ARP 广播 else if (5 == choice) { + send_arp_scan_broadcast(); } // 显示 ARP 表 diff --git a/router/router_firewall.c b/router/router_firewall.c deleted file mode 100644 index 136ea34..0000000 --- a/router/router_firewall.c +++ /dev/null @@ -1,2 +0,0 @@ -#include "router_firewall.h" - diff --git a/router/router_firewall.h b/router/router_firewall.h deleted file mode 100644 index c6ee3f0..0000000 --- a/router/router_firewall.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef __ROUTER_FIREWALL_H__ -#define __ROUTER_FIREWALL_H__ - -#endif \ No newline at end of file