Sau*_*rup 27 linux networkmanager centos docker centos8
我刚刚docker-ce在 CentOS 上安装了最新版本,但我无法从相邻服务器访问已发布的端口,也无法从容器本身访问外部。
在启用 NetworkManager 和 FirewallD 的情况下运行普通的 CentOS 8。默认防火墙区域是public.
版本:
docker-ce 19.03.3(官方 Docker RPM)containerd.io 1.2.6(用于 CentOS 7 的官方 Docker RPM - 尚不适用于 CentOS 8)Sau*_*rup 55
在花了几天时间查看相关组件的日志和配置后,我正准备认输并恢复到 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
Run Code Online (Sandbox Code Playgroud)
Reboot 或 restart dockerd,入口和出口都应该工作。
omn*_*mni 10
之前的答案中缺少的事实是,您首先需要将 docker 接口添加到您配置的区域,例如 public(或将其添加到此处建议的“受信任”区域,但我怀疑从安全角度来看这是否明智)。因为默认情况下它没有分配给区域。还记得在完成后重新加载 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
Run Code Online (Sandbox Code Playgroud)
为了能够为 Docker 设置细粒度的规则,我不需要将 docker0 设置到任何区域。
# 1. Stop Docker
systemctl stop docker
Run Code Online (Sandbox Code Playgroud)
# 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)
Run Code Online (Sandbox Code Playgroud)
# 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)
Run Code Online (Sandbox Code Playgroud)
# 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'
Run Code Online (Sandbox Code Playgroud)
# 5. log docker traffic (if you like)
firewall-cmd --direct \
--add-rule ipv4 filter DOCKER-USER 0 \
-j LOG \
--log-prefix ' DOCKER: '
Run Code Online (Sandbox Code Playgroud)
# 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'
Run Code Online (Sandbox Code Playgroud)
# 7. Reload firewalld, Start Docker again
firewall-cmd --reload
systemctl start docker
Run Code Online (Sandbox Code Playgroud)
这以 /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>
Run Code Online (Sandbox Code Playgroud)
缺点仍然是你需要从 CentOS7 安装containerd.io,如 Saustrup 所说
| 归档时间: |
|
| 查看次数: |
27496 次 |
| 最近记录: |