¿Cómo puedo configurar Nginx con un socket transparente?

¿Cómo puedo configurar Nginx con un socket transparente?

similar aestePublicación del blog de Cloudflare, estoy intentando configurar Nginx con un socket transparente (con elIP_TRANSPARENTopción de enchufe). Quiero hacer esto para implementar un proxy TCP inverso que se vincule efectivamente a todos los puertos.

La IP_TRANSPARENTopción del enchufe esno soportado de forma nativapor Nginx para escuchar, así que estoy intentando crear el socket usando unUnidad de enchufe systemdy luego pasarlo al proceso Nginx usando elNGINXVariable ambiental.

La unidad de enchufe es la siguiente (se han eliminado las líneas sin importancia):

[Socket]
ListenStream=127.0.0.1:1234
Transparent=true

[Install]
WantedBy=sockets.target

Mi unidad de servicio Nginx es la siguiente (se han eliminado las líneas sin importancia):

[Service]
# Configure Nginx to use the socket inherited from Systemd
Environment=NGINX=3;
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf

Y mi nginx.confes el siguiente (se han eliminado líneas sin importancia y upstreames el nombre de host del host ascendente al que quiero enviar proxy):

stream {
    server {
        proxy_pass upstream:443
        listen 127.0.0.1:1234;
    }
}

Nginx se ejecuta en una instancia informática de GCP detrás de unequilibrador de carga de paso internocon la dirección IP 10.11.12.13, por lo que agregué la siguiente regla de iptables para redirigir el tráfico al socket transparente:

iptables -t mangle -I PREROUTING -d 10.11.12.13/32 -p tcp -j TPROXY --on-port=1234 --on-ip=127.0.0.1

Como se describeaquí, GCP instala la ruta local para el balanceador de carga, por lo que no es necesario que lo haga yo mismo. En otras palabras, el siguiente comando devuelve RTNETLINK answers: File exists:

ip route add local 10.11.12.13/32 dev lo src 127.0.0.1

Sin embargo, el siguiente comando curl se bloquea:

curl https://10.11.12.13

La conexión TCP se está estableciendo correctamente desde la perspectiva de curl, sin embargo, al rastrear el proceso de trabajo de Nginx, parece estar pendiente de la accept4llamada al sistema.

Al ejecutar tcpdumpdesde la instancia en la que se ejecuta Nginx, se muestra lo siguiente:

15.59.51.564902 IP [REDACTED].50028 > 10.11.12.13.443: Flags [S], seq 3519046460, win 65535, options [mss 1320,nop,wscale 6,nop,nop,TS val 3905128064 ecr 0,sackOK,eol], length 0
15.59.51.564973 IP 10.11.12.13.443 > [REDACTED].50028: Flags [S.], seq 2512605282, ack 3519046461, win 28400, options [mss 1420,nop,nop,sackOK,nop,wscale 7], length 0
15.59.51.601898 IP [REDACTED].50028 > 10.11.12.13.443: Flags [.], ack 1, win 4096, length 0
15.59.51.601898 IP [REDACTED].50028 > 10.11.12.13.443: Flags [P.], seq 1:370, ack 1, win 4096, length 369
15.59.51.601898 IP 10.11.12.13.443 > [REDACTED].50028: Flags [.], ack 370, win 231, length 0

Según tengo entendido, esto significa que el cliente está enviando datos, el servidor los reconoce, pero luego el cliente no envía más datos, presumiblemente porque espera una respuesta del servidor que no recibe. Por esta razón, sospecho que Nginx simplemente ignora los datos enviados por el cliente.

Espero haber proporcionado suficiente contexto para comprender el problema. No estoy muy seguro de hacia dónde ir a partir de ahora o si hay algo fundamentalmente incorrecto en lo que estoy tratando de hacer. Cualquier ayuda sería muy apreciada.

Respuesta1

encontré la soluciónaquíque consistía en configurar la siguiente opción en la unidad de servicio Nginx:

[Service]
NonBlocking=true

Presumiblemente, Nginx asume que esta opción está configurada cuando se crea el socket de escucha, por lo que los datos no se pueden leer si Systemd le pasa un socket sin esta opción configurada.

información relacionada