Porque é que a sua regra de iptables nunca vê tráfego VPN em ponte
Os quadros em ponte podem contornar a cadeia IP que está a observar. Compare a família bridge nativa com o antigo br_netfilter antes de acrescentar outra regra.
Duas máquinas virtuais no mesmo host chegam à LAN através de uma ponte, e uma regra colocada na cadeia ip forward mostra um contador que nunca se move. Os quadros são reais, o tráfego passa e a regra simplesmente não está no seu caminho. Comparar as duas formas como o Linux expõe o tráfego em ponte explica este silêncio, e também explica porque é que carregar um módulo antigo é uma resposta pior do que parece.
Dois caminhos através de um só host
Um pacote pode sair deste host de duas formas muito diferentes, e a diferença decide que hooks o veem. Se o destino está para lá de uma porta física e o quadro é comutado entre duas portas da ponte, o host reencaminha um quadro Ethernet; o código de encaminhamento não é consultado, e não ocorre nenhum salto encaminhado. Se o destino é o próprio host, ou uma rede alcançada por uma interface de túnel, o pacote é encaminhado e os hooks da camada IP aplicam-se de facto. Tenha esta bifurcação presente, porque cada pergunta posterior sobre cadeias e famílias decorre de qual dos dois caminhos um quadro toma.
Essa distinção é toda a história por trás de uma regra que não conta nada. Um quadro em ponte de veth9a1 para enp3s0 atravessa a ponte, não a pilha IP, por isso uma cadeia ip forward não vê nada para corresponder. Os nomes das interfaces num exemplo mais antigo não determinam que caminho tem, e por isso o primeiro passo é olhar para a topologia e não para o conjunto de regras.
Um túnel acrescenta um terceiro caso que merece um nome. Um dispositivo TUN entrega pacotes IP ao host, por isso são encaminhados e atravessam de facto cadeias IP, enquanto um dispositivo TAP ligado a uma ponte entrega quadros e comporta-se como o caso da ponte. É o tipo de dispositivo, não o nome do produto, que decide.
Compare as duas famílias que conseguem ver um quadro em ponte
O Linux suporta filtragem de ponte nativa através da família bridge do nftables, e não precisa de qualquer módulo antigo para inspecionar e descartar quadros em voo. A documentação da ponte do próprio kernel faz essa recomendação diretamente, o que vale a pena saber antes de um resultado de pesquisa lhe dizer para carregar um módulo.
| Observation point | What it sees | What it costs |
|---|---|---|
nftables bridge family chains | Ethernet frames forwarded between bridge ports, in both directions | Rules must be written in bridge syntax with link-layer matches |
Legacy br_netfilter plus an ip chain | Bridged IPv4 and IPv6 packets, re-exposed through IP-layer hooks | Existing host rules may begin matching traffic they never saw before |
inet chain for routed traffic | Packets the host routes, including traffic arriving from a TUN device | No visibility into purely switched frames |
Usar o comando nft em vez do iptables não coloca, por si só, uma regra na família correta. Uma cadeia declarada na família bridge vê quadros; uma cadeia declarada em ip, ip6 ou inet não os vê, independentemente do binário que a criou. A família é uma propriedade da cadeia, não da ferramenta que a escreveu.
O caminho antigo funciona de forma diferente, e é por isso que vale a pena comparar em vez de escolher um lado por hábito. Carregar o br_netfilter e ativar as definições bridge-nf-call volta a expor o tráfego IPv4 e IPv6 em ponte através dos hooks da camada IP, para que uma regra normal de iptables finalmente possa corresponder-lhe. Os quadros não mudam; o conjunto de hooks por que passam muda, o que significa que cada regra de host existente tem agora um novo público.
Leia o caminho efetivo antes de acrescentar uma regra
Três comandos estabelecem onde está: a que está ligada a ponte, se o módulo antigo está ativo e que cadeias já existem na família bridge. Execute-os antes de escrever o que quer que seja, porque a resposta decide qual dos dois desenhos está a ampliar. Saltar este passo é a forma como uma regra correta acaba numa cadeia que nada atravessa.
bridge link show
lsmod | grep br_netfilter
nft list ruleset | grep -A4 "chain forward"
A saída separa os casos com clareza. As portas listadas sob a ponte dizem-lhe que interfaces são comutadas; um resultado vazio de lsmod significa nenhuma visibilidade na camada IP dos quadros em ponte; uma cadeia forward existente da família bridge significa que já existe um dono da política e que a sua regra pertence ali e não a uma nova cadeia própria.
Depois acrescente uma regra fácil de reler, com um contador e sem mudar o veredicto, e faça passar um único fluxo representativo pela ponte. Um contador que se move prova que o quadro chegou à regra. É tudo o que prova, por isso siga também com o caminho negado, uma vez que uma política que aceita tudo também produz um contador em movimento.
nft add rule bridge filter forward iifname "veth9a1" oifname "enp3s0" counter acceptOnde o módulo antigo muda o comportamento
Ativar o caminho antigo numa ponte em funcionamento não é um ato neutro de acrescentar visibilidade. As regras que antes eram inalcançáveis para o tráfego em ponte tornam-se alcançáveis, incluindo regras de host escritas para outra interface, e uma política drop predefinida na cadeia ip forward pode passar a aplicar-se de repente a quadros que antes passavam intactos. Num host gerido através dessa ponte, o resultado é um bloqueio sem consola. Este não é um modo de falha hipotético; é a consequência comum de alargar um conjunto de hooks numa máquina a que chega pelo caminho que acabou de alargar.
A sequência mais segura é decidir qual família detém a política, escrever aí as regras e manter um caminho de recuperação independente antes de alterar qualquer sysctl. Se duas famílias têm regras, documente qual é a autoridade; duas políticas sobrepostas são a forma como um pacote é aceite num sítio e descartado noutro sem um único ficheiro para ler.
O isolamento em si ainda precisa de um desenho completo. Permitir uma origem para um destino prova apenas que um fluxo funciona, quando o requisito costuma ser que uma VM não consiga alcançar os vizinhos ou o host. Os contadores das regras de negação importam mais do que o contador da regra de aceitação, porque o contador de aceitação é o que já esperava que se movesse.
Por fim, mantenha o caso da entrada do host separado. O tráfego dirigido ao próprio IP da ponte chega a input, não a forward, e uma regra em forward nunca o verá, escolha a família que escolher. Três casos, duas famílias, uma lição: o caminho decide o hook, e o hook decide se a sua regra existe sequer.