我为某台计算机设置了配额:
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),那么无论保存什么计数器,该计算机仍然可以下载500 MB,所以计算机失去互联网访问之前的总计数器大小将是X 500MB,其中X是保存的计数器大小.
我必须做错事,因为这是保存/恢复计数器的重点:从该字节计数恢复直到达到限制.任何类型的提示将不胜感激……
解决方法
问题是内核错误.
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("a_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("a_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做同样的事情,价值不会减少.我想设计师认为,确保人们知道配额是什么而不是配额的真实情况可能是更好的事情(因为数据包计数清楚地说明剩下的是什么).
但是,这会产生意想不到的效果.当你运行iptables-save时,你可以通过iptables保存配额值.在EL6中,如果此值达到0,则显示0到iptables.因此,在还原时,将0还原为iptables链.
随着它们删除它,这个值永远不会减少,因此你永远不会实际保存配额.
真正需要发生的是模块需要重新设计.应该有配额条目和剩余条目.剩余应该像EL6一样递减,并且用于强制执行配额,而“quota”应该是F20中的实际设定值.这样你就可以获得两全其美.已保存的配额状态以及设置的配额的实际描述.
您应该向netfilter团队报告此事.