nftables
suporta conjuntos preenchidos dinamicamente que são documentados no wiki nftables . O primeiro exemplo na página wiki é o seguinte:
table ip my_filter_table {
set my_ssh_meter {
type ipv4_addr
size 65535
flags dynamic
}
chain my_input_chain {
type filter hook input priority filter; policy accept;
tcp dport 22 ct state new add @my_ssh_meter { ip saddr limit rate 10/second } accept
}
}
nftables
configuração acima é explicada da seguinte forma:
Neste exemplo, criamos uma regra para corresponder a novas conexões TCP ssh (porta 22), que usa um conjunto dinâmico chamado my_ssh_meter para limitar a taxa de tráfego a 10 conexões por segundo para cada endereço IP de origem.
Como ler esta regra ou como entendê-la? Quero dizer, os endereços IP de origem ( ip saddr
) com limit rate 10/second
dados são adicionados ao conjunto nomeado my_ssh_meter
se o subsistema de rastreamento de conexão do Linux detectar uma nova conexão ( ct state new
) para a porta de destino TCP 22 ( tcp dport 22
). No entanto, parece que o my_ssh_meter
conjunto nunca é usado? E a accept
ação executada ao preencher o conjunto foi bem-sucedida?
O que acontece:
quando uma nova conexão ssh chega, sua fonte mais medidor anexado é adicionado (se ainda não estiver presente: é um conjunto, então cada elemento está presente apenas uma vez) ao conjunto e avaliado para fornecer um resultado booleano verdadeiro/falso
se a avaliação for verdadeira, a regra pode continuar, senão a regra para.
nota: sem o medidor anexado, adicionar um elemento sempre seria avaliado como verdadeiro: adicionar a um conjunto não é terminal.
Aqui:
se for avaliada como verdadeira (ou seja: não inundar), a regra continua para
accept
encerrar achain my_input_chain
avaliação do gancho de entrada atual (ou seja: ).se for avaliado como falso, a regra termina antes de sua
accept
declaração finalaccept
Portanto, aconteça o que acontecer, o novo pacote de conexão é sempre aceito: esse conjunto de regras como está não tem efeito visível, exceto preencher o conjunto.
O exemplo do conjunto de regras do wiki está incompleto. Deve ser seguido por um
drop
(oureject
) nas mesmas condições (certamente é possível alguma fatoração de regra):Portanto, se a métrica estourou, a
accept
parte final da regra anterior não é avaliada e a conexão de entrada é descartada na próxima regra. Enquanto houver tentativas, elas serão contabilizadas no balde de token da métrica. Portanto, enquanto as tentativas continuarem muito rápidas, nenhuma nova conexão será possível (observe que, com um token bucket burst padrão de 5, as primeiras conexões sempre serão bem-sucedidas, mesmo que sejam inundadas imediatamente).O importante a saber aqui é que, como acontece com muitas outras instruções, a instrução set (com sua sintaxe especial usando
@
set ) faz uma ação com uma alteração (um elemento é adicionado a um conjunto) e tem um resultado booleano: true ou false o que condiciona uma avaliação posterior da parte restante da regra: ambos os papéis estão em uso ao mesmo tempo.Para fazer testes, basta substituir
10/second
por10/minute
ou10/hour
: o comportamento agora ficará mais óbvio (após as 5 primeiras conexões: por padrãolimit
o token bucket do 's permite um burst de 5 pacotes.)