通过路由器的 ARP 响应

ARP Response over router

我对网络还很陌生,我一直在努力理解 ARP 请求。我一直在使用 mininet 和 wireshark 来测试我在做什么。

当我使用 mininet 生成 2 个主机(h1 和 h2)和一个交换机时,我的 ARP 广播立即得到 ARP 回复的响应,一切正常。

当我使用给定的 router.py 脚本在 mininet 上生成以下内容时 -

*** Creating network
*** Adding controller
*** Adding hosts:
h1x1 h1x2 h2x1 h2x2 h3x1 h3x2 r0 
*** Adding switches:
s1 s2 s3 
*** Adding links:
(h1x1, s1) (h1x2, s1) (h2x1, s2) (h2x2, s2) (h3x1, s3) (h3x2, s3) (s1, r0) (s2, r0) (s3, r0) 
*** Configuring hosts
h1x1 h1x2 h2x1 h2x2 h3x1 h3x2 r0 
*** Starting controller
c0 
*** Starting 3 switches
s1 s2 s3 ...
*** Routing Table on Router:
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.0.0.0        0.0.0.0         255.0.0.0       U     0      0        0 r0-eth3
172.16.0.0      0.0.0.0         255.240.0.0     U     0      0        0 r0-eth2
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 r0-eth1
// ./a.out Send <InterfaceName>  <DestIP> <RouterIP> <Message>
mininet> h1x1 ./a.out Send h1x1-eth0 10.0.0.1 192.168.1.100 'This is a test'

这就是我 运行 我在 mininet 上的命令到 运行 ARP 请求的方式。

当我尝试 运行 使用目标 IP 10.0.0.1 和路由器 IP 192.168.1.00 的 ARP 请求时,我的 ARP 请求广播正常,但我没有收到 ARP 回复,而是收到一系列ICMPv6 响应。

这是我创建 ARP 的方式 header

struct arp_hdr construstArpRequest(char if_name[], int sockfd, struct in_addr dst, struct ifreq if_hwaddr) {
    printf("Constructing ARP request --\n");
    struct arp_hdr arphdr;
    arphdr.ar_hrd = htons(0x0001);
    arphdr.ar_pro = htons(0x0800);
    arphdr.ar_hln = 6;
    arphdr.ar_pln = 4;
    arphdr.ar_op = htons(0x0001);

    unsigned long sip = get_ip_saddr(if_name, sockfd); // source IP
    memcpy(arphdr.ar_sip, &sip, 4); // source IP
    memcpy(arphdr.ar_tip, &dst.s_addr, 4); // taget IP
    memset(arphdr.ar_tha, 0, 6); // taget HA
    memcpy(arphdr.ar_sha, if_hwaddr.ifr_hwaddr.sa_data, 6); // source HA

    return arphdr;
}

然后我创建我的 ARP 请求

        int sockfd = -1;
        if((sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0){
            perror("socket() failed!");
        }

        // connect to an internet frame
        struct ifreq if_hwaddr;
        memset(&if_hwaddr, 0, sizeof(struct ifreq));
        strncpy(if_hwaddr.ifr_name, interfaceName, IFNAMSIZ-1);
        if(ioctl(sockfd, SIOCGIFHWADDR, &if_hwaddr) < 0){
            perror("SIOCGIFHWADDR");
        }

        struct arp_hdr arpRequest;
        arpRequest = construstArpRequest(interfaceName, sockfd, router_ip, if_hwaddr);

如果我需要包含有关我实际发送请求的方式的代码,我可以但不确定它是否是必要的代码。在我的整个研究过程中,我遇到了一些答案,说你不会得到广播响应,因为你是通过网络 运行 连接它,在这种情况下,你如何获得目标 MAC 地址?

ARP 请求仅针对 IPv4,并使用广播(IPv6 没有广播,它使用 NDP,而不是 ARP),但路由器不会将广播转发到不同的网络。

源主机将使用其配置的掩码来屏蔽目标地址,以确定目标地址是否在同一网络上。如果目标在同一个网络上,它将使用 ARP(在 ARP table 中,或发送一个新的 ARP 请求)来确定目标主机数据-link 地址并使用它来构建数据-link 帧。如果目的地在不同的网络上,源主机将使用 ARP(在 ARP table 中,或发送新的 ARP 请求)来确定其配置网关的数据-link 地址,并且它将使用网关数据-link 地址来构建数据-link 框架。

您正在尝试对不同网络上的主机使用 ARP 请求,但这不起作用。尝试向不同网络上的目的地发送 ARP 请求将得不到响应,并且您看到了这一点(您需要为 ARP 请求实现超时,并在网络堆栈上向请求进程发送错误消息超时)。

您看到的 IPv6 流量是在配置了 IPv6 的 LAN 上定期发生的正常 IPv6 维护流量。