투명 소켓으로 Nginx를 어떻게 설정합니까?

투명 소켓으로 Nginx를 어떻게 설정합니까?

마찬가지로이것Cloudflare 블로그 게시물에서 투명 소켓을 사용하여 Nginx를 설정하려고 합니다(IP_TRANSPARENT소켓 옵션). 모든 포트에 효과적으로 바인딩하는 역방향 TCP 프록시를 구현하기 위해 이 작업을 수행하고 싶습니다.

소켓 IP_TRANSPARENT옵션은기본적으로 지원되지 않음청취를 위해 Nginx가 작성했기 때문에 다음을 사용하여 소켓을 생성하려고 합니다.시스템화된 소켓 유닛그런 다음 다음을 사용하여 Nginx 프로세스에 전달합니다.NGINX환경 변수.

소켓 장치는 다음과 같습니다(중요하지 않은 줄은 제거되었습니다).

[Socket]
ListenStream=127.0.0.1:1234
Transparent=true

[Install]
WantedBy=sockets.target

내 Nginx 서비스 단위는 다음과 같습니다(중요하지 않은 줄은 제거되었습니다):

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

nginx.conf내용은 다음과 같습니다(중요하지 않은 줄은 제거되었으며 upstream프록시하려는 업스트림 호스트의 호스트 이름입니다).

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

Nginx는 GCP 컴퓨팅 인스턴스에서 실행되고 있습니다.내부 패스스루 로드 밸런서IP 주소가 10.11.12.13이므로 트래픽을 투명 소켓으로 리디렉션하기 위해 다음 iptables 규칙을 추가했습니다.

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

설명한대로여기, GCP는 부하 분산기를 위한 로컬 경로를 설치하므로 직접 수행할 필요가 없습니다. 즉, 다음 명령은 다음을 반환합니다 RTNETLINK answers: File exists.

ip route add local 10.11.12.13/32 dev lo src 127.0.0.1

그러나 다음 컬 명령이 중단됩니다.

curl https://10.11.12.13

컬의 관점에서 TCP 연결이 올바르게 설정되고 있지만 Nginx 작업자 프로세스를 추적할 때 시스템 accept4호출이 중단된 것처럼 보입니다.

tcpdumpNginx가 실행 중인 인스턴스에서 실행하면 다음이 표시됩니다.

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

내가 이해하는 바에 따르면 이는 클라이언트가 데이터를 보내고 있고 서버가 이를 승인하고 있지만 클라이언트가 더 이상 데이터를 보내지 않는다는 것을 의미합니다. 아마도 서버로부터 수신되지 않는 응답을 기대하고 있기 때문일 것입니다. 이런 이유로 나는 Nginx가 클라이언트가 보낸 데이터를 무시하고 있다고 의심합니다.

문제를 이해하는 데 충분한 맥락을 제공했으면 좋겠습니다. 여기서 어디로 가야할지, 내가 하려는 일에 근본적으로 잘못된 것이 있는지 잘 모르겠습니다. 어떤 도움이라도 대단히 감사하겠습니다.

답변1

해결책을 찾았습니다여기Nginx 서비스 단위에서 다음 옵션을 설정하는 것입니다.

[Service]
NonBlocking=true

아마도 Nginx는 청취 소켓이 생성될 때 이 옵션이 설정되어 있다고 가정하므로 Systemd가 이 옵션이 설정되지 않은 소켓에 데이터를 전달하면 데이터를 읽을 수 없습니다.

관련 정보