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

Нет сетевого подключения к / из контейнера Docker CE в CentOS 8

Я только что установил последнюю версию docker-ce на CentOS, но я не может получить доступ к опубликованным портам с соседнего сервера и не может выйти наружу из самого контейнера.

Запуск простой ванильной CentOS 8 с включенными NetworkManager и FirewallD. Зона межсетевого экрана по умолчанию: public.

Версии:

Потратив пару дней на просмотр журналов и конфигураций задействованных компонентов, я уже собирался бросить это полотенце и вернуться к Fedora 30, где это, кажется, работает прямо из коробки.

Сосредоточившись на межсетевом экране, я понял, что отключение firewalld казалось, это помогло, но я бы предпочел не делать этого. При проверке сетевых правил с iptables, Я понял, что переход на nftables Значит это iptables теперь слой абстракции, который показывает только небольшую часть nftables правила. Это означает, что большинство - если не все - firewalld конфигурация будет применяться вне рамок iptables.

Я привык находить всю правду в iptables, так что к этому нужно привыкнуть.

Короче говоря - чтобы это сработало, мне пришлось включить маскировку. Это выглядело как dockerd уже сделал это через iptables, но, очевидно, это нужно специально включить для зоны межсетевого экрана для iptables маскировка на работу:

# Masquerading allows for docker ingress and egress (this is the juicy bit)
firewall-cmd --zone=public --add-masquerade --permanent

# Specifically allow incoming traffic on port 80/443 (nothing new here)
firewall-cmd --zone=public --add-port=80/tcp
firewall-cmd --zone=public --add-port=443/tcp

# Reload firewall to apply permanent rules
firewall-cmd --reload

Перезагрузите или перезапустите dockerd, и входящий и исходящий трафик должны работать.

Чего не хватает в ответах раньше, так это того факта, что вам сначала нужно добавить интерфейс докера в зону, которую вы настраиваете, например общедоступный (или добавьте его в "доверенную" зону, которая была предложена Вот но я сомневаюсь, что это разумно с точки зрения безопасности). Потому что по умолчанию он не привязан к зоне. Также не забудьте перезагрузить демон docker, когда закончите.

# Check what interface docker is using, e.g. 'docker0'
ip link show

# Check available firewalld zones, e.g. 'public'
sudo firewall-cmd --get-active-zones

# Check what zone the docker interface it bound to, most likely 'no zone' yet
sudo firewall-cmd --get-zone-of-interface=docker0

# So add the 'docker0' interface to the 'public' zone. Changes will be visible only after firewalld reload
sudo nmcli connection modify docker0 connection.zone public

# Masquerading allows for docker ingress and egress (this is the juicy bit)
sudo firewall-cmd --zone=public --add-masquerade --permanent
# Optional open required incomming ports (wasn't required in my tests)
# sudo firewall-cmd --zone=public --add-port=443/tcp
# Reload firewalld
sudo firewall-cmd --reload
# Reload dockerd
sudo systemctl restart docker

# Test ping and DNS works:
docker run busybox ping -c 1 172.16.0.1
docker run busybox cat /etc/resolv.conf
docker run busybox ping -c 1 yourhost.local

Чтобы установить подробные правила для Docker, мне не нужно было устанавливать docker0 для какой-либо зоны.

# 1. Stop Docker
systemctl stop docker
# 2. Recreate DOCKER-USER chain in firewalld. 
firewall-cmd --permanent \
             --direct \
             --remove-chain ipv4 filter DOCKER-USER

firewall-cmd --permanent \
             --direct \
             --remove-rules ipv4 filter DOCKER-USER

firewall-cmd --permanent \
             --direct \
             --add-chain ipv4 filter DOCKER-USER

# (Ignore any warnings)

# 3. Docker Container <-> Container communication

firewall-cmd --permanent \
             --direct \
             --add-rule ipv4 filter DOCKER-USER 1 \
             -m conntrack --ctstate RELATED,ESTABLISHED \
             -j ACCEPT \
             -m comment \
             --comment 'Allow docker containers to connect to the outside world'

firewall-cmd --permanent \
             --direct \
             --add-rule ipv4 filter DOCKER-USER 1 \
             -j RETURN \
             -s 172.17.0.0/16 \
             -m comment \
             --comment 'allow internal docker communication'

# Change the Docker Subnet to your actual one (e.g. 172.18.0.0/16)
# 4. Add rules for IPs allowed to access the Docker exposed ports.

firewall-cmd --permanent \
             --direct \
             --add-rule ipv4 filter DOCKER-USER 1 \
             -o docker0 \
             -p tcp \
             -m multiport \
             --dports 80,443 \
             -i eth0 \
             -o docker0 \
             -s 1.2.3.4/32 \
             -j ACCEPT \
             -m comment \
             --comment 'Allow IP 1.2.3.4 to docker ports 80 and 443'
# 5. log docker traffic (if you like)

firewall-cmd --direct \
             --add-rule ipv4 filter DOCKER-USER 0 \
             -j LOG \
             --log-prefix ' DOCKER: '
# 6. Block all other IPs. 
This rule has lowest precedence, so you can add allowed IP rules later.

firewall-cmd --permanent \
             --direct \
             --add-rule ipv4 filter DOCKER-USER 10 \
             -j REJECT \
             -m comment \
             --comment 'reject all other traffic to DOCKER-USER'
# 7. Reload firewalld, Start Docker again
firewall-cmd --reload
systemctl start docker

Это заканчивается правилами, определенными в /etc/firewalld/direct.xml:

<?xml version="1.0" encoding="utf-8"?>
<direct>
  <chain ipv="ipv4" table="filter" chain="DOCKER-USER"/>
  <rule ipv="ipv4" table="filter" chain="DOCKER-USER" priority="0">-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment 'Allow docker containers to connect to the outside world'</rule>
  <rule ipv="ipv4" table="filter" chain="DOCKER-USER" priority="0">-j RETURN -s 172.17.0.0/16 -m comment --comment 'allow internal docker communication'</rule>
  <rule ipv="ipv4" table="filter" chain="DOCKER-USER" priority="0">-p tcp -m multiport --dports 80,443 -s 1.2.3.4/32 -j ACCEPT -m comment --comment 'Allow IP 1.2.3.4 to docker ports 80 and 443'</rule>
  <rule ipv="ipv4" table="filter" chain="DOCKER-USER" priority="0">-j LOG --log-prefix ' DOCKER TCP: '</rule>
  <rule ipv="ipv4" table="filter" chain="DOCKER-USER" priority="10">-j REJECT -m comment --comment 'reject all other traffic to DOCKER-USER'</rule>
</direct>

Недостатком по-прежнему является то, что вам необходимо установить containerd.io из CentOS7, как заявил Saustrup.

Я снова изменил переменную FirewallBackend на iptables, и у меня она работает.

В этом обновлении подсистема фильтрации nftables является серверной частью межсетевого экрана по умолчанию для демона firewalld. Чтобы изменить серверную часть, используйте параметр FirewallBackend в файле /etc/firewalld.conf.

Ссылка на сайт: Centos8 Deprecated_functionality

У меня не так много информации об этом изменении поведения. Согласно журналам CentOS8, некоторые из правил iptables, которые пытается использовать Docker, не работают:

ПРЕДУПРЕЖДЕНИЕ: COMMAND_FAILED: '/ usr / sbin / iptables -w10 -D FORWARD -i docker0 -o docker0 -j DROP' failed: iptables: Плохое правило (существует ли подходящее правило в этой цепочке?).