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

Как получить настоящий IP-адрес клиента для службы, работающей внутри докера

Мой сценарий: я хотел бы, чтобы мои службы на основе докеров знали, какой IP вызывает их из Интернета (требование моего приложения).

Я использую облачный VPS, debian jessie, с докером 1.12.2.

я использую nc в подробном режиме, чтобы открыть порт 8080.

docker run --rm -p "8080:8080" centos bash -c "yum install -y nc && nc -vv -kl -p 8080"

Скажем, у VPS есть домен example.com, и с другой моей машины, у которой, скажем, есть IP dead:::::beef Я звоню

nc example.com 8080

В сервер говорит:

Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Listening on :::8080
Ncat: Listening on 0.0.0.0:8080
Ncat: Connection from 172.17.0.1.
Ncat: Connection from 172.17.0.1:49799.

172.17.0.1 на сервер в локальной сети и, конечно, не имеет никакого отношения к моему клиенту. По факту:

docker0   Link encap:Ethernet  HWaddr ....
          inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0

Если я запустил контейнер в режиме сети хоста

docker run --rm --net=host -p "8080:8080" centos bash -c "yum install -y nc && nc -vv -kl -p 8080"

и снова позвони на мой сервер

nc example.com 8080

Получаю ожидаемый результат:

Ncat: Connection from dead:::::beef.
Ncat: Connection from dead:::::beef:55650.

Мои вопросы:

Согласно документация, драйвер по умолчанию (т.е. когда вы не указываете --net=host в docker run, это bridge сетевой драйвер.

Дело не в «маскировке» IP-адресов докерами, а в том, как bridged и host сетевые режимы различаются.

Что касается Docker, мостовая сеть использует программный мост, который позволяет контейнерам, подключенным к одной и той же мостовой сети, обмениваться данными, обеспечивая изоляцию от контейнеров, которые не подключены к этой сети моста. Драйвер моста Docker автоматически устанавливает правила на главном компьютере, чтобы контейнеры в разных сетях моста не могли напрямую взаимодействовать друг с другом.

Docker создает изолированную сеть, чтобы каждый контейнер в мостовой сети мог обмениваться данными, в вашем случае это docker0. Таким образом, по умолчанию контейнеры на вашем хосте докеров обмениваются данными в этой сети.

Как вы, возможно, уже догадались, да 172.17.0.1 это маршрут по умолчанию на docker0 сеть, но он не действует как маршрутизатор, который пересылает пакеты к месту назначения, поэтому вы видите его как источник вывода netcat.

Фактически, вы можете проверить это, запустив ss -tulnp на вашем докер-хосте. Вы должны увидеть, что процесс, прослушивающий порт 8080, - это докер.

С другой стороны, используя хозяин сетевой драйвер означает, что между контейнером и хостом нет изоляции. Вы можете проверить это, запустив ss -tulnp на вашем докер-хосте; вы должны увидеть, как процесс прослушивает сокет вместо докера (в вашем случае вы должны увидеть nc).