Saltar al contenido

¿Cómo redirigir las solicitudes en el puerto 80 a localhost: 3000 usando nftables?

Nuestro team de expertos pasados varios días de trabajo y de juntar de datos, hemos dado con los datos necesarios, esperamos que te resulte útil en tu proyecto.

Solución:

Intentaré abordar y completar la propia respuesta de trabajo de OP y más comentarios, que incluyen algunas preguntas restantes:

  • por que es net.ipv4.conf.eth0.route_localnet=1 ¿necesario?
  • ¿Por qué es necesario permitir el puerto 3000 eth0 en vez de lo?

y también abordará un problema menor de seguridad mientras lo hace.

Primero, aquí hay un esquema obligatorio sobre el flujo de paquetes en Netfilter y redes generales:

Flujo de paquetes en Netfilter y redes generales

Este esquema se hizo con iptables en mente, pero nftables puede (y lo hace en la mayoría de los conjuntos de reglas predeterminados) usar los mismos ganchos en los mismos lugares.

Cuando un paquete llega a la capa de red (capa 3 de IP), es manejado por varios subsistemas. Normalmente, solo habría la pila de enrutamiento, pero aquí Netfilter proporciona ganchos para sí mismo (conntrack, incluido el manejo de NAT después del paquete inicial) o para nftables.

Netfilter (conntrack) o nftables no se preocupan por el enrutamiento (a menos que, por ejemplo, nftables utiliza expresiones especializadas relacionadas con el enrutamiento), lo dejan a la pila de enrutamiento: manipulan direcciones y puertos y nftables luego verifica las propiedades disponibles como interfaces, direcciones y puertos.

Entonces:

  • un paquete en una nueva conexión (por lo que también atraviesa ip nat prerouting) llega de eth0 con (por ejemplo) la dirección de origen 192.0.2.2 y el puerto 45678 de destino a la dirección 192.168.0.1 y el puerto 80 (o 443).

  • los ip nat preroutingdnat la regla coincide y dice netfilter (su conntrack subsistema) para cambiar la dirección de destino a 127.0.0.1 y el puerto de destino a 3000. Esto no cambia ninguna otra propiedad del paquete. En particular, el paquete todavía llegó de eth0.

  • la pila de enrutamiento (decisión de enrutamiento en el esquema) no depende de Netfilter, por lo que lógicamente se mantiene independiente de él y no tiene conocimiento de la alteración anterior. Ahora tiene que manejar un paquete de 192.0.2.2 y un destino 127.0.0.1.

    Esto es una anomalía: permitiría que un rango de direcciones reservado para bucle invertido se vea “en Internet”, como se indica en RFC 1122:

    (gramo) 127,

    Dirección de loopback del host interno. Las direcciones de este formulario NO DEBEN aparecer fuera de un host.

    que se maneja explícitamente en el kernel de Linux pila de enrutamiento: trátalo como destino marciano (es decir, descarta el paquete), a no ser que relajado usando route_localnet=1 en la interfaz relacionada. Por eso para este caso específico net.ipv4.conf.eth0.route_localnet=1 se debe establecer.

  • del mismo modo, el siguiente nftables regla, esta vez desde el gancho de entrada del filtro, ve un paquete con la interfaz de entrada todavía eth0 pero con el puerto de destino ahora 3000. Por lo tanto, debe permitir el puerto de destino 3000, y ya no tiene que permitir que 80 (o 443) lo acepten. Por tanto, la regla debería acortarse a:

    iifname "eth0" tcp dport 4489, 3000 counter accept
    

    porque nunca verá paquetes de eth0 con el puerto tcp de destino 80 o 443: todos se cambiaron al puerto 3000 en el enlace previo de enrutamiento nat anterior. Además, en aras de la explicación, suponiendo que se vieran dichos paquetes, se aceptarían, pero como no habría un proceso de escucha en los puertos 80 o 443 (está escuchando en el puerto 3000), la pila tcp emitiría un reinicio de TCP para rechazar la conexión.

    También mientras el pila de enrutamiento refuerza algunas relaciones entre 127.0.0.0/8 y el lo interfaz (más relajado con route_localnet=1), como se dijo antes, esto no concierne netfilter o nftables que no les importa nada sobre el enrutamiento. Además, si tal fuera el caso, para el aporte interfaz esta sería la fuente dirección que no cambió, no la destino dirección que se relacionaría con el producción interfaz que ni siquiera tiene un significado real en el aporte sendero: oif o oifname no se puede utilizar aquí. El mero hecho de estar en el gancho de entrada de filtro ya significa que el paquete evaluado llega al host para un local proceso, como se ve en el esquema.

    ACTUALIZACIÓN: En realidad, la regla dada anteriormente debería cambiarse más por razones de seguridad: se permite el puerto 3000, pero no solo para el destino 127.0.0.1. Una conexión a 192.168.0.1:3000 puede recibir un TCP RST que sugiere que hay algo especial aquí, en lugar de no obtener ninguna respuesta. Para abordar este caso:

    • o use esto (que incluye una segunda regla de aspecto muy extraño):

      iifname "eth0" tcp dport 4489 counter accept
      iifname "eth0" ip daddr 127.0.0.1 tcp dport 3000 counter accept
      

      que, porque route_localnet=1, aún permite que un sistema modificado en la misma LAN 192.168.0.0/24 acceda al servicio sin usar NAT en absoluto, enviando paquetes con 127.0.0.1 en el cable, incluso si probablemente no haya ganancia al hacer esto. Por ejemplo, otro sistema Linux, con estos 4 comandos:

      sysctl -w net.ipv4.conf.eth0.route_localnet=1
      ip address delete 127.0.0.1/8 dev lo # can't have 127.0.0.1 also local
      ip route add 127.0.0.1/32 via 192.168.0.1 # via, that way no suspicious ARP *broadcast* for 127.0.0.1 will be seen elsewhere.
      socat tcp4:127.0.0.1:3000 -
      
    • o en cambio, también protegiendo para el caso anterior, mucho más genérico y preferido:

      iifname "eth0" tcp dport 4489 counter accept
      ct status dnat counter accept
      
      • mantiene el puerto 4489 / tcp no relacionado permitido como antes
      • ct status dnat coincide si el paquete fue previamente DNATed por el host: por lo tanto, aceptará cualquier alteración previa sin tener que reafirmar explícitamente qué puerto era (aún es posible indicarlo también o cualquier otra cosa para limitar aún más el alcance de lo que se acepta): ahora el valor del puerto 3000 además ya no es necesario que se indique explícitamente.
      • por lo tanto, tampoco permitirá conexiones directas al puerto 3000 ya que este caso no habría sido DNAT.
  • solo para estar completo: lo mismo sucede en (no del todo) orden inverso para la salida y las respuestas. net.ipv4.conf.eth0.route_localnet=1 permite que los paquetes salientes generados inicialmente desde 127.0.0.1 a 192.0.2.2 no se traten como fuentes marcianas (=> caída) en la ruta de salida decisión de enrutamiento, antes de que tengan la oportunidad de ser “des-DNATed” de nuevo a la dirección de origen prevista original (192.168.0.1) por netfilter (conntrack) solo.


Por supuesto, usando route_localnet=1 es una especie de seguridad relajante (no es realmente relevante con las reglas de firewall adecuadas, pero no todos los sistemas usan un firewall) y requiere conocimientos asociados sobre su uso (por ejemplo: copiar el nftables El conjunto de reglas solo en otro lugar ya no funcionará sin el route_localnet=1 configuración).

Ahora que los problemas de seguridad se abordaron en las explicaciones anteriores (consulte “ACTUALIZAR”), si la aplicación pudiera escuchar 192.168.0.1 (o cualquier dirección) en lugar de solo 127.0.0.1, se podría realizar una configuración equivalente sin habilitar route_localnet=1, cambiando en ip nat prerouting:

iif eth0 tcp dport  80, 443  counter dnat 127.0.0.1:3000

para:

iif eth0 tcp dport  80, 443  counter dnat to 192.168.0.1:3000

o simplemente para:

  iif eth0 tcp dport  80, 443  counter redirect to :3000

que no difieren mucho: redirect cambia el destino a la dirección IP principal del host en la interfaz eth0 que es 192.168.0.1, por lo que la mayoría de los casos se comportarían igual.

Más adelante puedes encontrar las notas de otros desarrolladores, tú asimismo tienes la opción de dejar el tuyo si te gusta.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *