tplink arp绑定的 类型 强制和普通的区别

本文介绍了局域网中路由器的两种绑定方式:普通绑定与强制绑定。普通绑定建立了IP与MAC地址的对应关系,能自动学习更新,有效防止ARP攻击;而强制绑定则不具备自动学习能力,必须手动添加IP与MAC对应关系才能通讯。
普通绑定是在路由器上记录了局域网内计算机MAC地址对应的IP地址,建立了一个对应关系,不会受到ARP欺骗,导致无法正常通讯。对于没有进行IP与MAC地址绑定的计算机就可能受到ARP攻击。普通绑定只是设置了一个IP与MAC的对应关系,若计算机更改了其IP地址,路由器仍然能进行ARP映射表自动学习,扫描到计算机新的对应关系,该计算机仍能与路由器进行通讯。
强制绑定是通过添加IP与MAC对应的关系来进行数据的通讯的,没有自动学习ARP映射表的能力,若没有添加计算机IP与MAC的对应关系,该计算机是无法与路由器进行通讯的。所以在设置了强制绑定后,新接入路由器的计算机,若没有添加IP与MAC地址对应关系,该计算机是不能通讯的。或者路由器下的计算机更改了其IP地址,导致与路由器上记录的IP与MAC对应关系不一致,也无法进行通讯。

http://service.tp-link.com.cn/detail_article_95.html

arp_scanner.c:/* Copyright (c) 2009-2025 TP-LINK Technologies CO.,LTD. * * file None * brief None * details None * * author Wei Gan <ganwei@tp-link.com.hk> * version 1.0.0 * date 31Jul25 * * history \arg version, date, author, modification */ /**************************************************************************************************/ /* INCLUDE */ /**************************************************************************************************/ #include <sys/socket.h> #include <linux/if_packet.h> #include <net/ethernet.h> #include <sys/ioctl.h> #include <netinet/in.h> #include <arpa/inet.h> #include <net/if.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "arp_scanner.h" /**************************************************************************************************/ /* DEFINES */ /**************************************************************************************************/ /**************************************************************************************************/ /* TYPES */ /**************************************************************************************************/ /**************************************************************************************************/ /* VARIABLES */ /**************************************************************************************************/ /**************************************************************************************************/ /* FUNCTIONS */ /**************************************************************************************************/ /* 创建原始socket */ int create_arp_socket() { int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (sock < 0) { perror("socket"); return -1; } return sock; } /* * fn static int send_arp_request(int sockfd, const char *src_ip, const char *dest_ip, const char *ifname) * brief 发送ARP请求 * details None * * param[in] sockfd 套接字 * param[in] src_ip 源ip * param[in] ifname 网卡名 * param[out]None * return None * * retval None * note None */ static int send_arp_request(int sockfd, const char *src_ip, const char *dest_ip, const char *ifname) { // 获取接口索引 struct ifreq ifr; strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if (ioctl(sockfd, SIOCGIFINDEX, &ifr) < 0) { perror("ioctl(SIOCGIFINDEX)"); return -1; } // 获取接口MAC地址 if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) { perror("ioctl(SIOCGIFHWADDR)"); return -1; } uint8_t src_mac[6]; memcpy(src_mac, ifr.ifr_hwaddr.sa_data, 6); // 构建以太网帧ARP包 unsigned char packet[60] = {0}; struct ether_header *eth = (struct ether_header *)packet; struct ether_arp *arp = (struct ether_arp *)(packet + sizeof(struct ether_header)); /************** 填充以太网帧头 **************/ // 目标MAC: 广播地址 (FF:FF:FF:FF:FF:FF) memset(eth->ether_dhost, 0xFF, 6); // 源MAC: 接口MAC地址 memcpy(eth->ether_shost, src_mac, 6); // 以太网类型: ARP (0x0806) eth->ether_type = htons(ETHERTYPE_ARP); /************** 填充ARP包 **************/ // 硬件类型: 以太网 (1) arp->arp_hrd = htons(ARPHRD_ETHER); // 协议类型: IPv4 (0x0800) arp->arp_pro = htons(ETHERTYPE_IP); // 硬件地址长度: 6字节 (MAC) arp->arp_hln = 6; // 协议地址长度: 4字节 (IPv4) arp->arp_pln = 4; // 操作码: ARP请求 (1) arp->arp_op = htons(ARPOP_REQUEST); // 源MAC: 接口MAC地址 memcpy(arp->arp_sha, src_mac, 6); // 源IP: 将字符串转换为网络字节序 struct in_addr src_addr; if (inet_pton(AF_INET, src_ip, &src_addr) <= 0) { perror("inet_pton(src_ip)"); return -1; } memcpy(arp->arp_spa, &src_addr.s_addr, 4); // 目标MAC: ARP请求中设为全0 (未知) memset(arp->arp_tha, 0, 6); // 目标IP: 将字符串转换为网络字节序 struct in_addr dest_addr; if (inet_pton(AF_INET, dest_ip, &dest_addr) <= 0) { perror("inet_pton(dest_ip)"); return -1; } memcpy(arp->arp_tpa, &dest_addr.s_addr, 4); /************** 发送数据包 **************/ struct sockaddr_ll sa = { .sll_family = AF_PACKET, .sll_ifindex = ifr.ifr_ifindex, .sll_halen = ETH_ALEN, .sll_addr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} // 广播 }; if (sendto(sockfd, packet, sizeof(packet), 0, (struct sockaddr*)&sa, sizeof(sa)) < 0) { perror("sendto"); return -1; } return 0; } /* 处理ARP响应 */ static void process_arp_response(arp_scanner_t *scanner, unsigned char *buffer, size_t len) { struct ether_arp *arp = (struct ether_arp *)(buffer + sizeof(struct ether_header)); // 提取IPMAC char ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, arp->arp_spa, ip_str, sizeof(ip_str)); pthread_mutex_lock(&scanner->lock); // 检查是否是新主机 int is_new = 1; arp_entry_t *entry = scanner->entries; while (entry) { if (strcmp(entry->ip, ip_str) == 0) { memcpy(entry->mac, arp->arp_sha, 6); entry->last_seen = time(NULL); is_new = 0; break; } entry = entry->next; } // 发现新主机 if (is_new) { arp_entry_t *new_entry = malloc(sizeof(arp_entry_t)); strcpy(new_entry->ip, ip_str); memcpy(new_entry->mac, arp->arp_sha, 6); new_entry->last_seen = time(NULL); new_entry->next = scanner->entries; scanner->entries = new_entry; // 打印到串口 printf("[NEW HOST] IP: %s, MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", ip_str, arp->arp_sha[0], arp->arp_sha[1], arp->arp_sha[2], arp->arp_sha[3], arp->arp_sha[4], arp->arp_sha[5]); } pthread_mutex_unlock(&scanner->lock); } /* 清理过期条目 */ static void clean_expired_entries(arp_scanner_t *scanner) { time_t now = time(NULL); pthread_mutex_lock(&scanner->lock); arp_entry_t **pp = &scanner->entries; // **pp 保存的是链表头节点地址 while (*pp) { arp_entry_t *entry = *pp; if (now - entry->last_seen > scanner->config.valid_time) { *pp = entry->next; free(entry); } else { pp = &entry->next; } } pthread_mutex_unlock(&scanner->lock); } /* 接收ARP响应 */ void *arp_scan_thread(void *arg) { arp_scanner_t *scanner = (arp_scanner_t *)arg; scanner->scanning = SCANNING_ON; while (scanner->scanning) { // 清理过期条目 clean_expired_entries(scanner); // 遍历IP范围 for (uint32_t ip = inet_addr(scanner->config.start_ip); ip <= inet_addr(scanner->config.end_ip); ip = ntohl(ntohl(ip) + 1)) { if (!scanner->scanning) break; // scanning为0,停止扫描 // 发送ARP请求 char dest_ip[16]; inet_ntop(AF_INET, &ip, dest_ip, sizeof(dest_ip)); send_arp_request(scanner->sockfd, SOURCE_IP, dest_ip, IFNAME); // 接收响应 unsigned char buffer[ETH_FRAME_LEN]; struct sockaddr_ll saddr; socklen_t saddr_len = sizeof(saddr); fd_set fds; // 设置发包间隔 struct timeval tv = { .tv_usec = scanner->config.send_interval * 1000 }; FD_ZERO(&fds); FD_SET(scanner->sockfd, &fds); if (select(scanner->sockfd + 1, &fds, NULL, NULL, &tv) > 0) { ssize_t len = recvfrom(scanner->sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&saddr, &saddr_len); if (len > 0) { process_arp_response(scanner, buffer, len); } } } // 等待扫描间隔 int sleep_count = scanner->config.scan_interval; while (sleep_count > 0 && scanner->scanning) { sleep(1); sleep_count--; } } close(scanner->sockfd); scanner->sockfd = -1; scanner->scanning = SCANNING_OFF; return NULL; }
最新发布
08-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值