前几天,由于工作需要,需要在高版本Linux内核中验证iptables的一个功能。于是我使用Ubuntu16.04(内核版本是4.13.0)搭建了一个实验环境。之前一直使用CentOS6.5比较多(内核版本是2.6.35),Ubuntu用的比较少。环境搭好后,立即就发现了一个不对劲的地方。  

root@ubuntu:/home/liu# iptables -nvL 
Chain INPUT (policy ACCEPT 228 packets, 23310 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 282 packets, 55168 bytes)
 pkts bytes target     prot opt in     out     source               destination         

网桥brg0下有两个接口enp2s6和enp2s7,分别接两台PC,我从一台PC ping 另一台PC,结果使用iptables查看filter表的FORWARD链居然没有任何数据包匹配(policy ACCEPT 0 packets, 0 bytes)??很显然,加入到FORWARD链的规则也不会被匹配。这太奇怪了。

正常情况下,网桥转发的数据包也会匹配FORWARD链的规则的(如果没有任何规则,则匹配默认的ACCEPT策略)。于是我又换回CentOS6.5,发现filter表的FORWARD链是有计数的。难道是iptables有问题?我直接重新编译了一次iptables,发现还是这样,看来和iptables没有关系。

网上搜了一些,没有找到类似的问题。只好自己定位了。

我的定位过程如下:

直接搜索Linux4.13内核版本源码,查找“NF_INET_FORWARD",立即查找到net\bridge\br_netfilter_hooks.c文件中br_nf_forward_ip函数最后如下:

 

	NF_HOOK(pf, NF_INET_FORWARD, state->net, NULL, skb,
		brnf_get_logical_dev(skb, state->in),
		parent,	br_nf_forward_finish);

会调用NF_INET_FORWARD HOOK点注册的钩子函数。其中一个钩子函数会遍历filter表的FORWARD链规则。现在看起来是网桥转发流程没有走到这里。怎么办?加打印呗。在最后加一条打印,然后重新编译内核模块,发现会重新编译生成net/bridge/br_netfilter.ko。这个ko很奇怪,lsmod看下居然没有加载这个ko,于是直接把这个ko加载上,立即正常了。  

root@ubuntu:/home/liu# iptables -nvL 
Chain INPUT (policy ACCEPT 15496 packets, 3400K bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 207 packets, 12474 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 14546 packets, 17M bytes)
 pkts bytes target     prot opt in     out     source               destination         

这个br_netfilter.ko是个什么鬼?查了下,netfilter ebtables项目组网站 赫然闪烁着如下提示:

 Since Linux kernel 3.18-rc1, you have to modprobebr_netfilter to enable bridge-netfilter.

从Linux3.18-rc1内核版本之后,你必须手动加载br_netfilter.ko来启动bridge-netfilter功能,这个功能官方网站介绍的很详细了:

 

  • {Ip,Ip6,Arp}tables can filter bridged IPv4/IPv6/ARPpackets, even when encapsulated in an 802.1Q VLAN or PPPoE header. Thisenables the functionality of a stateful transparent firewall.

加载br_netfilter这个ko后,iptables可以过滤网桥处理的数据包,可以使用/proc/sys/net/bridge/bridge-nf-call-iptables的值来控制iptables是否能“看见”网桥处理的数据包。默认系统启动时不会加载这个ko,这样的话,iptables是看不见网桥处理的这些数据包的!更不会匹配任何iptables中的任何规则的!

记录下此文,希望遇到同样问题的朋友能少走弯路。

Logo

更多推荐