Я установил квоту для определенного компьютера:
iptables -A FORWARD -d 192.168.1.10 -m quota --quota 500000000 -j ACCEPT
iptables -A FORWARD -d 192.168.1.10 -j DROP
Это работает, как ожидалось. По достижении предела (500 МБ) все пакеты для этого компьютера отбрасываются.
Но если я сохраню счетчики (iptables-save -c> /home/iptables.counters), перезапущу iptables и восстановлю счетчики (iptables-restore -c /home/iptables.counters), то независимо от того, какие сохраненные счетчики при этом этот компьютер все еще сможет загрузить 500 МБ, поэтому общий размер счетчика до того, как этот компьютер потеряет доступ в Интернет, будет X + 500 МБ, где X - размер сохраненного счетчика.
Я, должно быть, делаю что-то не так, поскольку в этом весь смысл сохранения / восстановления счетчиков: возобновление с этого счетчика байтов до тех пор, пока не будет достигнут предел. Мы будем очень благодарны за любые подсказки ...
Эта проблема является ошибка ядра.
В 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("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.
Когда они его удаляют, это значение никогда не уменьшается, и поэтому вы никогда не сохраняете квоту.
Что действительно нужно сделать, так это переработать модуль. Должен быть quota
вход и remaining
вход. Оставшееся значение должно уменьшаться, как в EL6, и быть тем, что используется для обеспечения соблюдения квоты, тогда как «квота» должна быть фактическим установленным значением, как в F20. Таким образом, вы получите лучшее из обоих миров. Сохраненное состояние квоты и фактическое описание того, какая квота установлена.
Вам, вероятно, следует сообщить об этом команде netfilter.