305 lines
11 KiB
C
305 lines
11 KiB
C
#include "net_task_thread.h"
|
||
#include "db.h"
|
||
|
||
extern volatile int stop_thread; // 声明
|
||
|
||
void *net_task(void *arg)
|
||
{
|
||
|
||
printf("net_task\n");
|
||
|
||
char *dev = pcap_lookupdev(errbuf); // 获取网络接口
|
||
if (dev == NULL) // 获取网络接口失败
|
||
{
|
||
printf("pcap_lookupdev error: %s\n", errbuf);
|
||
return NULL;
|
||
}
|
||
printf("网络接口: %s\n", dev);
|
||
|
||
// 获取网卡的网络号,掩码地址
|
||
bpf_u_int32 netip, netmask;
|
||
if (pcap_lookupnet(dev, &netip, &netmask, NULL) == 0)
|
||
{
|
||
unsigned char ip[INET_ADDRSTRLEN] = "";
|
||
unsigned char mask[INET_ADDRSTRLEN] = "";
|
||
|
||
inet_ntop(AF_INET, &netip, ip, INET_ADDRSTRLEN);
|
||
inet_ntop(AF_INET, &netmask, mask, INET_ADDRSTRLEN);
|
||
printf("网络地址: %s 掩码地址: %s\n", ip, mask);
|
||
}
|
||
|
||
// 打开网络设备,开始捕获数据
|
||
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 广播
|
||
void send_arp_scan_broadcast()
|
||
{
|
||
libnet_t *my_libnet;
|
||
char errbuf[LIBNET_ERRBUF_SIZE];
|
||
|
||
// 初始化libnet句柄
|
||
my_libnet = libnet_init(LIBNET_LINK, NULL, errbuf);
|
||
if (my_libnet == NULL)
|
||
{
|
||
fprintf(stderr, "libnet_init() failed: %s\n", errbuf);
|
||
exit(EXIT_FAILURE);
|
||
}
|
||
|
||
// 配置源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)
|
||
{
|
||
fprintf(stderr, "libnet_build_arp() failed: %s\n", libnet_geterror(my_libnet));
|
||
exit(EXIT_FAILURE);
|
||
}
|
||
|
||
// 构建以太网数据包
|
||
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);
|
||
if (ether_tag == -1)
|
||
{
|
||
fprintf(stderr, "libnet_build_ethernet() failed: %s\n", libnet_geterror(my_libnet));
|
||
exit(EXIT_FAILURE);
|
||
}
|
||
|
||
// 发送数据包
|
||
int bytes_sent = libnet_write(my_libnet);
|
||
if (bytes_sent == -1)
|
||
{
|
||
fprintf(stderr, "libnet_write() failed: %s\n", libnet_geterror(my_libnet));
|
||
exit(EXIT_FAILURE);
|
||
}
|
||
else
|
||
{
|
||
printf("ARP scan broadcast sent: %d bytes\n", bytes_sent);
|
||
}
|
||
|
||
// 销毁libnet句柄
|
||
libnet_destroy(my_libnet);
|
||
}
|
||
|
||
void ip_blacklist_filter(const char *ip)
|
||
{
|
||
// printf("ip_blacklist_filter\n");
|
||
// printf("ip: %s\n", ip);
|
||
|
||
// 查询数据库黑名单IP表中是否已存在此IP
|
||
int ret = search_ip_fw(ip);
|
||
|
||
if (ret > 0)
|
||
{
|
||
char iptables_check[256] = "";
|
||
sprintf(iptables_check, "iptables -C INPUT -s %s -j DROP", ip);
|
||
|
||
// 检查规则是否存在
|
||
// printf("iptables_command: %s\n", iptables_command);
|
||
if (system(iptables_check) != 0)
|
||
{
|
||
// 规则不存在,添加规则
|
||
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);
|
||
}
|
||
}
|
||
} |