Вопрос или проблема
На этой неделе я изучал сетевые технологии, но у меня все еще есть одна, казалось бы, значительная пробел в понимании, связанная с тем, какие IP-адреса доступны с моего хоста и как.
В частности, ip -br addr
показывает:
lo UNKNOWN 127.0.0.1/8 ::1/128
tunl0@NONE DOWN
sit0@NONE DOWN
ip6tnl0@NONE DOWN
eth0@if15 UP 198.19.249.109/24 metric 1024 fd07:b51a:cc66:0:439:fcff:fe3f:27d6/64 fe80::439:fcff:fe3f:27d6/64
docker0 DOWN 172.17.0.1/16 fe80::acc7:7cff:fe73:5421/64
br-140e1fbca70a UP 172.18.0.1/16 fe80::34c3:10ff:fe55:2464/64
vethbf1bfcc@if5 UP fe80::38fd:c6ff:fe37:f54/64
veth7e8fb76@if5 UP fe80::689e:8bff:fe81:d8c3/64
А ip route
показывает:
default via 198.19.249.1 dev eth0 proto dhcp src 198.19.249.109 metric 1024
0.250.250.200 via 198.19.249.1 dev eth0 proto dhcp src 198.19.249.109 metric 1024
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
172.18.0.0/16 dev br-140e1fbca70a proto kernel scope link src 172.18.0.1
198.19.249.0/24 dev eth0 proto kernel scope link src 198.19.249.109 metric 1024
198.19.249.1 dev eth0 proto dhcp scope link src 198.19.249.109 metric 1024
А ip neigh
показывает:
198.19.249.1 dev eth0 lladdr da:9b:d0:54:e0:02 STALE
172.18.0.3 dev br-140e1fbca70a lladdr fe:50:d0:de:5a:ce STALE
fe80::d84c:3aff:fef1:e382 dev eth0 lladdr da:9b:d0:54:e0:02 router STALE
Более того, docker network inspect ..._..._default
говорит, что сеть имеет шлюз 172.18.0.1
, с двумя подключенными контейнерами, включая 172.18.0.3
.
iptables
содержит только стандартные правила Docker.
Вопрос:
Я выполнил ip route del 172.18.0.0/16
и удалил эту запись из таблицы маршрутизации.
Почему я больше не могу получить доступ к контейнеру Docker?
Контейнер 172.18.0.3
работает локально на моем компьютере, поэтому я ожидал, что смогу получить к нему доступ, если как-то настрою правила iptables
. Это не так?
Контейнер работает как отдельное “сетевое пространство имен”. Даже если он физически находится на вашем компьютере, он имеет свою собственную изолированную сетевую конфигурацию – свои собственные интерфейсы, свои собственные маршруты, свои собственные iptables, даже собственное представление ‘localhost’ – по всем параметрам он ведет себя так, как будто это действительно совершенно отдельная машина от хоста.
(Ядро хоста отслеживает, какие процессы находятся в каком пространстве имен; такие инструменты, как lsns
, unshare
и nsenter
могут быть использованы для изучения.)
Единственная связь между этими двумя пространствами имен – это пара интерфейсов ‘veth’, которые действуют как два конца виртуального Ethernet-кабеля (они всегда создаются парами, и затем одна из них назначается пространству имен контейнера, а другая остается на стороне хоста).
Интерфейс veth на стороне хоста может быть подключен к мосту или нет, в зависимости от ваших предпочтений – мост создается для удобства, это как подключение машин через коммутатор по сравнению с подключением их с использованием множества кабелей один-к-одному – но в любом случае, IP-адреса, маски подсетей и маршруты должны быть настроены так, как если бы вы действительно подключали отдельные машины.
Так что нет, вы не можете получить доступ к этому адресу, просто настроив правила iptables. Здесь нет какого-то специального пути, который бы вступал в действие до таблицы маршрутизации (в действительности вся суть сетевых пространств имен в том, чтобы такого пути не существовало), поэтому, если у вас нет маршрута к нему, вы не можете отправлять пакеты.
Не все контейнеры так отделены, однако; у Docker есть режим “сетевой хост”, который не использует сетевое пространство имен, и контейнер просто разделяет IP-адрес хоста.
.
Ответ или решение
Введение в Docker и сетевые пространства имён представляет собой сложную, но весьма интересную тему. Важно понимать, что Docker обеспечивает контейнеры изолированными средами, включая отдельные сетевые пространства имен, которые действуют как отдельные виртуальные машины. В дальнейшем обсудим, как это повлияет на вашу ситуацию и каким образом можно получить доступ к контейнеру без использования мостового интерфейса.
Теория
Docker по умолчанию создаёт изолированные сетевые пространства имен для каждого контейнера. Это включает в себя создание пары интерфейсов "veth" (virtual ethernet) по принципу виртуального кабеля, один конец которого остаётся в пространстве хоста, а другой перемещается в пространство контейнера. Сетевые настройки, такие как IP-адресация, маршрутизация, и сетевые правила (iptables), выполняются отдельность для каждого пространства имен.
Маршрутизация играет критическую роль в соединении между сетями. Без настроенной маршрутизации, ваш хост не сможет «видеть» контейнер в изолированном пространстве. Удалив маршрут 172.18.0.0/16
в вашей системе, вы фактически удалили путь, по которому могут передаваться пакеты к сети, в которой находится контейнер, что и привело к потере связи с ним.
Пример
Рассмотрим ваш случай. Вы имели возможность связаться с контейнером через сеть с адресом 172.18.0.3
, пока маршрут 172.18.0.0/16
действовал в вашей системе. Однако с удалением этой записи, маршрут к контейнеру исчез и попытки доступа к 172.18.0.3
через IP-адрес стали невозможными. Ваша система теперь не знает, как отправлять пакеты в сеть контейнера, так как отсутствует соответствующая запись в таблице маршрутов.
Применение
Для восстановления возможности доступа к контейнеру без использования мостового интерфейса, вам понадобятся следующие шаги:
-
Проверить текущие соединения и маршрутизацию: Используйте команды, такие как
ip route
иip addr
, чтобы удостовериться в своей текущей конфигурации сети. -
Добавление маршрута вручную: Его можно восстановить командой
ip route add 172.18.0.0/16 dev YOUR_INTERFACE
, гдеYOUR_INTERFACE
— это интерфейс, к которому подключен контейнер (например,docker0
или другой соответствующий интерфейс). -
Настройка правил iptables: Если это необходимо, настройте правила iptables, которые позволят пакетам достигать контейнера, обеспечивая при этом безопасность вашей сети.
-
Используйте host network: Альтернативной вкладкой может быть использование сетевого режима Docker
host
, который отключает изолированное сетевое пространство. В этом режиме контейнеры делят IP адрес с хостом и могут оперировать как процессы на самой машине.
Не стоит забывать, что правильная настройка вашей сети и маршрутизации критически важна для поддержания функциональности и безопасности системы. Понимание того, что контейнеры действуют в отдельных, изолированных сетевых пространствах, также позволит вам более эффективно управлять ними и избегать проблем с доступом.