iptables nat表命中率很少问题解析和解决

问题背景描述:做一个功能,路由器抓取lan侧client的上下行速率,原先考虑到断网的情况下,来抓取lan client跟路由器,所以在nat表的PREROUTING里设置规则,结果发现对应的规则抓取的包很少。

当时测试方案,在路由器console里,调用tftp 从lan PC down个文件下来,结果,mangle的PREROUTING数据包正常,NAT的PREROUTING数据包很少,FILTER的INPUT数据包正常。

这个问题当时觉着非常诡异,且自己也比较感兴趣,那么开始分析原因和解决方案了

当时第一个想法是:1.是不是mangle的PREROUTING ACCEPT的包,就不过NAT的PREROUTING,测试方案,在mangle里和NAT里的PREROUTING设置同一条对DNS 过滤的包,如下
iptables -t nat -I PREROUTING -m string --hex-string "luyou|04|qtec|02|cn" --algo bm
结果对应的规则下抓包NAT和mangle一致, 可见单个规则的ACCEPT,只会影响当前chain,也验证了mangle的PREROUTING的包也会过NAT表的PREROUTING的包,该想法不成立

接下来第二个想法是是不是发往local in的包不过NAT的PREROUTING, 发往wan口的过NAT的PREROUTING,首先从相关文档上看这个假想方案不成立,但当时实在没其他方向,测试方案,还是抓取dns包,首先将LAN PC 的DNS服务器设置为8.8.8.8,在NAT的PREROUTING里能抓到这个包,后来将 LAN PC的DNS服务器设置为gateway,但在NAT的PREROUTING仍能抓取到,所以该想法也没不通过

第3个想法是 是否开启硬件加速,就是说硬件加速的包,不过nat prerouting的计数器, 后来根据大牛解释,后来在内核发现对应的硬件加速没有开启

最后细心看源码,发现在iptable_nat.c里

*switch (ctinfo) {

case IP_CT_RELATED:
case IP_CT_RELATED_REPLY:
    if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
        if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo,
                           hooknum))
            return NF_DROP;
        else
            return NF_ACCEPT;
    }
    /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
case IP_CT_NEW:
    /* Seen it before?  This can happen for loopback, retrans,
     * or local packets.
     */
    if (!nf_nat_initialized(ct, maniptype)) {
        unsigned int ret;
        ret = nf_nat_rule_find(skb, hooknum, in, out, ct);
        if (ret != NF_ACCEPT)
            return ret;
    } else {
        pr_debug("Already setup manip %s for ct %p\n",
             maniptype == NF_NAT_MANIP_SRC ? "SRC" : "DST",
             ct);
        if (nf_nat_oif_changed(hooknum, ctinfo, nat, out))
            goto oif_changed;
    }
    break;*

终于发现问题产生的原因 即 netfilter中处理nat的hook并不像处理filter的hook。处理nat的hook时首先判断连接是否IPT_NEW或者IPT_RELATED的连接,如果是则ipt_do_table()调用nat上的规则;如果是保持IPT_ESTABLISHED的,则直接找出tuple,然后做相应的修改。 这也是nat表不建议加对包过滤的规则的原因了
而之前的DNS查询测试中,lan PC每次DNS查询都会使用一个新的随机源端口,所以NAT的规则的包也会增加,所以察觉不到异常,而TFTP中,当文件UDP下传时,应该conntrack 建立,所以很多包就不走NAT的PREROUTING了,所以NAT的PREROUTING包就少了很多,所以命中很少。
看来NETFRITER框架要好好仔细看,另除了firewall 规则外,ip conntrack也是比较重要的一环

你可能感兴趣的:(iptables)