为什么Linux在不正确的接口上应答ARP?

我有以下Linuxnetworking设置:有一个eth10networking接口,分配地址为10.11.0.1/24。 然后有一个tap0networking接口,分配了虚拟地址0.0.0.1/32(我分配了一个虚拟地址来使接口向上),并且来自/到那个的stream量由最初创buildtap0接口的用户空间程序控制。 在tap0接口的另一端,有一个用户空间程序通过原始套接字使用它来查找ARP请求并构造一个响应。

现在,当用户空间程序构build一个请求10.11.0.1的ARP请求时,我期望另一个原始套接字用户空间程序回复它。 但是,我得到了两个答复:一个来自原始套接字程序,另一个来自Linux内核。

显然,Linux内核推断10.11.0.1是属于它的地址,因此回复。 但是,10.11.0.1不是tap0接口的地址。 它是eth10接口的地址。

我的问题是:为什么Linux内核会这样做? 有什么办法来禁用在错误的界面上的ARP答复?

我对这个问题的临时解决scheme是使用除10.11.0.1之外的其他地址作为原始套接字/ tap0目的。 但是,因为这个系统应该是可以在任何开发机器上运行的应用程序的系统级testing,所以我不能保证与其他接口没有IP地址冲突。 因此,在错误的接口上禁用ARP回复将会很好。

解决这个问题的另一种方法是使用netmap,为用户空间应用程序保留整个接口,防止内核在用户空间应用程序运行时将其用于任何事情。 但是我希望我的testing在没有netmap的情况下运行。

你为什么把ARP回复称为“错误的”? 系统的IP地址当然可以通过该接口访问。 这就是为什么发送ARP回复开始。 不这样做可能会导致一些stream量通过不太理想的path,或根本不stream通。 例如,tap0可能是一个VPN连接,这个ARP应答有助于确保到其他IP地址的stream量能够通过VPN正确stream动。

如果你真的想这样做,你可以设置arp_ignorearp_announce为所需的值。

 arp_announce - INTEGER Define different restriction levels for announcing the local source IP address from IP packets in ARP requests sent on interface: 0 - (default) Use any local address, configured on any interface 1 - Try to avoid local addresses that are not in the target's subnet for this interface. This mode is useful when target hosts reachable via this interface require the source IP address in ARP requests to be part of their logical network configured on the receiving interface. When we generate the request we will check all our subnets that include the target IP and will preserve the source address if it is from such subnet. If there is no such subnet we select source address according to the rules for level 2. 2 - Always use the best local address for this target. In this mode we ignore the source address in the IP packet and try to select local address that we prefer for talks with the target host. Such local address is selected by looking for primary IP addresses on all our subnets on the outgoing interface that include the target IP address. If no suitable local address is found we select the first local address we have on the outgoing interface or on all other interfaces, with the hope we will receive reply for our request and even sometimes no matter the source IP address we announce. The max value from conf/{all,interface}/arp_announce is used. Increasing the restriction level gives more chance for receiving answer from the resolved target while decreasing the level announces more valid sender's information. 

arp_ignore被描述为:

 arp_ignore - INTEGER Define different modes for sending replies in response to received ARP requests that resolve local target IP addresses: 0 - (default): reply for any local target IP address, configured on any interface 1 - reply only if the target IP address is local address configured on the incoming interface 2 - reply only if the target IP address is local address configured on the incoming interface and both with the sender's IP address are part from same subnet on this interface 3 - do not reply for local addresses configured with scope host, only resolutions for global and link addresses are replied 4-7 - reserved 8 - do not reply for all local addresses The max value from conf/{all,interface}/arp_ignore is used when ARP request is received on the {interface} 

所以,你会想将arp_ignore设置为1(或者可能是2),将arp_announce为2。

 net.ipv4.conf.all.arp_ignore=1 net.ipv4.conf.all.arp_announce=2 

对于testing,这可能是很好的。 但是一个真正的生产系统可能会以你所经历的方式行事,你的程序需要能够处理这个问题。