Observei que o netfilter altera a porta de origem quando uma conexão é estabelecida no módulo conntrack. Eu preciso evitar esse comportamento.
Aqui está o que fiz para reproduzir meu problema:
- Eu crio uma regra netfilter que irá realizar DNAT da porta 2002 a 2003
sudo iptables -w -t nat -A OUTPUT -s 192.168.30.3 -d 192.168.30.1 -p udp --sport 2001 --dport 2002 -j DNAT --to-destination :2003
- Em seguida, crio uma entrada conntrack para simular uma conexão de 192.168.30.1:2001 (Meu computador) a 192.168.30.1:2003
sudo /sbin/conntrack -I -s 192.168.30.1 -d 192.168.30.3 -p udp --sport 2003 --dport 2001 --timeout 100000
- Eventualmente, eu realizo uma conexão com 192.168.30.1:2002 do meu computador com porta de origem 2001:
sudo nc -u -p 2001 192.168.30.1 2002
Devido à regra DNAT do netfilter, eu esperava um pacote de saída com porta de destino 2003 e porta de origem 2001. No entanto, no wireshark observei que a porta de origem mudou para um número aleatório. Acho que isso ocorre porque meu computador considera que existe uma conexão na porta 2001 (devido à entrada conntrack) e impede que a porta de origem seja 2001 (certo?). Mas eu não quero esse comportamento? Como posso forçar o uso do número da porta 2001?
Responder1
Para que o DNAT funcione (no sentido de que, para que o programa seja capaz de reconhecer as respostas), será necessário realizar um "NAT reverso" que altera a porta de origem dos tráfegos de resposta de 192.168.30.1
(para 192.168.30.3:2001
) de 2003
para .2002
Porém, quando há tráfegos vindos 192.168.30.1:2003
daquele 192.168.30.3:2001
ponto de vista do conntrack não são consequência do DNAT (porque conforme a entrada do conntrack criada, o host não é aquele que iniciou a conexão), o NAT reverso será inapropriado.
Portanto, o netfilter é "forçado" a realizar também o SNAT para que os tráfegos correspondam à regra DNAT, para que possa diferenciar os tráfegos de resposta (que também são de 192.168.30.1:2003
) pelo destino 192.168.30.3:$random
.
Presumo que o netfilter executará NAT reverso para DNAT (que é um SNAT) antes do NAT reverso para SNAT (que é um DNAT) ou conseguirá usar o destino antes do NAT reverso para SNAT (ou seja, 192.168.30.3:$random
) como correspondência para o NAT reverso para DNAT, caso contrário o SNAT forçado será inútil. (No caso de não reversão, entretanto, nada disso é verdadeiro AFAIK: DNAT será executado em PREROUTING antes de SNAT em INPUT, e a correspondência de destino na regra SNAT, se houver, usará o valor resultante no DNAT)
O fato é que a história acima/o "problema" da sua pergunta dificilmente faz sentido na realidade. Tomemos como exemplo uma VPN wireguard de dois hosts: suponha que você queira ter Endpoint=
configurado em ambos os hosts (para que qualquer um deles possa iniciar a comunicação) e não queira que os valores sejam "atualizados" inesperadamente por causa do SNAT forçado (assumindo que poderia realmente ser acionado), o que você deve fazer é simplesmente um SNAT "sempre ativo" que "complementa" o DNAT/é equivalente ao NAT de reserva:
iptables -t nat -A INPUT -s 192.168.30.1 -d 192.168.30.3 -p udp --sport 2003 --dport 2001 -j SNAT --to-source :2002
o que normalmente não é necessário no modelo cliente-servidor devido ao NAT reverso automático para o DNAT.
PS: Você ainda não deve alcançá-lo 192.168.30.1:2003
, 192.168.30.1:2003
caso contrário, o NAT de origem forçada também ocorrerá se você alcançá-lo novamente 192.168.30.1:2002
antes que a entrada conntrack do primeiro seja eliminada. A regra SNAT adicional em INPUT também não deve causar problemas extras.
Responder2
Você pode definir dois fluxos que normalmente colidiriam noconexãotabela de pesquisa (geralmente acionando uma reescrita da porta de origem no novo fluxo para evitar a colisão) para estar em diferenteszonas de conexão. Esta propriedade de zona adicional tornaconexãonão corresponder/colidir com um fluxo existente em uma zona conntrack diferente: nenhuma reescrita da porta de origem acontecerá.
Para o seu exemplo específico, aqui está uma regra específica que evitará a colisão e, assim, impedirá a reescrita da porta de origem:
iptables -t raw -A OUTPUT -s 192.168.30.3 -d 192.168.30.1 -p udp --sport 2001 --dport 2002 -j CT --zone-orig 1
Normalmente, dependendo do caso de uso, um seletor mais sensato é usado. É frequentemente usado na cadeia PREROUTING com uma interface de entrada como seletor durante o roteamento e frequentemente associado a um valor de marca para que o roteamento também possa ser afetado.
O caso de uso original que fez esta opção aparecer é quandoconexãona mesma pilha de rede (sem namespace de rede adicional) com uma configuração de roteamento complexa (por exemplo: roteamento entre 4 LANs privadas diferentes usando os mesmos endereços IP. por exemplo, entre 192.168.1.0/24 eth0 <-> eth1 10.1.0.0/24, ede novo192.168.1.0/24 eth2 <-> 10.1.0.0/24 eth3) pode ver dois fluxos não relacionados com os mesmos endereços/portas. ComoFiltro de redeeconexãonão sei nada sobre roteamento (oconexãotabela de pesquisa inclui apenas endereços), eles devem ser ensinados a considerar esses fluxos separadamente, adicionando uma propriedade de zona manualmente vinculada à topologia de roteamento noconexãotabela de pesquisa.
(Aqui está umLigação LWNquando o recurso foi originalmente proposto.)
Responder3
O NAT altera a porta de origem para reduzir o risco de um conflito de porta. O que deveria acontecer se aquele esporte 2002 já estivesse ocupado na máquina NAT?
Se você tiver requisitos específicos para portas específicas, poderá adicionar SNAT
regras específicas para isso, mas, novamente, e se vários clientes internos tentarem usar a mesma porta de origem?
Aqui devemos voltar e reconhecer que o NAT é um hack que foi criado para reduzir o problema da falta de endereços IP públicos. A verdadeira solução aqui é que todos tenham IPs públicos não NAT.
Hoje em dia, quando falamos sobre NAT, na maioria das vezes nos referimos a endereços IP privados atrás de um IP.NAPT
aPergunta semelhante relacionada a isso, eu estava pensando no MASQUERADE
alvo e nãoDNAT