当使用配额时,iptables计数器还原,不按预期工作

我为某台电脑设定了一个配额:

iptables -A FORWARD -d 192.168.1.10 -m quota --quota 500000000 -j ACCEPT iptables -A FORWARD -d 192.168.1.10 -j DROP 

这按预期工作。 达到限制(500MB)时,此特定计算机的所有数据包都将被丢弃。

但是,如果我保存计数器(iptables-save -c> /home/iptables.counters),重新启动iptables,并恢复计数器(iptables-restore -c /home/iptables.counters),那么不pipe保存的计数器那台电脑仍然可以下载500 MB,所以总计数器的大小,在这台电脑失去互联网访问将是X + 500MB,其中X是保存的计数器大小。

我一定是做错了,因为这是保存/恢复计数器的重点:从字节计数恢复,直到达到限制。 任何types的提示将不胜感激…

问题一个内核错误。

在EL6中,匹配的配额代码显示了这一点:

 quota_mt(const struct sk_buff *skb, const struct xt_match_param *par) { struct xt_quota_info *q = (void *)par->matchinfo; struct xt_quota_priv *priv = q->master; bool ret = q->flags & XT_QUOTA_INVERT; spin_lock_bh(&quota_lock); if (priv->quota >= skb->len) { priv->quota -= skb->len; ret = !ret; } else { /* we do not allow even small packets from now on */ priv->quota = 0; } /* Copy quota back to matchinfo so that iptables can display it */ q->quota = priv->quota; spin_unlock_bh(&quota_lock); return ret; 

在F20中显示了这一点:

 static bool quota_mt(const struct sk_buff *skb, struct xt_action_param *par) { struct xt_quota_info *q = (void *)par->matchinfo; struct xt_quota_priv *priv = q->master; bool ret = q->flags & XT_QUOTA_INVERT; spin_lock_bh(&priv->lock); if (priv->quota >= skb->len) { priv->quota -= skb->len; ret = !ret; } else { /* we do not allow even small packets from now on */ priv->quota = 0; } spin_unlock_bh(&priv->lock); return ret; } 

除了一行之外基本相同(减去间距的变化)

  /* Copy quota back to matchinfo so that iptables can display it */ q->quota = priv->quota; 

这是作为一个显示参数。

因此,在EL6中,如果您设置了配额,请传递一些数据包,然后执行iptables -vnL SOMECHAIN您将注意到配额值递减。

在F20做同样的事情,价值不会减less。 我想devise师们相信这可能是一个更好的事情,以确保人们知道什么是配额,而不是配额的真正含量(看包数清楚说明什么是剩余的)。

但是,这具有意想不到的效果。 当你运行iptables-save你通过iptables读取的配额值。 在EL6中,如果这个值达到0,它将显示0到iptables 。 因此,当你恢复时,你将0恢复回iptables链。

随着他们删除它,这个值永远不会减less,因此你永远不会实际保存配额。

真正需要发生的是模块需要重新devise。 应该有一个quota条目和一个remaining条目。 剩余的应该像EL6那样递减,是用来强制配额的,而“配额”应该是F20中的实际设定值。 这样你就得到了两全其美的好处。 配额的保存状态和设置的配额的实际说明。

你应该把这个报告给netfilter团队。