Solusi 1:
Setelah menghabiskan beberapa hari melihat log dan konfigurasi untuk komponen yang terlibat, saya akan menyerah dan kembali ke Fedora 30, di mana ini tampaknya langsung berfungsi.
Berfokus pada firewall, saya menyadari bahwa menonaktifkan firewalld
tampaknya berhasil, tetapi saya lebih suka tidak melakukannya. Saat memeriksa aturan jaringan dengan iptables
, saya menyadari bahwa beralih ke nftables
artinya iptables
sekarang merupakan lapisan abstraksi yang hanya menampilkan sebagian kecil dari nftables
aturan. Itu berarti sebagian besar - jika tidak semua - dari firewalld
konfigurasi akan diterapkan di luar cakupan iptables
.
Saya dulu bisa menemukan seluruh kebenaran di iptables
, jadi ini akan membutuhkan waktu untuk membiasakan diri.
Singkat cerita - agar ini berhasil, saya harus mengaktifkan penyamaran. Sepertinya dockerd
sudah melakukannya 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/tcp
firewall-cmd --zone=public --add-port=443/tcp
# Reload firewall to apply permanent rules
firewall-cmd --reload
Mulai ulang atau mulai ulang dockerd
, dan jalan masuk dan keluar harus berfungsi.
Solusi 2:
Apa yang hilang dari jawaban sebelumnya adalah fakta bahwa Anda harus terlebih dahulu menambahkan antarmuka buruh pelabuhan ke zona yang Anda konfigurasikan, mis. publik (atau tambahkan ke zona "tepercaya" yang disarankan di sini tapi saya ragu itu bijaksana, dari perspektif keamanan). Karena secara default tidak ditetapkan ke zona. Ingatlah juga untuk memuat ulang daemon buruh pelabuhan 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' 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
Solusi 3:
Agar dapat menetapkan aturan mendetail untuk Docker, saya tidak perlu menyetel docker0 ke zona mana pun.
# 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
Ini diakhiri dengan aturan yang ditentukan 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>
Kelemahannya adalah Anda perlu menginstal containerd.io dari CentOS7 seperti yang dinyatakan oleh Saustrup