Os contadores de repositórios Iptables restauram, ao usar cotas, não funcionando como esperado

5

Eu defini uma cota para um determinado computador:

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

Isso funciona como esperado. Quando o limite (500MB) é atingido, todos os pacotes desse computador em particular são descartados.

Mas, se eu salvar os contadores (iptables-save -c > /home/iptables.counters), reiniciar o iptables e restaurar os contadores (iptables-restore -c /home/iptables.counters), então não importa O que os contadores salvos eram, esse computador ainda será capaz de baixar 500 MB, então o tamanho total do contador, antes que o computador perca o acesso à Internet será X + 500MB, onde X é o tamanho do contador salvo.

Eu devo estar fazendo algo errado, já que este é o objetivo de salvar / restaurar contadores: retomar a contagem de bytes até que o limite seja atingido. Qualquer tipo de sugestão seria muito apreciado ...

    
por Andy 18.06.2014 / 13:12

1 resposta

7

O problema é um erro do kernel.

No EL6, o código de cota que faz a correspondência mostra isso:

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;

Em F20, mostra isso:

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;
}

É basicamente o mesmo (menos alterações de espaçamento) apart de uma linha;

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

Isso serve como um parâmetro de exibição.

Portanto, no EL6, se você configurar uma cota, passar alguns pacotes e, em seguida, iptables -vnL SOMECHAIN , perceberá que o valor da cota diminui.

Em F20 fazendo a mesma coisa, o valor não diminui. Eu acho que os projetistas acreditam que é provavelmente uma coisa melhor garantir que as pessoas saibam qual cota foi definida e não qual é a cota (ver como a contagem de pacotes deixa claro o que sobrou).

No entanto, isso tem um efeito não intencional. Quando você executar iptables-save , salve o valor da cota como lido por iptables . No EL6, se esse valor atingir 0, ele exibirá 0 a iptables . Assim, quando você restaurar, você restaura o 0 de volta na cadeia do iptables.

Com eles removendo-o, esse valor nunca diminui e, portanto, você nunca salva a cota.

O que realmente precisa acontecer é que o módulo precisa ser redesenhado. Deve haver uma entrada quota e uma entrada remaining . Restantes devem decrementar como no EL6 e ser o que é usado para forçar a cota, enquanto que "cota" deve ser o valor atual como em F20. Desta forma, você obtém o melhor dos dois mundos. Um estado salvo da cota e uma descrição real da cota definida.

Você provavelmente deve denunciar isso para a equipe do netfilter.

    
por 20.06.2014 / 01:09