Не слишком запутывайтесь в настоящем и не беспокойтесь слишком сильно о будущем. Когда вы что-то испытываете, пейзаж перед вами уже не тот, что раньше. —— Харуки Мураками
В обычных обстоятельствах при запуске контейнера в Docker этот контейнер может автоматически получить доступ к внешней сети. Сегодня давайте посмотрим, как контейнер в Docker обращается к внешней сети.
По умолчанию, когда ничего не настроено, докер будет использоваться для каждого созданного контейнера Bridge Network
тип сети, в то время как docker Используется по умолчанию bridge
сетевой драйвер
Это можно проверить с помощью следующей команды
liruilonger@cloudshell:~$ docker network inspect bridge --format='{{.Driver}}'
bridge
liruilonger@cloudshell:~$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "cd77486c39955f3d2369fe32e1f5b9b65d81c1a07bb677b085cec72b8fb52440",
"Created": "2024-03-26T13:03:43.742084591Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1460"
},
"Labels": {}
}
]
liruilonger@cloudshell:~$
liruilonger@cloudshell:~$ docker info | grep -i network
Network: bridge host ipvlan macvlan null overlay
Теперь запускаем контейнер nginx
liruilonger@cloudshell:~$ docker run -d -p 2024:80 --name mynginxs nginx
704b4427a24d56e6a2cc999fcf95125c73e665cb90029b191febc405f90a789a
liruilonger@cloudshell:~$
Доступ к маппинг-порту нормальный
В то же время доступ к внешним веб-сайтам внутри контейнера является нормальным.
liruilonger@cloudshell:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
704b4427a24d nginx "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 0.0.0.0:2024->80/tcp mynginxs
liruilonger@cloudshell:~$ docker exec -it 704b4427a24d bash
root@704b4427a24d:/# curl baidu.com
<html>
<meta http-equiv="refresh" content="0;url=http://www.baidu.com/">
</html>
root@704b4427a24d:/#
Теперь давайте посмотрим на доступ к контейнеру. baidu.com
Как это произошло? Перед этим мне нужно взглянуть на конфигурацию сети текущего контейнера.
liruilonger@cloudshell:~$ docker inspect 704b4427a24d
Чтобы иметь доступ к внешней сети, необходима следующая конфигурация:
"NetworkSettings": {
"Bridge": "",
"SandboxID": "29735aa89eefbbbc03beb8f120aab0d0898de7b46959cf560739748458a1f8ca",
"SandboxKey": "/var/run/docker/netns/29735aa89eef",
"Ports": {
"80/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "2024"
}
]
},
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "c8e13b9e448504121192937ac4e4619c3dbdcc58fd26b89a601f3bba61dd9f21",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"MacAddress": "02:42:ac:11:00:02",
"NetworkID": "cd77486c39955f3d2369fe32e1f5b9b65d81c1a07bb677b085cec72b8fb52440",
"EndpointID": "c8e13b9e448504121192937ac4e4619c3dbdcc58fd26b89a601f3bba61dd9f21",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"DriverOpts": null,
"DNSNames": null
}
}
}
В приведенной выше информации о конфигурации вы можете найти полезную информацию.
IP-адрес: «IPAddress»: «172.17.0.2», шлюз: «Шлюз»: «172.17.0.1».
Кратко подытожим процесс:
baidu.com
запрос доступа/var/run/docker/netns/29735aa89eef
)Соответствующийсетьстек получатьbaidu.com
Не внутри контейнерсеть, стек сети определил, что запрос необходимо отправить во внешнюю сеть контейнера.172.17.0.1
Отправьте запрос. Адрес шлюза здесь на самом деле является местом установки. docker да Устройство виртуального подключения моста, созданное по умолчанию docker0
Мы можем увидеть с помощью следующей команды
liruilonger@cloudshell:~$ ifconfig docker0
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1460
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:87:21:0a:8b txqueuelen 0 (Ethernet)
RX packets 23 bytes 2710 (2.6 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 23 bytes 4437 (4.3 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
liruilonger@cloudshell:~$
Фактически, после создания контейнера докер по умолчанию сделает за нас некоторые вещи.
veth pair
,Воля Чтосередина Порт, подключенный к корневому пространству именсерединамостdocker0
начальство,Другой порт размещается в пространстве имен контейнера.net.ipv4.ip_forward=1
),Также в пространстве имен контейнера Конфигурация по умолчанию используется шлюз (172.17.0.1).SNAT
,Воляконтейнерпространство имен сетисерединатрафик ВпередизИсходный IP-адрес преобразуется в IP-адрес в корневом пространстве имен.
。может пройти sudo iptables -t nat -nL
команда найденаPOSTROUTING
настроен в цепочке SNAT
правило
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
Он устанавливает исходный адрес как 172.17.0.0/16 (подсеть сети Docker Bridge)
Исходный адрес всех пакетов изменяется наIP-адрес хоста
,и Воля Цельадресустановлен на 0.0.0.0/0
,Представляет любой адрес назначения. Это правило разрешено располагать в Docker Контейнеры в мостовой сети получают доступ к внешней сети и ресурсам Интернета.
docker0
После этого, поскольку он включен по умолчанию ipv4
Вперед,То есть это можно просто понимать как обращение с хостом как свыключатель
, docker0
трафик будет перенаправляться напрямую во внешнюю сетьliruilonger@cloudshell:~$ ip route
default via 10.88.0.1 dev eth0
10.88.0.0/16 dev eth0 proto kernel scope link src 10.88.0.4
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
liruilonger@cloudshell:~$
SNAT
,это ВоляКонвертироватьконтейнервнутренний источник IP Адрес соответствует адресу хост-машины IP адрес
,Сетевой стек на хосте будет основан на собственной таблице маршрутизации.,Переслать запрос во внешнюю сеть,В то же время, чтобы ответ мог прийти корректно при возвратеИтак, как правило, для доступа контейнера к внешней сети необходимы два фактора:
ip_forward
(включать IPV4 Вперед)SNAT/MASQUERADE
(Конфигурация SNAT/MASQUERADE)Поэтому, если вы обнаружите, что не можете получить доступ к внешней сети внутри контейнера,Вам необходимо подтвердить системуip_forward
да Нет, открыто。или проверьтеdocker daemon
при запуске--ip-forward
параметрда Нетдаустановлено наfalse
Понятно,Если да,Вам нужно установить--ip-forward=true
Перезапуск Docker,Docker Открою хост ip forward。
То есть доступ к пакетам внешней сети из контейнерного сегмента сети.,Придется сделать это один разMASQUERADE
,То есть все исходящие пакеты используют адрес хоста.Исходный адрес замены IP-адреса
。
Ниже приведены все цепочки на текущем хосте контейнера. nat
столбрандмауэрправило
liruilonger@cloudshell:~$ sudo iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- 0.0.0.0/0 169.254.169.254 tcp dpt:80 to:127.0.0.1:900
DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DNAT tcp -- 0.0.0.0/0 169.254.169.254 tcp dpt:80 to:127.0.0.1:900
DNAT tcp -- 0.0.0.0/0 169.254.169.254 tcp dpt:8080 to:169.254.169.254:80
DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
MASQUERADE tcp -- 172.17.0.2 172.17.0.2 tcp dpt:80
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:2024 to:172.17.0.2:80
liruilonger@cloudshell:~$
Здесь мы рассмотрим принцип сопоставления контейнерных портов. На самом деле он в основном заключается в. DOCKER
Эта пользовательская цепочка настроена с DNAT
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:2024 to:172.17.0.2:80
liruilonger@cloudshell:~$
второйправилода Целевой источникадресдля0.0.0.0/0
,Цельадресдля0.0.0.0/0
,TCP-пакет с портом назначения 2024. Это правило изменяет адрес назначения пакета на 172.17.0.2:80.,То есть перенаправить пакет на порт 80 172.17.0.2.
。
Здесь фактически выполняется сопоставление портов, и именно здесь возникает DNAT. Он имеет две ссылки.
соответственнодаPREROUTING
цепь иOUTPUT
цепь,Это означает, что он отправляется на локальную машину извне, и локальный процесс обращается к локальной машине (посредством iptables соответствоватьправилоADDRTYPE match dst-type LOCAL
обозначение)из 2024 Адрес назначения пакета порта будет изменен на 172.17.0.2:80。
о docker отображение портов, удалять Понятноиспользоватьdocker ps
команда данаконтейнервзаимосвязь сопоставления портов,Также доступенdocker port
Представление командконтейнериз端口существовать Хозяинначальствоиз映射
Вот краткий обзор некоторых знаний о DNAT и SNAT.
ДНКАТ в соответствии с заданными условиями Измените IP-адрес назначения и порт назначения пакета.
。DNAT Принцип аналогичен принципу переадресации портов, который мы обсуждали выше. Разница в том, что переадресация портов не изменяет IP-адрес. Типичный пример использования iptables для преобразования адресов назначения выглядит следующим образом:
iptables -t nat -A PREROUTING -d 1.2.3.4 -p tcp -dport 80 -j DNAT --to-destination 10.20.30.40:8080
Аналогично, DNAT не изменяет протокол. Если вы хотите сопоставить сетевую карту, вы можете использовать -i eth0
Укажите сетевую карту, получившую пакет (т. да input аббревиатура). На что следует обратить внимание, ДНКАТ происходит только в таблица НАТ PREROUTING
цепь и OUTPUT
,Это также причина, по которой нам нужно указать сетевую карту, которая получает пакет, а не сетевую карту, которая отправляет пакет.
Когда дело доходит до пересылки IP-адреса назначения на внешнюю машину, вам необходимо убедиться, что функция ip переадресации, т.е. Linux, включена:
echo 1 > /proc/sys/net/ipv4/ip_forward
Таинственный подмена сетевого Адрес на самом деле является разновидностью даSNAT. СНАТ Измените исходный IP-адрес пакета данных в соответствии с указанными условиями, то есть DNAT обратная операция. и DNAT Ограничения аналогичны SNAT. Стратегии могут возникать только в nat стол POSTROUTING цепь и INPUT
цепь。
ipttables -t nat -A POSTROUTING -s 192.168.26.12 -o eth0 -j SNAT -to-source 10.127.16.1
Что касается камуфляжа сетевых адресов,Подобно SNAT, это на самом деле специальная трансляция адреса источника.,Замените исходный адрес сообщения IP-адресом сетевой карты, с которой пришло сообщение.,Какой конкретно использовать?IPадрес Определяется ядром。Следующийправилозначениеда:источникадресда 10.8.0.0/16 Сделайте это один раз для каждого сообщения Masq
。
iptable -t nat -A POSTROUTING -s 10.8.0.0/16 -j MASQUERADE
© Авторские права на справочный контент в этой статье принадлежат оригинальному автору. Пожалуйста, сообщите нам, если есть какие-либо нарушения. :)
© liruilonger@gmail.com, 2018–2024. Все права сохранены. Attribution-NonCommercial-ShareAlike (CC BY-NC-SA 4.0).