Como posso configurar o Nginx com um soquete transparente?

Como posso configurar o Nginx com um soquete transparente?

similarmente aessePostagem do blog Cloudflare, estou tentando configurar o Nginx com um soquete transparente (com oIP_TRANSPARENTopção de soquete). Quero fazer isso para implementar um proxy TCP reverso que se ligue efetivamente a todas as portas.

A IP_TRANSPARENTopção de soquete énão tem suporte nativopelo Nginx para ouvir, então estou tentando criar o soquete usando umUnidade de soquete Systemde depois passá-lo para o processo Nginx usando oNGINXvariável de ambiente.

A unidade de soquete é a seguinte (linhas sem importância foram removidas):

[Socket]
ListenStream=127.0.0.1:1234
Transparent=true

[Install]
WantedBy=sockets.target

Minha unidade de serviço Nginx é a seguinte (linhas sem importância foram removidas):

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

E o meu nginx.confé o seguinte (linhas sem importância foram removidas e upstreamé o nome do host upstream para o qual desejo fazer proxy):

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

O Nginx está sendo executado em uma instância de computação do GCP atrás de umbalanceador de carga de passagem internacom endereço IP 10.11.12.13, então adicionei a seguinte regra iptables para redirecionar o tráfego para o soquete 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

Conforme descritoaqui, o GCP instala a rota local para o balanceador de carga, portanto não há necessidade de fazer isso sozinho. Em outras palavras, o seguinte comando retorna RTNETLINK answers: File exists:

ip route add local 10.11.12.13/32 dev lo src 127.0.0.1

No entanto, o seguinte comando curl trava:

curl https://10.11.12.13

A conexão TCP está sendo estabelecida corretamente da perspectiva do curl, porém, ao rastrear o processo de trabalho do Nginx, ele parece estar travado na accept4chamada do sistema.

A execução tcpdumpa partir da instância em que o Nginx está sendo executado mostra o seguinte:

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

Pelo que entendi, isso significa que o cliente está enviando dados, o servidor está reconhecendo isso, mas o cliente não está enviando mais dados, provavelmente porque está esperando uma resposta do servidor que não está recebendo. Por esse motivo, suspeito que o Nginx esteja apenas ignorando os dados enviados pelo cliente.

Espero ter fornecido contexto suficiente para entender o problema. Não tenho muita certeza de para onde ir a partir daqui ou se há algo fundamentalmente errado com o que estou tentando fazer. Qualquer ajuda seria muito apreciada.

Responder1

Eu encontrei a soluçãoaquique era definir a seguinte opção na unidade de serviço Nginx:

[Service]
NonBlocking=true

Presumivelmente, o Nginx assume que esta opção é definida quando o soquete de escuta é criado, de modo que os dados não podem ser lidos se o Systemd passar um soquete sem esta opção definida.

informação relacionada