Назад | Перейти на главную страницу

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

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

Теперь мне нужно настроить прозрачный прокси для второго контейнера докеров. так что весь трафик 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

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

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

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

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

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

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

Мое решение:

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

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

root# iptables -t nat -N REDSOCKS

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

root# iptables -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURN
root# iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
root# iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
root# iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
root# iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
root# iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
root# iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN
root# 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 должен помочь.

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

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

Я не знаю точно, может ли ваш клиент (браузер) использовать переменную $ http_proxy env var, но должен существовать аналогичный метод. Например, для 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 во втором контейнере, чтобы узнать, какое имя переменных вы должны использовать в своей точке входа

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

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

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