Встановлення Docker в моєму варіанті дещо ускладнено.
Я не хочу використовувати дефолтовий firewalld і iptables.
Наразі firewalld не підтримує збереження правил nftables, які вносяться через nft, тому при рестарті все вилітає.
А сам він не підтримує SNAT.
Плюс мені не подобається ідея ввімкнення маскарадінгу для всіх. Я хочу старий добрий Source NAT.
І завжди краще знати що відбувається під капотом та як працює, щоб не виникало сумних історій під час дебага.
Тому тут буде більше про nftables і як вимкнути в докері дефолтовий фаєрвол.
Ставимо докер. Додаємо репозиторій
~]# dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo
Adding repo from: https://download.docker.com/linux/centos/docker-ce.repo
Встановлюємо
~]# dnf install docker-ce
Docker CE Stable - x86_64 41 kB/s | 14 kB 00:00
Dependencies resolved.
================================================================================================================================
Package Architecture Version Repository Size
================================================================================================================================
Installing:
docker-ce x86_64 3:20.10.7-3.el8 docker-ce-stable 27 M
Installing dependencies:
container-selinux noarch 2:2.162.0-1.module_el8.4.0+830+8027e1c4 appstream 52 k
containerd.io x86_64 1.4.9-3.1.el8 docker-ce-stable 30 M
docker-ce-cli x86_64 1:20.10.7-3.el8 docker-ce-stable 33 M
docker-ce-rootless-extras x86_64 20.10.7-3.el8 docker-ce-stable 9.2 M
docker-scan-plugin x86_64 0.8.0-3.el8 docker-ce-stable 4.2 M
fuse-common x86_64 3.2.1-12.el8 baseos 21 k
fuse-overlayfs x86_64 1.4.0-3.module_el8.4.0+830+8027e1c4 appstream 72 k
fuse3 x86_64 3.2.1-12.el8 baseos 50 k
fuse3-libs x86_64 3.2.1-12.el8 baseos 94 k
libcgroup x86_64 0.41-19.el8 baseos 70 k
libslirp x86_64 4.3.1-1.module_el8.4.0+575+63b40ad7 appstream 69 k
slirp4netns x86_64 1.1.8-1.module_el8.4.0+641+6116a774 appstream 51 k
tar x86_64 2:1.30-5.el8 baseos 838 k
Enabling module streams:
container-tools rhel8
Transaction Summary
================================================================================================================================
Install 14 Packages
Total download size: 104 M
Installed size: 424 M
Is this ok [y/N]: y
.....
Total 9.0 MB/s | 104 MB 00:11
warning: /var/cache/dnf/docker-ce-stable-fa9dc42ab4cec2f4/packages/containerd.io-1.4.9-3.1.el8.x86_64.rpm: Header V4 RSA/SHA512 Signature, key ID 621e9f35: NOKEY
Docker CE Stable - x86_64 10 kB/s | 1.6 kB 00:00
Importing GPG key 0x621E9F35:
Userid : "Docker Release (CE rpm) <docker@docker.com>"
Fingerprint: 060A 61C5 1B55 8A7F 742B 77AA C52F EB6B 621E 9F35
From : https://download.docker.com/linux/centos/gpg
Is this ok [y/N]: y
Встановлюємо docker-compose
~]# curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 633 100 633 0 0 1692 0 --:--:-- --:--:-- --:--:-- 1692
100 12.1M 100 12.1M 0 0 5469k 0 0:00:02 0:00:02 --:--:-- 6980k
~]# chmod +x /usr/local/bin/docker-compose
За замовчуванням Centos 8 має firewalld та nftables в якості фаєрволу.
~]# cat /etc/firewalld/firewalld.conf |grep FirewallBackend
# FirewallBackend
FirewallBackend=nftables
Але він поки не розуміє source NAT. А ще має дуже заплутану схему таблиць та ланцюжків.
Тому я його просто вимикаю й маскую від інших, щоб не могли запустити.
~]# systemctl stop firewalld
~]# systemctl disable firewalld
Removed /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
~]# systemctl mask firewalld
Created symlink /etc/systemd/system/firewalld.service → /dev/null.
А от nftables вмикаємо
~]# systemctl start nftables
~]# systemctl enable nftables
Вивести правила фільтру:
~]# nft list table ip filter
table ip filter {
chain INPUT {
type filter hook input priority filter; policy accept;
}
chain FORWARD {
type filter hook forward priority filter; policy accept;
}
chain OUTPUT {
type filter hook output priority filter; policy accept;
}
}
Дефолтом краще для FORWARD поставити політику drop й дозволяти тільки тим, кому потрібно
~]# nft add chain filter FORWARD '{policy drop;}'
Docker поки не має підтримки nftables. Треба вимкнути в ньому iptables та налаштувати фаєрвол самому.
Доречі ip_forward має бути увімкнений
~]# sysctl -a|grep net.ipv4.ip_forward
net.ipv4.ip_forward = 1
зробимо окремий service файл для systemd
~]# cp /usr/lib/systemd/system/docker.service /etc/systemd/system/
Потрібно дещо змінити рядки для старту
~]# tail -n+$(cat /etc/systemd/system/docker.service -n|grep "\[Service\]"|sed 's/\|/ /'|awk '{print $1}') /etc/systemd/system/docker.service |head -n12
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
EnvironmentFile=-/etc/sysconfig/docker
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock $DOCKER_ARGS
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
Файл, в якому зазначаються опції
~]# cat /etc/sysconfig/docker
DOCKER_ARGS=--iptables=false --ipv6=false --bip 172.17.0.1/16 --fixed-cidr 172.17.0.0/16
Запускаємо та перевіряємо
~]# systemctl daemon-reload
~]# systemctl start docker
~]# ps ax|grep docker
7027 ? Ssl 0:00 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=false --ipv6=false --bip 172.17.0.1/16 --fixed-cidr 172.17.0.0/16
Якщо демон докера вже запускався, то, щоб скинути всі правила, робимо
~]# iptables -F
обережно, якщо iptables використовується чимось, то перевірте
~]# iptables -nvL
Опції присутні, дивимось мережу
~]# ip a l dev docker0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:d9:fb:98:3b brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
Для перевірки роботи можна запустити звичайний Web сервер.
~]# docker run -it --rm -d -p 8080:80 --name web nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
33847f680f63: Pull complete
dbb907d5159d: Pull complete
8a268f30c42a: Pull complete
b10cf527a02d: Pull complete
c90b090c213b: Pull complete
1f41b2f2bf94: Pull complete
Digest: sha256:8f335768880da6baf72b70c701002b45f4932acae8d574dedfddaf967fc3ac90
Status: Downloaded newer image for nginx:latest
1aa985a47ed44011712c00d3e68309297d32b4caf6a4b51852e7bd4b2005a55d
Доступ є, нжінкс віддає сторінку
Але ж треба перевірити чи є доступ в самих контейнерах
~]# docker exec -ti web /bin/bash
root@1aa985a47ed4:/# curl 1.1.1.1
Доступу немає
На хості маємо.
~]# tcpdump -ni docker0
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes
22:17:34.837034 IP 172.17.0.2.36384 > 1.1.1.1.http: Flags [S], seq 1659458766, win 29200, options [mss 1460,sackOK,TS val 2264482116 ecr 0,nop,wscale 7], length 0
22:17:35.853350 IP 172.17.0.2.36384 > 1.1.1.1.http: Flags [S], seq 1659458766, win 29200, options [mss 1460,sackOK,TS val 2264483133 ecr 0,nop,wscale 7], length 0
Дивимось що там з nftables
~]# nft list table nat
table ip nat {
chain PREROUTING {
type nat hook prerouting priority dstnat; policy accept;
fib daddr type local counter packets 9 bytes 540 jump DOCKER
}
chain INPUT {
type nat hook input priority 100; policy accept;
}
chain POSTROUTING {
type nat hook postrouting priority srcnat; policy accept;
oifname != "docker0" @nh,96,16 44049 counter packets 6 bytes 360 masquerade
}
chain OUTPUT {
type nat hook output priority -100; policy accept;
@nh,128,8 != 127 fib daddr type local counter packets 0 bytes 0 jump DOCKER
}
chain DOCKER {
iifname "docker0" counter packets 0 bytes 0 return
}
}
Є маскарадінг для докера. Вже щось.
Але мені в такому вигляді він не потрібен, бо не полюбляю коли хтось щось за мене вирішує.
Дивимось номер правила для видалення
~]# nft -a list chain nat POSTROUTING
table ip nat {
chain POSTROUTING { # handle 3
type nat hook postrouting priority srcnat; policy accept;
oifname != "docker0" @nh,96,16 44049 counter packets 6 bytes 360 masquerade # handle 14
}
}
маємо handle 14, можна видаляти
~]# nft delete rule nat POSTROUTING handle 14
~]# nft -a list chain nat POSTROUTING
table ip nat {
chain POSTROUTING { # handle 3
type nat hook postrouting priority srcnat; policy accept;
}
}
Таким же чином видаляємо інші правила й ланцюжки docker
А до аргументів запуску докера треба додати --ip-masq=false аби він сам не намагався такого утнути ще раз.
~]# cat /etc/sysconfig/docker
DOCKER_ARGS=--iptables=false --ip-masq=false --ipv6=false --bip 172.17.0.1/16 --fixed-cidr 172.17.0.0/16
Можна перезапускати докер
~]# docker stop web
~]# systemctl restart docker
~]# docker run -it --rm -d -p 8080:80 --name web nginx
69c3a05b33a8a8c289428a386324c336c2e0c100aa7129e4857a09908ba9c498
~]# docker exec -ti web /bin/bash
root@69c3a05b33a8:/#
Ще у firewall-cmd додавалась зона docker, вона активна і там є інтерфейс docker0
~]# firewall-cmd --get-active-zones
docker
interfaces: docker0
public
interfaces: enp0s3
Якщо firewalld ще працює, її я теж приберу
~]# firewall-cmd --zone=docker --remove-interface=docker0
success
~]# firewall-cmd --permanent --zone=docker --remove-interface=docker0
Warning: NOT_ENABLED: docker0
success
~]# firewall-cmd --get-active-zones
public
interfaces: enp0s3
Docker ще додав файл конфігурації до /etc/firewalld/zones
Його я теж видалив й перечитав конфіг firewall-cmd --reload
Ми все вимкнули, тому доступу з докера нікуди немає
Додаємо трансляцію nat POSTROUTING
~]# nft add rule nat POSTROUTING ip saddr 172.17.0.0/24 oif enp0s3 snat to 192.168.7.104
~]# nft list chain nat POSTROUTING
table ip nat {
chain POSTROUTING {
type nat hook postrouting priority srcnat; policy accept;
ip saddr 172.17.0.0/24 oif "enp0s3" snat to 192.168.7.104
}
}
Доступу все одно немає, бо у filter FORWARD політика drop (якщо accept, то пропускаємо)
~]# nft list chain filter FORWARD
table ip filter {
chain FORWARD {
type filter hook forward priority filter; policy drop;
}
}
Дозволяємо FORWARD для мережі докера
~]# nft add rule ip filter FORWARD ip saddr 172.17.0.0/16 accept
~]# nft add rule ip filter FORWARD ip daddr 172.17.0.0/16 accept
Вмикаємо для старта в автоматичному режимі
~]# systemctl enable docker
Тепер постає питання збереження правил nftables під час старту firewalld.
Залишаються тільки дефолтові правила nftables та наш source NAT
Зберігаємо
~]# nft list ruleset >> /etc/sysconfig/nftables.conf
Переглянути
# nft list ruleset
table ip filter {
chain INPUT {
type filter hook input priority filter; policy accept;
}
chain FORWARD {
type filter hook forward priority filter; policy drop;
ip saddr 172.17.0.0/16 accept
ip daddr 172.17.0.0/16 accept
}
chain OUTPUT {
type filter hook output priority filter; policy accept;
}
}
table ip6 filter {
chain INPUT {
type filter hook input priority filter; policy accept;
}
chain FORWARD {
type filter hook forward priority filter; policy accept;
}
chain OUTPUT {
type filter hook output priority filter; policy accept;
}
}
table bridge filter {
chain INPUT {
type filter hook input priority filter; policy accept;
}
chain FORWARD {
type filter hook forward priority filter; policy accept;
}
chain OUTPUT {
type filter hook output priority filter; policy accept;
}
}
table ip security {
chain INPUT {
type filter hook input priority 150; policy accept;
}
chain FORWARD {
type filter hook forward priority 150; policy accept;
}
chain OUTPUT {
type filter hook output priority 150; policy accept;
}
}
table ip raw {
chain PREROUTING {
type filter hook prerouting priority raw; policy accept;
}
chain OUTPUT {
type filter hook output priority raw; policy accept;
}
}
table ip mangle {
chain PREROUTING {
type filter hook prerouting priority mangle; policy accept;
}
chain INPUT {
type filter hook input priority mangle; policy accept;
}
chain FORWARD {
type filter hook forward priority mangle; policy accept;
}
chain OUTPUT {
type route hook output priority mangle; policy accept;
}
chain POSTROUTING {
type filter hook postrouting priority mangle; policy accept;
}
}
table ip nat {
chain PREROUTING {
type nat hook prerouting priority dstnat; policy accept;
}
chain INPUT {
type nat hook input priority 100; policy accept;
}
chain POSTROUTING {
type nat hook postrouting priority srcnat; policy accept;
ip saddr 172.17.0.0/24 oif "enp0s3" snat to 192.168.7.104
}
chain OUTPUT {
type nat hook output priority -100; policy accept;
}
}
table ip6 security {
chain INPUT {
type filter hook input priority 150; policy accept;
}
chain FORWARD {
type filter hook forward priority 150; policy accept;
}
chain OUTPUT {
type filter hook output priority 150; policy accept;
}
}
table ip6 raw {
chain PREROUTING {
type filter hook prerouting priority raw; policy accept;
}
chain OUTPUT {
type filter hook output priority raw; policy accept;
}
}
table ip6 mangle {
chain PREROUTING {
type filter hook prerouting priority mangle; policy accept;
}
chain INPUT {
type filter hook input priority mangle; policy accept;
}
chain FORWARD {
type filter hook forward priority mangle; policy accept;
}
chain OUTPUT {
type route hook output priority mangle; policy accept;
}
chain POSTROUTING {
type filter hook postrouting priority mangle; policy accept;
}
}
table ip6 nat {
chain PREROUTING {
type nat hook prerouting priority dstnat; policy accept;
}
chain INPUT {
type nat hook input priority 100; policy accept;
}
chain POSTROUTING {
type nat hook postrouting priority srcnat; policy accept;
}
chain OUTPUT {
type nat hook output priority -100; policy accept;
}
}
table bridge nat {
chain PREROUTING {
type filter hook prerouting priority dstnat; policy accept;
}
chain OUTPUT {
type filter hook output priority out; policy accept;
}
chain POSTROUTING {
type filter hook postrouting priority srcnat; policy accept;
}
}
В результаті: мені не довелось вмикати маскарадінг для всіх, я не використовував firewall-cmd
Ви маєте увійти під своїм обліковим записом