Вопрос или проблема
Я использую nginx для мультиплексирования SSH и HTTPS, используя этот файл /etc/nginx/nginx.config
:
stream {
upstream ssh {
server 127.0.0.1:22;
}
upstream https {
server 127.0.0.1:8443;
}
map $ssl_preread_protocol $upstream {
default ssh;
"TLSv1.2" https;
"TLSv1.3" https;
"TLSv1.1" https;
"TLSv1.0" https;
}
server {
listen 443;
proxy_pass $upstream;
ssl_preread on;
}
}
Трафик успешно перенаправляется, но имеет побочный эффект: все подключения выглядят как идущие с 127.0.0.1 как для SSH, так и для HTTPS:
$ last
jason pts/3 127.0.0.1 Wed Feb 19 22:25 - 22:25 (00:00)
...
$ tail -1 /var/log/nginx/access.log
127.0.0.1 - - [19/Feb/2025:20:31:36 +0100] "GET /favicon.ico HTTP/1.1" 200 1406 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, как Gecko) Chrome/132.0.0.0 Safari/537.36"
Я попробовал прозрачное проксирование, изменив файл /etc/nginx/nginx.config
следующим образом:
user root; # было: www-data
...
server {
listen 443;
proxy_bind $remote_addr transparent;
proxy_pass $upstream;
ssl_preread on;
}
...
Однако это вызывает зависание и тайм-аут входящих ssh и https соединений. Я пытался отключить брандмауэр ufw
, но это не дает эффекта.
Документация proxy_bind
не очень конкретна по поводу того, что нужно делать: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_bind
Для работы этого параметра обычно необходимо запускать рабочие процессы nginx с привилегиями суперпользователя. В Linux это не требуется (1.13.8), поскольку, если задан параметр transparent, рабочие процессы наследуют возможность CAP_NET_RAW от основного процесса. Также необходимо настроить таблицу маршрутизации ядра для перехвата сетевого трафика от проксируемого сервера.
Я изменил на user root;
и запускаю nginx через sudo systemctl start nginx
, так что, вероятно, с привилегиями суперпользователя я разобрался, верно?
Как мне “настроить таблицу маршрутизации ядра для перехвата сетевого трафика от проксируемого сервера”? Обратите внимание, что я в данный момент использую ufw
для настройки iptables, если это имеет значение.
Ответ или решение
Конфигурация прозрачного прокси с использованием nginx может быть сложной задачей, особенно когда необходимо правильно настроить iptables и маршрутизацию ядра для сетевого трафика. Рассмотрим подробнее вашу ситуацию.
Теория
Когда вы используете nginx для проксирования SSH и HTTPS с помощью proxy_bind transparent
, цель состоит в том, чтобы конечные серверы (здесь это SSH и HTTPS серверы на локальной машине) видели исходные IP-адреса клиентов, а не IP-адрес прокси (127.0.0.1 в вашем случае). Для этого необходимо выполнить несколько важных шагов.
-
Прозрачное Проксирование: Во-первых, более чем одной прослойке программного обеспечения необходимо поддерживать прозрачное проксирование. Nginx с
proxy_bind transparent
позволяет ему перенаправлять исходные IP-адреса дальше, но это также требует поддержки на уровне системы и сети. -
Настройка iptables: Вам необходимо настроить правила iptables для изменения исходного IP-адреса в пакетах, проходящих через ваш сервер. Это включает использование маркеров, таких как TPROXY.
-
Маршрутизация ядра: На уровне ядра Linux, необходимы изменения в таблице маршрутизации, чтобы перехватывать и изменять трафик, проходящий через ваш сервер.
Пример
Рассмотрим практическую конфигурацию и шаги.
-
Привилегии и права доступа:
- Убедитесь, что nginx работает от имени root, или что он имеет необходимые права (например,
CAP_NET_RAW
).
- Убедитесь, что nginx работает от имени root, или что он имеет необходимые права (например,
-
Настройка iptables:
-
Вам нужно использовать механизм
mangle
в iptables. Вот пример правил:iptables -t mangle -N DIVERT iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT iptables -t mangle -A DIVERT -j MARK --set-mark 1 iptables -t mangle -A DIVERT -j ACCEPT ip rule add fwmark 1 lookup 100 ip route add local 0.0.0.0/0 dev lo table 100
- Эти правила позволяют маркеровать трафик для локальной маршрутизации.
-
-
Настройки sysctl:
- Проверьте, что у вас настроены правильные параметры sysctl:
sysctl -w net.ipv4.ip_forward=1 sysctl -w net.ipv4.conf.all.route_localnet=1
- Проверьте, что у вас настроены правильные параметры sysctl:
Применение
Применив все шаги, вы обеспечиваете, что nginx может действовать как прозрачный прокси. Однако ошибки могут возникнуть, если какой-то из шагов выполнен неправильно.
-
Проверка nginx:
- После всех изменений перезапустите nginx и убедитесь, что он работает без ошибок конфигурации.
-
Журналирование и диагностика:
- Воспользуйтесь логами nginx и системными журналами, такими как
journalctl
, для отслеживания потенциалальных ошибок.
- Воспользуйтесь логами nginx и системными журналами, такими как
-
Тестирование:
- Проверьте, что конечные серверы теперь видят правильные удаленные IP-адреса.
Заключение
Ваша конфигурация включает много движущихся частей, и каждая из них должна работать корректно. Если шаги выполнены верно, nginx сможет поддерживать прозрачное проксирование без изменения IP-адресов исходных клиентов. Возможные проблемы могут быть связаны с неправильно установленными правилами iptables или ошибками маршрутизации. Если вы используете ufw
, убедитесь, что он не конфликтует с напрямую настроенными правилами iptables, так как это может вызвать неожиданные поведения. Рекомендуется отключить ufw
после настройки вышеописанных правил для тестирования корректности работы, или внести необходимые изменения в конфигурацию ufw
, чтобы они не конфликтовали.