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