similarmente aessePostagem do blog Cloudflare, estou tentando configurar o Nginx com um soquete transparente (com oIP_TRANSPARENT
opção de soquete). Quero fazer isso para implementar um proxy TCP reverso que se ligue efetivamente a todas as portas.
A IP_TRANSPARENT
opçã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 oNGINX
variá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 accept4
chamada do sistema.
A execução tcpdump
a 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.