多网卡配置同一网段IP情况解析

目录

一、概述

二、分析


一、概述

一般情况下是不这么配置的,但是实际项目中总有些奇葩的甲方。在虚拟机中模拟一下这个情形。

二、分析

虚拟机中添加三个网卡,ip地址配置成同一个网段,桥接。主机的IP地址是192.168.0.109

ens33: inet 192.168.0.112  netmask 255.255.255.0  broadcast 192.168.0.255
            ether 00:0c:29:ae:cd:e2  txqueuelen 1000  (Ethernet)

ens37: inet 192.168.0.111  netmask 255.255.255.0  broadcast 192.168.0.255
        ether 00:0c:29:ae:cd:ec  txqueuelen 1000  (Ethernet)

ens38: inet 192.168.0.107  netmask 255.255.255.0  broadcast 192.168.0.255
        ether 00:0c:29:ae:cd:f6  txqueuelen 1000  (Ethernet)

试着在主机上分别ping三个接口,都是通的,但是此时看mac表:

三个IP的mac都是一样的,这是为什么呢,在解释原因之前,我们先看下虚拟机上的路由,可以发现,三个接口添加了三条直连路由:

[root@localhost ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use   Iface
192.168.0.0     0.0.0.0         255.255.255.0       U       0      0        0       ens38
192.168.0.0     0.0.0.0         255.255.255.0       U     100    0        0       ens33
192.168.0.0     0.0.0.0         255.255.255.0       U     101    0        0       ens37

这种情况下只有一条路由生效,可以使用ping 192.168.0.109发现是通的(通过抓包,发现源IP是192.168.0.108,即是从ens38口发出的;对应的ens38 metric最小,优先级最高)。

回到开始的问题,在主机上分别ping虚拟机上三个网口时,会发送arp request,对于我们目前的组网来说,每个网口都会收到arp广播,但是抓包可以发现,所有的arp都是回复的ens38口的MAC,这就是主机上对应三个虚拟机网口地址一样的直接原因。

虚拟机在arp reply的时候要查找路由,由于三个地址都是本机地址,所以从代码看arp对于这三个地址应该有三个回复,

    if (arp->ar_op == htons(ARPOP_REQUEST) &&
        ip_route_input_noref(skb, tip, sip, 0, dev) == 0) {

        rt = skb_rtable(skb);
        addr_type = rt->rt_type;

        if (addr_type == RTN_LOCAL) {
            int dont_send;

            dont_send = arp_ignore(in_dev, sip, tip);
            if (!dont_send && IN_DEV_ARPFILTER(in_dev))
                dont_send = arp_filter(sip, tip, dev);
            if (!dont_send) {
                n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
                if (n) {
                    arp_send_dst(ARPOP_REPLY, ETH_P_ARP,
                             sip, dev, tip, sha,
                             dev->dev_addr, sha,
                             reply_dst);
                    neigh_release(n);
                }
            }

 

但实际过程中只有一个arp reply,可以用systemtap跟踪一下每个口报文的情况,这里我发现除了ens38能成功发送arp reply,其他的口对应的arp request处理在查路由时失败了,关键就在于fib_validate_source函数,fib_validate_source的逻辑是这样,如果查路由时发现目的IP是local的,要进一步进行校验,主要的方法是将sip,dip对调,再去查一遍路由,这时候要保证二者查到的接口是一致的,这就是所谓反向过滤(rp_filter)配置,你可以试着关闭,可以看到三个arp reply,虽然这也不是好事情。

    if (res.type == RTN_LOCAL) {
        err = fib_validate_source(skb, saddr, daddr, tos,
                      0, dev, in_dev, &itag);
        if (err < 0)
            goto martian_source;
        goto local_input;
    }

通过上面的分析,在arp reply进行反向路由查找校验时,由于源地址是192.168.0.109,查找时一定会命中第一条直连路由,于是将ens38对应的mac回复给host。而在其他端口发送相应的arp request时就会产生冲突。

那么如果想要通过ens37访问192.168.0.109如何实现呢,我们使用ping 192.168.0.109 -I ens37,这时候没有通,再抓包,发现这次报文确实是从ens37发出的,当使用ens37 ping host时,报文发送的源mac确实是ens37的,从主机上抓包可以确认:

按照上面的分析 host回复报文目的mac是ens38的:

这个报文由于目的mac是ens38的从而导致监听ens37端口的ping无法返回。

由上我们知道,处于相同网段的几个IP之间,在进行arp reply的时候,总会使用优先级高的那条直连路由对应的mac,导致后续回包的目的MAC和目的IP不匹配,导致接收失败。如果主机上学到三个接口正确的MAC地址,就不会产生这种情况。

一种解决的方法是使用策略路由,配置如下:

  • ip rule add from 192.168.0.111 table 20
  • ip route add default via 192.168.0.1 dev ens37 table 20
  • ip route add 192.168.0.0/24 dev ens37 src 192.168.0.111 table 20

目的是配置在同一网段ip时产生的直连路由不产生冲突。如主机请求ens37的mac时,在arp reply时查反向路由,由于src ip匹配了,会去table 20中查找路由,命中table 20中的直连路由,从而以ens37的mac进行回应(在未配置策略路由的情况下,到ens38的广播报文总是匹配优先级高的路由),ens37的目的mac正确时就能正常转发到网卡ens37了。

 

 

 

 

 

  • 6
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值