
Estou tentando direcionar o tráfego do cliente para um cluster Kubernetes NodePort escutando no 192.168.1.100.30000
.
O cliente precisa fazer uma solicitação, 192.168.1.100.8000
então adicionei a seguinte regra REDIRECT no iptables:
iptables -t nat -I PREROUTING -p tcp --dst 192.168.1.100 --dport 8000 -j REDIRECT --to-port 30000
Em seguida, emito um curl 192.168.1.100:8000
, no entanto, no tcpdump vejo uma porta diferente:
# tcpdump -i lo -nnvvv host 192.168.1.100 and port 8000
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
[Interface: lo] 20:39:22.685968 IP (tos 0x0, ttl 64, id 20590, offset 0, flags [DF], proto TCP (6), length 40)
[Interface: lo] 192.168.1.100.8000 > 192.168.1.100.49816: Flags [R.], cksum 0xacda (correct), seq 0, ack 3840205844, win 0, length 0
[Interface: lo] 20:39:37.519256 IP (tos 0x0, ttl 64, id 34221, offset 0, flags [DF], proto TCP (6), length 40)
Eu esperaria que o tcpdump mostrasse algo como
192.168.1.100.8000 > 192.168.1.100.30000
No entanto, ele está sendo exibido e causando um erro de conexão recusada, pois nenhum processo está listado no 192.168.1.100.49816
.
192.168.1.100.8000 > 192.168.1.100.49816
Estou usando um ambiente de teste, então não tenho acesso a dispositivos remotos, por isso estou usando curl
para testar o caminho REDIRECT do iptables.
Existe uma razão pela qual adicionar uma regra REDIRECT faz com que o tcpdump redirecione o tráfego para uma porta diferente daquela especificada?
Editar:
Após a sugestão do @AB, adicionei a seguinte regra OUTPUT:
iptables -t nat -I OUTPUT -d 192.168.1.100 -p tcp --dport 8000 -j REDIRECT --to-port 30000
e curl prossegue, a contagem de pacotes para a cadeia OUTPUT aumenta (embora o pacote da cadeia PREROUTING REDIRECT não tenha aumentado):
2 10 600 REDIRECT tcp -- * * 0.0.0.0/0 192.168.1.100 tcp dpt:8000 redir ports 30000
No entanto, obtendo o seguinte erro:
# curl -vk https://192.168.1.100:8000/v1/api
* About to connect() to 192.168.1.100 port 8000 (#0)
* Trying 192.168.1.100...
* Connected to 192.168.1.100 (192.168.1.100) port 8000 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* NSS error -12263 (SSL_ERROR_RX_RECORD_TOO_LONG)
* SSL received a record that exceeded the maximum permissible length.
* Closing connection 0
curl: (35) SSL received a record that exceeded the maximum permissible length.
Além disso, tentei adicionar uma rede de sistema remoto, desta vez a contagem de pacotes PREROUTING REDIRECT CHAIN aumenta após a execução remotesystem curl ...
(mas a OUTPUT CHAIN não aumenta):
2 34 2040 REDIRECT tcp -- * * 0.0.0.0/0 172.16.128.1 tcp dpt:8000 redir ports 30000
Erro:
# ip netns exec remotesystem curl -vk https://192.168.1.100:8000/v1/api
* About to connect() to 192.168.1.100 port 8000 (#0)
* Trying 192.168.1.100...
* Connection timed out
* Failed connect to 192.168.1.100:8000; Connection timed out
* Closing connection 0
curl: (7) Failed connect to 192.168.1.100:8000; Connection timed out
Responder1
Para ser claro: o teste do OP é feito do sistema 192.168.1.100 para ele mesmo, não de um sistema remoto, e essa é a causa do problema. A porta não foi alterada neste caso porque nenhuma regra NAT correspondeu, embora teria correspondido se fosse feita a partir de um sistema remoto.
O esquema abaixo mostra como a ordem das operações é executada em um pacote:
A razão é como o NAT funciona no Linux:tabelas de ipvê um pacote na nat
tabela apenas para o primeiro pacote de um novo fluxo conntrack (que está, portanto, no estado NEW).
Esta regra funciona bem quando proveniente de um sistema remoto. Neste caso, o primeiro pacote visto será um pacote recebido:
to port 8000 --> AF_PACKET (tcpdump) --> conntrack --> nat/PREROUTING (iptables REDIRECT): to port 30000
--> routing decision --> ... --> local process receiving on port 30000
Todos os pacotes seguintes no mesmo fluxo terão conntrack manipulando diretamente a mudança de porta (ou reversão de porta para respostas) e pularão qualquer regra iptables na nat
tabela (conforme escrito no esquema: nat
tabela consultada apenas para NEW
conexões). Então, (pulando a parte do pacote de resposta), o próximo pacote recebido passará por isso:
to port 8000 --> AF_PACKET (tcpdump) --> conntrack: to port 30000
--> routing decision --> ... --> local process receiving on port 30000
Para um teste do próprio sistema, o primeiro pacote não é um pacote de entrada, mas um pacote de saída. Em vez disso, isso acontece usando a lo
interface de saída:
local process client curl --> routing decision --> conntrack --> nat/OUTPUT (
no rule here
)
--> reroute check --> AF_PACKET (tcpdump) --> to port 8000
E agora esse pacote é retornado na lo
interface, ele reaparece como um pacote que não é mais o primeiro pacote em uma conexão, então segue o segundo caso acima: conntrack sozinho cuida do NAT e não chama nat/PREROUTING
. Exceto que não foi instruído na etapa anterior para fazer nenhum NAT:
to port 8000 --> AF_PACKET (tcpdump) --> conntrack
--> routing decision --> ... -->
no
local process receiving on port
8000
como não há nada escutando na porta 8000, o sistema operacional envia de volta um TCP RST.
Para que isso funcione no sistema local, uma REDIRECT
regra também deve ser colocada na nat/OUTPUT
cadeia:
iptables -t nat -I OUTPUT -d 192.168.1.100 -p tcp --dport 8000 -j REDIRECT --to-port 30000
Notas Adicionais
se o caso for para uso remoto, não teste no sistema local: as regras percorridas pelo teste não são as mesmas. Isso faz com que o teste não reflita a realidade.
Basta usar um namespace de rede para criar um sistema remoto de bolso caso nenhum outro sistema esteja disponível. Exemplo que deve funcionar com um sistema tendo apenas
nat/PREROUTING
regras e ações do OPcurl http://192.168.1.100/
(que não requer DNS):ip netns add remotesystem ip link add name vethremote up type veth peer netns remotesystem name eth0 ip address add 192.0.2.1/24 dev vethremote ip -n remotesystem address add 192.0.2.2/24 dev eth0 ip -n remotesystem link set eth0 up ip -n remotesystem route add 192.168.1.100 via 192.0.2.1 ip netns exec remotesystem curl http://192.168.1.100:8000/
tcpdump
e NATtcpdump
acontece nasAF_PACKET
etapas do esquema acima: muito cedo para entrada e muito tarde para saída. Isso significa que para um caso de sistema remoto, ele nunca capturará a porta 30000 mesmo quando estiver funcionando. Para o caso do sistema local, uma veznat/OUTPUT
adicionada a regra, ela capturará a porta 30000.Só não confie cegamente no endereço/porta exibido ao
tcpdump
fazer NAT: depende do caso e de onde acontece a captura.