Как настроить 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 зависает:

curl https://10.11.12.13

С точки зрения curl соединение TCP устанавливается правильно, однако при отслеживании рабочего процесса Nginx оно, похоже, зависает на accept4системном вызове.

Запуск tcpdumpс экземпляра, на котором работает Nginx, показывает следующее:

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 передаст ему сокет без установленной этой опции.

Связанный контент