Reenvío de puertos Proxmox a contenedor detrás de NAT

Reenvío de puertos Proxmox a contenedor detrás de NAT

Recientemente compramos un servidor en la subasta de servidores de Hetzner y queremos migrar nuestro servidor raíz anterior. Anteriormente usábamos solo el servidor Windows, pero ahora queremos configurarlo un poco más modular con proxmox.

Tenemos una única dirección IP pública, por lo que optamos por utilizar NAT con una subred interna 10.0.0.0/24.

Los contenedores pueden acceder a Internet, por lo que esto funciona bien.

Pero no podemos conectarnos a servidores que se ejecutan dentro de los contenedores a través de puertos personalizados.

¿Cómo puedo reenviar correctamente los puertos? Probamos el enrutamiento y el reenvío de puertos como se detalla a continuación. Algo salió mal, los puertos no están abiertos, como lo muestran los escaneos de puertos. Actualmente solo hay un firewall en el host de Proxmox, el firewall del host del servidor está deshabilitado, por lo que no sé por qué se debe bloquear el tráfico.

Esta es la configuración actual de la interfaz de red proxmox:

auto lo
iface lo inet loopback

iface lo inet6 loopback

auto eno1
iface eno1 inet static
        address public.ipv4/26
        gateway public.gateway
        up route add -net public.ipv4 netmask 255.255.255.192 gw public.ipv4 dev eno1
# route public.ipv4.range.start/26 via public.ipv4.range.start+1

iface eno1 inet6 static
        address public.ipv6/128
        gateway fe80::1

auto vmbr0
iface vmbr0 inet static
        address 10.0.0.1/24
        bridge-ports none
        bridge-stp off
        bridge-fd 0

        post-up   echo 1 > /proc/sys/net/ipv4/ip_forward
        post-up echo 1 > /proc/sys/net/ipv4/conf/eno1/proxy_arp
        post-up iptables -t nat -A POSTROUTING -s '10.0.0.0/24' -o eno1 -j MASQUERADE
        post-down iptables -t nat -D POSTROUTING -s '10.0.0.0/24' -o eno1 -j MASQUERADE
        post-up iptables -t nat -A PREROUTING -i vmbr0 -p tcp --dport 28967 -j DNAT --to 10.0.0.4:28967
        post-up iptables -t nat -A PREROUTING -i vmbr0 -p udp --dport 28967 -j DNAT --to 10.0.0.4:28967
        post-down iptables -t nat -D PREROUTING -i vmbr0 -p tcp --dport 28967 -j DNAT --to 10.0.0.4:28967
        post-down iptables -t nat -D PREROUTING -i vmbr0 -p udp --dport 28967 -j DNAT --to 10.0.0.4:28967

iface vmbr0 inet6 static
        address public.ipv6+1/64

iptables -L -t nat:

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DNAT       tcp  --  anywhere             anywhere             tcp dpt:28967 to:10.0.0.4:28967
DNAT       udp  --  anywhere             anywhere             udp dpt:28967 to:10.0.0.4:28967

Chain INPUT (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         
MASQUERADE  all  --  10.0.0.0/24          anywhere   

La interfaz eno1 fue generada automáticamente por su script de instalación. Agregamos el puente y el NAT, etc.

Configuración del cliente:

auto lo
iface lo inet loopback
iface lo inet6 loopback

auto eth0
iface eth0 inet static
        address 10.0.0.4/24
        gateway 10.0.0.1

El contenedor del cliente actualmente no tiene firewall.

Tenemos relativamente poca experiencia con la creación de redes dentro de un host KWM, por lo que cualquier ayuda será muy apreciada.

Respuesta1

Descubrimos algo y lo publicaré aquí en caso de que sea útil para alguien. (Descargo de responsabilidad: elaboramos esto después de horas de prueba y error, es posible que solo funcione para nuestro proveedor de alojamiento. No soy un experto en redes Linux de ninguna manera).

/etc/network/interfaces:

source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback
iface lo inet6 loopback

auto eno1
iface eno1 inet static
    address <hostpublicip>/26
    gateway <hostgateway>
    up route add -net <hostgateway-1> netmask 255.255.255.192 gw <hostgateway> dev eno1
    post-up echo 1 > /proc/sys/net/ipv4/ip_forward # add this line

auto vmbr0
iface vmbr0 inet static
    address 10.0.0.1/24
    bridge-ports none
    bridge-stp off
    bridge-fd 0

    post-up iptables -t nat -A POSTROUTING -s '10.0.0.0/24' -o eno1 -j MASQUERADE
    post-down iptables -t nat -D POSTROUTING -s '10.0.0.0/24' -o eno1 -j MASQUERADE
    post-down iptables -t nat -F
    post-up   iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1
    post-down iptables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1

La interfaz eno1 ya fue configurada por el script de instalación de nuestro proveedor de hosting (Hetzner), agregamos la post-uplínea para habilitar el reenvío de IP en el arranque.
Creamos la interfaz vmbr0 en proxmox y configuramos una dirección de subred; puede elegir cualquier rango de direcciones que desee. Optamos por 10.0.0.0/24. Luego debe cambiar la entrada del archivo de acuerdo con nuestro ejemplo anterior. Las líneas son obligatorias tal como están (excepto la IP, por supuesto). Si hay interfaces ipv6, déjelas en paz.

Ahora, cuando cree contenedores/VM, debe configurar la dirección IPv4 en estática y elegir cualquiera que se ajuste a su subrango ( 10.0.0.xxx/24), y configurar la puerta de enlace como 10.0.0.1.

Todos los reenvíos de puertos están definidos en el archivo /etc/network/interfaces.d/port_forwards(debe ser creado por el usuario, todos los archivos en esa ruta se cargan en el archivo principal anterior con la sourcelínea). La dirección IP en el puerto reenviado es la dirección IP que asignó al contenedor durante la creación.

# your network interface
iface vmbr0 inet static
    # minecraft container as example
    post-up port_forward -t 10.0.0.201 -p tcp -d 22     -s 22201 # external port 22201 for direct ssh to container
    post-up port_forward -t 10.0.0.201 -p tcp -m -d 25566,25576
    post-up port_forward -t 10.0.0.201 -p udp -m -d 25566,25576
    # follow with all the port forwards you need

Con un script de reenvío de puertos personalizado llamado port_forwardque simplemente abrevia los iptablescomandos para mantener el archivo legible. Este archivo debe colocarse o vincularse /bin/para que se cargue antes de montar la partición del usuario.

#!/bin/bash
# abbr for iptables dnat

usage() { echo "Usage: $0 -t <container_ip> -p <tcp/udp/etc> -d <port> [-s <external port if different>] [-m flag if ports will be comma separated list, not compatible with -s]" 1>&2; exit 0; }

while getopts t:p:d:s::m flag
do
    case "${flag}" in
        t) target_ip=${OPTARG};;
        p) protocoll=${OPTARG};;
        d) dest_port=${OPTARG};;
        s) src_port=${OPTARG};;
        m) multiport=1 ;;
        *) usage ;;
    esac
done

if [[ -z "$src_port" ]]; then
    src_port="$dest_port"
fi

if [[ "$multiport" -eq 1 ]]; then
    iptables -t nat -A PREROUTING -i eno1 -p "$protocoll" -m multiport --dports "$dest_port" -j DNAT --to "$target_ip"
else
    iptables -t nat -A PREROUTING -i eno1 -p "$protocoll" --dport "$src_port" -j DNAT --to "$target_ip":"$dest_port"
fi

Cada vez que se cambian los archivos, es necesario restablecer iptables de la siguiente manera:

iptables --flush
iptables -t nat --flush
iptables --delete-chain
ifreload --all

Esto también se puede poner en un archivo, le asignamos un nombre reload_networky lo colocamos en la /usr/local/bin/carpeta para acceder como un comando.

información relacionada