Регистрирует «реальный» IP-адрес клиента в Docker Swarm 1.12 при доступе к сервису

#nginx #docker #load-balancing #docker-swarm

#nginx #docker #балансировка нагрузки #docker-swarm

Вопрос:

У меня есть контейнер nginx, работающий как сервис в Docker Swarm внутри созданной пользователем оверлейной сети. Оба созданы с:

 docker network create --driver overlay proxy
docker service create --name proxy --network proxy -p 80:80 nginx
  

При доступе к сайту nginx через браузер в журнале удаленного доступа nginx адрес регистрируется как 10.255… форматированный адрес, который, как я полагаю, является адресом балансировщика нагрузки Swarm. Вопрос в том, как узнать / зарегистрировать адрес конечного клиента, обращающегося к сайту, а не адрес балансировщика нагрузки.

Ответ №1:

Хороший улов!, Большинство людей, анализирующих nginx access.log и IP-адрес клиента, являются важной частью этого.

В версии docker 1.12.1 проблема существует. nginx будет регистрировать наложенный IP-адрес swarm. Но IP-адрес клиента регистрируется нормально как отдельный контейнер. В качестве обходного пути вы можете reverse proxy указать на службу swarm. Я знаю, что это противоречит High availablity концепции swarm и Self Healing концепции swarm, но, похоже, сейчас это единственное решение.

пример конфигурации: (предположим, что служба swarm прослушивает 8081 на локальном хосте)

 server {
  listen 80 default_server;
  location / {
    proxy_set_header        Host $host;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        X-Forwarded-Proto $scheme;
    proxy_pass          http://localhost:8181;
    proxy_read_timeout  90;
  }
}
  

Дополнительную информацию можно найти по этой проблеме на github.

Другой вариант:

Вы можете использовать сеть в режиме хоста.

 docker service create 
--name nginx 
--network <your overlay network> 
--publish mode=host,target=80,published=80 
--publish mode=host,target=443,published=443 
--replicas 1 
nginx
  

Комментарии:

1. Я хотел бы отметить, что использование этого в производственной среде представляет угрозу безопасности, особенно если ваше приложение использует эти значения для проверки клиента. Заголовки X-Real-IP и X-Forwarded могут быть легко подделаны, и на них не следует полагаться.

2. @tkeeler с помощью haproxy вы можете отменить настройку переменных в http-запросе и установить реальное значение в ответе

3. @c4f4t0r — только если вы ограничиваете все HTTP-запросы haproxy. В противном случае кто-то может отправить запрос непосредственно на сервер, минуя вашу перезапись haproxy.

4. @tkeeler Я думаю, что сервис должен быть доступен миру только с использованием lb, и никто не может использовать один единственный сервер.

Ответ №2:

Итак, способ, которым я работал над этим на данный момент, заключается в использовании mode=host опции для публикации порта и привязки прокси-контейнера к одному узлу следующим образом:

 docker service create 
--name proxy 
--network proxy 
--publish mode=host,target=80,published=80 
--publish mode=host,target=443,published=443 
--constraint 'node.hostname == myproxynode' 
--replicas 1 
letsnginx
  

Комментарии:

1. mode=host опция была добавлена в Docker 1.13, и это то, что я сейчас тоже делаю.

Ответ №3:

Нам пришлось решить проблему идентификации реальных IP-адресов клиентов для нашего производственного развертывания Docker Swarm, работающего https://www.newsnow.co.uk / ( mode=host это был не вариант, так как нам нужно было запустить несколько реплик на нескольких узлах).

Чтобы решить эту проблему, мы создали: https://github.com/newsnowlabs/docker-ingress-routing-daemon , демон, который изменяет маршрутизацию входящей ячеистой сети, чтобы предоставлять истинные IP-адреса клиентов сервисным контейнерам.