Прозрачное проксирование одного контейнера docker к другому контейнеру docker

У меня есть пара контейнеров docker, запущенных на главном компьютере, эти контейнеры вместе обеспечивают выполнение моего приложения. Таким образом, для каждой итерации / экземпляра моего приложения требуется запуск пары контейнеров docker. До сих пор я использую параметр --link при запуске второго контейнера, чтобы связать первый контейнер и получить IP-адрес первого контейнера из файла hosts, чтобы использовать его программно.

Теперь мне нужно настроить прозрачный прокси-сервер для второго контейнера docker. таким образом, весь http-трафик (порт 80) второго контейнера должен проходить через порт 8080 первого контейнера.

Первый IP-адрес контейнера: 172.17.0.4 (Имеет прокси-службу, работающую на порту 8080).Второй контейнер IP: 172.17.0.6 (Имеет клиентские инструменты, такие как браузер).Я хотел перенаправить весь http-трафик (порт 80) из 172.17.0.6 в порт 8080 из 172.17.0.4.

то есть)> Трафик до 80 из 172.17.0.4 <--- 8080 из 172.17.0.6

Я попытался добавить правила iptables во второй контейнер для приведенной выше конфигурации. Но ни один из них не сработал.

~# sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 172.17.0.4:8080

Не работает.

~# sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 172.17.0.4:8080

Не работает.

~# sudo iptables -t nat -A POSTROUTING -j MASQUERADE

Итак, мой вопрос в том, как я могу настроить прозрачный прокси-сервер внутри контейнера docker, который может перенаправлять весь трафик указанного порта на порт другого контейнера?

P.S: Если я вручную добавлю настройки прокси-сервера в браузер во втором контейнере. Он работает нормально. Но я хотел установить прозрачный прокси-сервер для всего контейнера, а не только для браузера. таким образом, любой сетевой запрос от любого инструмента внутри второго контейнера будет перенаправлен на прокси-порт первого контейнера.

Я прочитал несколько руководств по обратному проксированию всех контейнеров, работающих вместе, с использованием nginx / HAProxy. Но я хотел настроить отдельный контейнер с его собственным прокси-контейнером в качестве пары.

Спасибо всем вам за то, что нашли время ответить. По сути, то, что я пытаюсь сделать, - это прокси-сервер исходящий/исходящий движение 2-го контейнера (записка: Я есть НЕ пытаюсь прокси-сервер для входящего трафика, поэтому не могу использовать Apache mod_proxy или Nginx proxy_pass. Эти модули работают для входящего трафика). 1-й контейнер запускает прокси-службу на порту 8080.

Как предположил Тьерно, я могу использовать переменные http_proxy и https_proxy ENV для прокси исходящего трафика, но, к сожалению НЕ все приложения / службы, запущенные в вашей операционной системе, учитывают эти переменные среды http_proxy и https_proxy. Существуют приложения, которые принудительно пропускают настройки прокси-сервера. Это причина, по которой я хотел использовать iptables для обеспечения соблюдения правил дорожного движения. Таким образом, ни одно приложение / служба не может пропустить прокси-сервер.

Ошибка, которую я допустил в предыдущих настройках вопроса, заключается в том, что я пытался перенаправить входящий трафик на порт 80 на 8080 прокси-сервера. Поскольку в 1-м контейнере нет никакого входящего трафика, он не будет работать, и это логически неправильно ПРЕДВАРИТЕЛЬНО маршрутизировать/ПЕРЕНАПРАВЛЯТЬ трафик чтобы достичь того, что я искал. Чтобы маршрутизировать исходящий / исходящий трафик, нам нужно использовать ВЫХОДНАЯ цепочка из iptables.

Мое Решение:

Я использовал комбинацию RedSocks с iptables для принудительного использования прокси-сервера для полного исходящего трафика с сервера. Вот конфигурация iptables, которую я использовал:

# Создайте новую цепочку для RedSocks

root# iptables -t nat -N REDSOCKS

# Игнорировать локальные сети и некоторые другие зарезервированные адреса

root# iptables -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURNroot# iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURNroot# iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURNroot# iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURNroot# iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURNroot# iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURNroot# iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURNroot# iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN

# Перенаправить весь http на локальный порт redsocks

root# sudo iptables -t nat -A REDSOCKS -p tcp --dport 80 -j REDIRECT --to-ports 12345

# для трафика https просто замените порт 80 на 443

# Используйте всю цепочку REDSOCKS для всего исходящего трафика на eth0

root# sudo iptables -t nat -A OUTPUT -p tcp -o eth0 -j REDSOCKS

Теперь настройте redsocks на прослушивание локального порта 12345 для входящего трафика и перенаправление его на IP и порт прокси-сервера. Чтобы сделать это редактировать redsocks.conf как это,

redsocks {local_ip = 127.0.0.1;local_port = 12345;ip = 172.17.0.4;port = 8080;type = http-relay;}

просто сохраните конф и перезапустите службу redsocks. Теперь весь исходящий трафик, исходящий из 1-го контейнера, будет принудительно использоваться для использования прокси-сервера. (записка: Я использовал iptables-persistent для сохранения правил при перезагрузках сервера) На самом деле я реализовал то же самое как для http, так и для https-трафика, добавив еще одну строку в конфигурацию iptables. Хотя это не прозрачный прокси-сервер, он выполняет эту работу за меня.

Если у кого-нибудь есть какие-либо другие альтернативные решения этой проблемы, пожалуйста, предложите.

Я думаю, что с помощью $http_proxy env var должен помочь.

Вы можете установить точку входа в свой файл docker (для контейнера #2), чтобы экспортировать переменную env при запуске контейнера. Где-то в вашей точке входа у вас должно быть что-то вроде этого:

export http_proxy=http://$CONATAINER1_PORT_8080_TCP_ADDR:$CONATAINER1_PORT_8080_TCP_PORT

Я не знаю точно, может ли ваш клиент (браузер) использовать переменную $http_proxy env, но должен существовать аналогичный метод. Например, для firefox:

user_pref("network.proxy.http", "$CONATAINER1_PORT_8080_TCP_ADDR");user_pref("network.proxy.http_port", $CONATAINER1_PORT_8080_TCP_PORT);user_pref("network.proxy.type", 1);

Чаевые: использовать printenv на втором контейнере, чтобы узнать, какое имя переменных вы должны использовать в своей точке входа

Насколько я знаю, взаимное связывание - это не то, что есть в docker (информация, обнаруженная во время выполнения о контейнере, перенесенном обратно или переданном обратно прародителю). Вероятно, именно поэтому в большинстве руководств используется третий, общий предок - "прокси".

Если вы готовы использовать фреймворки, такие как fig или weave, которые, как я полагаю, имеют конфигурационные файлы yaml или json, вы, вероятно, сможете настроить это всего с помощью двух взаимных контейнеров.

Если вы хотите иметь третий, то все порты и сантехника могут быть связаны через общего предка для обоих ваших "родственных" контейнеров.