Enrutar el tráfico al clúster de Kubernetes mediante iptables

Enrutar el tráfico al clúster de Kubernetes mediante iptables

Tengo un clúster de Kubernetes (actualmente solo 1 nodo) ejecutándose en mi servidor raíz (netcup) e intento enrutar el tráfico hacia él. Soy bastante malo en networking así que espero que alguien pueda ayudarme.

en el racimometallbEstá instalado y calico según CNI. Metallb es responsable de la asignación y el anuncio de direcciones IP a K8s-LoadBalancers, lo que funciona bien internamente. Entonces puedo alcanzar un servicio de carga equilibrada desde el servidor. Sólo expongo un único servicio con una IP interna fija (proxy inverso)

Ahora quiero exponerlo al exterior enrutando el tráfico directamente a la dirección IP desde metalb usandoiptables

Se aplicaron las siguientes reglas en iptables:

iptables -A PREROUTING -t nat -p tcp -m tcp -j DNAT --to-destination <metallb-ip> -i eth0 --destination-port 80 -m comment --comment Redirect web traffic to cluster (80)
iptables -A PREROUTING -t nat -p tcp -m tcp -j DNAT --to-destination <metallb-ip> -i eth0 --destination-port 443 -m comment --comment Redirect web traffic to cluster (443)
iptables -A POSTROUTING -t nat -p tcp -m tcp -j SNAT --to-source <public-server-ip> -o eth0 --destination-port 80 -m comment --comment Redirect web traffic from cluster (80)
iptables -A POSTROUTING -t nat -p tcp -m tcp -j SNAT --to-source <public-server-ip> -o eth0 --destination-port 443 -m comment --comment Redirect web traffic from cluster (443)

(Tal vez los comandos no sean 100% correctos porque los extraje de mi script ansible. Puede encontrar la parte ansible en la parte inferior)

Hasta donde tengo entendido, esto debería enviar todo el tráfico TCP entrante a la IP interna usando DNAT y todo el tráfico saliente tendrá la dirección del servidor público usando SNAT. Entonces, para un cliente que se conecta, ¿debería parecer que está hablando directamente con el puerto/IP público?

Desafortunadamente, intentar acceder al servicio desde Internet produce lo siguiente:

$> curl <public-server-ip>
curl: (7) Failed to connect to <public-server-ip> port 80 after 647 ms: Network is down

El acceso desde el servidor funciona:

$> curl <metallb-ip>
404 page not found # which the expected answer since its a blank Traefik reverse proxy

Un escaneo de puerto nmap arroja actualmente lo siguiente:

$> nmap -Pn -p 80,443 <public-server-ip>
Starting Nmap 7.93 ( https://nmap.org ) at 2022-12-15 15:57 CET
Strange SO_ERROR from connection to <public-server-ip> (50 - 'Network is down') -- bailing scan
QUITTING!

Pero está funcionando desde que estoy conectado vía SSH.

Actualmente no hay ninguno ufwhabilitado.

Agradezco cualquier ayuda ya que como dije no soy muy bueno haciendo networking. ;)

Guión ansible:

- name: DNAT port 80 to cluster
  iptables:
    table: nat
    chain: PREROUTING
    in_interface: eth0
    protocol: tcp
    match: tcp
    jump: DNAT # REDIRECT
    to_destination: <metallb-ip>
    destination_port: 80
    comment: Redirect web traffic to cluster (80)
  become: yes

- name: DNAT port 443 to cluster
  iptables:
    table: nat
    chain: PREROUTING
    in_interface: eth0
    protocol: tcp
    match: tcp
    destination_port: 443
    jump: DNAT # REDIRECT
    to_destination: <metallb-ip>
    comment: Redirect web traffic to cluster (443)
  become: yes 

- name: SNAT port 80 from cluster
  iptables:
    table: nat
    chain: POSTROUTING
    out_interface: eth0
    protocol: tcp
    match: tcp
    destination_port: 80
    jump: SNAT # REDIRECT
    to_source: <public-server-ip>
    comment: Redirect web traffic from cluster (443)
  become: yes

- name: SNAT port 443 from cluster
  iptables:
    table: nat
    chain: POSTROUTING
    out_interface: eth0
    protocol: tcp
    match: tcp
    destination_port: 443
    jump: SNAT # REDIRECT
    to_source: <public-server-ip>
    comment: Redirect web traffic from cluster (443)
  become: yes

- name: Configure IP Masquerading
  iptables: 
    table: nat
    chain: POSTROUTING
    out_interface: eth0
    jump: MASQUERADE

ACTUALIZAR: Con la ayuda deesteartículo traté de entender el flujo. Se agregaron declaraciones de registro para investigar dónde van mal las cosas. Esto es lo que encontré hasta ahora:

Para comprobar dónde se pierden los paquetes, agregué las siguientes reglas:

iptables -t raw -A PREROUTING -p tcp --dport 80 -j LOG --log-prefix "[raw:PREROUTING]: "
iptables -t mangle -A PREROUTING -p tcp --dport 80 -j LOG --log-prefix "[mangle:PREROUTING]: "
iptables -t nat -A PREROUTING -p tcp --dport 80 -j LOG --log-prefix "[nat:PREROUTING]: "
iptables -t mangle -A POSTROUTING -p tcp --sport 80 -j LOG --log-prefix "[mangle:PREROUTING]: "
iptables -t nat -A POSTROUTING -p tcp --sport 80 -j LOG --log-prefix "[nat:PREROUTING]: "

/var/log/kern.logSolo debajo de las declaraciones de registro rawy mangleque aparecen. Entonces parece que el natpaso no se activa. Verificando las reglas de manipulación con: sudo iptables -t mangle -Lpero no pude identificar ningún problema aquí.

El reenvío de IP está habilitado:

$> sudo sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

Entonces, ¿por qué los paquetes no llegan al natpaso?

$> sudo iptables -t mangle -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
cali-PREROUTING  all  --  anywhere             anywhere             /* cali:6gwbT8clXdHdC1b1 */
LOG        tcp  --  anywhere             anywhere             tcp dpt:http LOG level warning prefix "[mangle:PREROUTING]: "

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
cali-POSTROUTING  all  --  anywhere             anywhere             /* cali:O3lYWMrLQYEMJtB5 */

Chain KUBE-IPTABLES-HINT (0 references)
target     prot opt source               destination

Chain KUBE-KUBELET-CANARY (0 references)
target     prot opt source               destination

Chain KUBE-PROXY-CANARY (0 references)
target     prot opt source               destination

Chain cali-from-host-endpoint (1 references)
target     prot opt source               destination

Chain cali-to-host-endpoint (1 references)
target     prot opt source               destination

Chain cali-PREROUTING (1 references)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             /* cali:6BJqBjBC7crtA-7- */ ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere             /* cali:KX7AGNd6rMcDUai6 */ mark match 0x10000/0x10000
cali-from-host-endpoint  all  --  anywhere             anywhere             /* cali:wNH7KsA3ILKJBsY9 */
ACCEPT     all  --  anywhere             anywhere             /* cali:Cg96MgVuoPm7UMRo */ /* Host endpoint policy accepted packet. */ mark match 0x10000/0x10000

Chain cali-POSTROUTING (1 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere             /* cali:NX-7roTexQ3fGRfU */ mark match 0x10000/0x10000
MARK       all  --  anywhere             anywhere             /* cali:nnqPh8lh2VOogSzX */ MARK and 0xfff0ffff
cali-to-host-endpoint  all  --  anywhere             anywhere             /* cali:nquN8Jw8Tz72pcBW */ ctstate DNAT
RETURN     all  --  anywhere             anywhere             /* cali:jWrgvDQ0xEZHmta3 */ /* Host endpoint policy accepted packet. */ mark match 0x10000/0x10000

información relacionada