Tidak ada konektivitas jaringan ke / dari Docker CE container di CentOS 8

Saya baru saja menginstal rilis terbaru dari docker-ce pada CentOS, tapi saya tidak dapat menjangkau port yang dipublikasikan dari server tetangga dan tidak bisa mencapai luar dari wadah itu sendiri.

Menjalankan polos vanili CentOS 8 dengan NetworkManager dan FirewallD diaktifkan. Zona firewall Default adalah public.

Versi:

  • docker-ce 19.03.3 (RPM buruh pelabuhan resmi)
  • containerd.io 1.2.6 (rpm Docker resmi untuk CentOS 7 - belum tersedia untuk CentOS 8)
  • CentOS 8.0.1905 (instalasi minimal)

Setelah menghabiskan beberapa hari melihat log dan konfigurasi untuk komponen yang terlibat, saya akan menyerah dan kembali ke Fedora 30, di mana ini tampaknya bekerja langsung di luar kotak.

Berfokus pada firewall, saya menyadari bahwa menonaktifkan firewalld tampaknya melakukan trik, tapi aku lebih suka untuk tidak melakukan itu. Saat memeriksa aturan jaringan dengan iptables, Saya menyadari bahwa peralihan ke nftables berarti bahwa iptables sekarang merupakan lapisan abstraksi yang hanya menunjukkan sebagian kecil dari nftables aturan. Itu berarti sebagian besar-jika tidak semua-dari firewalld konfigurasi akan diterapkan di luar lingkup iptables.

Aku digunakan untuk dapat menemukan seluruh kebenaran dalam iptables, jadi ini akan membutuhkan waktu untuk membiasakan diri.

Singkat cerita-agar ini berhasil, saya harus mengaktifkan penyamaran. Itu tampak seperti dockerd sudah melakukan ini melalui iptables, tetapi tampaknya ini perlu diaktifkan secara khusus untuk Zona firewall untuk iptables menyamar untuk bekerja:

# 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/tcpfirewall-cmd --zone=public --add-port=443/tcp# Reload firewall to apply permanent rulesfirewall-cmd --reload

Reboot atau restart dockerd, dan masuk dan keluar harus bekerja.

Apa yang hilang dari jawaban sebelumnya adalah kenyataan bahwa Anda harus terlebih dahulu menambahkan antarmuka buruh pelabuhan anda ke zona yang Anda konfigurasikan, misalnya publik (atau menambahkannya ke zona "tepercaya" yang disarankan di sini tapi saya ragu itu bijaksana, dari perspektif keamanan). Karena secara default itu tidak ditugaskan ke zona. Juga ingat untuk memuat ulang daemon docker setelah selesai.

# 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' yetsudo firewall-cmd --get-zone-of-interface=docker0# So add the 'docker0' interface to the 'public' zone. Changes will be visible only after firewalld reloadsudo 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 firewalldsudo firewall-cmd --reload# Reload dockerdsudo systemctl restart docker# Test ping and DNS works:docker run busybox ping -c 1 172.16.0.1docker run busybox cat /etc/resolv.confdocker run busybox ping -c 1 yourhost.local

Untuk dapat menetapkan aturan berbutir halus untuk Docker, saya tidak perlu mengatur docker0 ke zona mana pun.

# 1. Stop Dockersystemctl stop docker
# 2. Recreate DOCKER-USER chain in firewalld. firewall-cmd --permanent \             --direct \             --remove-chain ipv4 filter DOCKER-USERfirewall-cmd --permanent \             --direct \             --remove-rules ipv4 filter DOCKER-USERfirewall-cmd --permanent \             --direct \             --add-chain ipv4 filter DOCKER-USER# (Ignore any warnings)
# 3. Docker Container <-> Container communicationfirewall-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 againfirewall-cmd --reloadsystemctl start docker

Ini berakhir dengan aturan yang didefinisikan di / 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>

Kelemahan masih adalah bahwa Anda perlu menginstal containerd.io dari CentOS7 seperti yang dinyatakan oleh Saustrup

Saya telah mengubah variabel FirewallBackend menjadi iptables lagi dan itu berfungsi untuk saya.

Dengan pembaruan ini, subsistem pemfilteran nftables adalah backend firewall default untuk daemon firewalld. Untuk mengubah backend, gunakan opsi FirewallBackend di / etc / firewalld.berkas conf.

Tautan: Centos8 Deprecated_functionality

Saya tidak memiliki terlalu banyak informasi tentang perubahan perilaku ini. Beberapa aturan iptables yang coba digunakan Docker tidak berfungsi sesuai dengan log CentOS8:

Peringatan: COMMAND_FAILED: '/ usr / sbin / iptables-w10-D FORWARD-I DOCKER0-O DOCKER0-J DROP ' gagal: iptables: aturan buruk (apakah ada aturan yang cocok dalam rantai itu?).

Milik saya bahkan tidak berfungsi dengan firewalld yang sepenuhnya dinonaktifkan. Ada yang punya ide ??