Я только что установил последнюю версию docker-ce
на CentOS, но я не может получить доступ к опубликованным портам с соседнего сервера и не может выйти наружу из самого контейнера.
Запуск простой ванильной CentOS 8 с включенными NetworkManager и FirewallD. Зона межсетевого экрана по умолчанию: public
.
Версии:
docker-ce
19.03.3 (официальный RPM Docker)containerd.io
1.2.6 (официальный RPM Docker для CentOS 7 - пока недоступен для CentOS 8)Потратив пару дней на просмотр журналов и конфигураций задействованных компонентов, я уже собирался бросить это полотенце и вернуться к 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: Плохое правило (существует ли подходящее правило в этой цепочке?).