Linux的IPV4协议栈的多网口IP报文转发

【背景】:

arm板有2个网口A和B,A口通过网线连接PC,PC的IP配置的网关为ARM的A网口IP,具体如下:

PC的IP配置: 172.20.0.111 255.255.0.0 172.20.0.16

ARM的网卡A: 172.20.0.16 255.255.0.0 default gw

ARM的网卡B: 172.21.0.17 255.255.0.0 default gw

【现象】:pc ping 172.21.0.17 能够ping通,在pc上通过wireshark抓包,发现icmp报文的mac地址是ARM的网卡A,ip地址是ARM的网卡B。

【分析1】:想到/proc/sys/net/ipv4/xx/arp_ignore和arp_announce这2个参数,对于arp报文的多网口转发,查看ARM的板卡配置,arp_ignore=1 arp_announce=2,已经禁止网口间arp转发;并且pc的arp表查看,没有学到网口B的mac地址。

【分析2】:想到linux的Ip转发,/proc/sys/net/ipv4/ip_forward这个参数,查看ARM板卡的配置,ip_forward这个参数是0,表示默认关闭ip报文转发。

【分析3】:分析Linux内核ipv4的路由查找代码,在ipv4收到包后,分析如果非广播和多播报文,会进行路由查找,先查找local route表,没有找到再查找main route表。local route表总查找到dstip地址就是网口B的ip地址,直接建立路由连接。

【更改】:在local route查找过程中,匹配dstip和本网卡的ip,如果不是同一个网段,则直接丢弃该IP包。

【代码】:在net/ipv4/fib_frontend.c的__fib_validate_source()函数中,增加如下:

	if (!rpf && !fib_num_tclassid_users(net) &&
	    (dev->ifindex != oif || !IN_DEV_TX_REDIRECTS(idev)))
#if 0
	{
		struct in_ifaddr **ifap = NULL;
		struct in_ifaddr *ifa = NULL;
		if(idev->ifa_list)
		{
			for (ifap = &idev->ifa_list; (ifa = *ifap) != NULL;
				 ifap = &ifa->ifa_next)
				{
					if((fl4.saddr & ifa->ifa_mask) == (ifa->ifa_local & ifa->ifa_mask))
					{
						//pr_info("net:%s saddr:%pI4 ifa_address:%pI4 ifa_local:%pI4 mask:%d", idev->dev->name, &fl4.saddr, &ifa->ifa_address, 
							//										  &ifa->ifa_local, ifa->ifa_mask);
						goto last_resort;
					}	
				}
		}
		goto e_inval;
	}
#endif
	goto last_resort;

你可能感兴趣的:(Linux系统,linux,tcp/ip)