Почему firewalld разрешает публичный трафик на мои непубличные порты, привязанные к контейнерам Docker?
Я пытаюсь реализовать довольно простой брандмауэр в Fedora, где общедоступный Интернет может получить доступ к SSH, HTTP, HTTPS и Cockpit, но не более того. Тем временем на серверах через Docker выполняются микросервисы, которые могут взаимодействовать друг с другом через порты 8000–8999.
Я настроил это на новой установке сервера Fedora с помощью следующих команд:
firewall-cmd --zone=public --add-service=cockpit
firewall-cmd --zone=public --add-service=http
firewall-cmd --zone=public --add-service=https
firewall-cmd --zone=internal --add-source=192.168.1.65
firewall-cmd --zone=internal --add-source=192.168.1.66
firewall-cmd --zone=internal --add-port=8000-8999/tcp
firewall-cmd --runtime-to-permanent
Когда я проверяю свою конфигурацию с помощью--list-all
, все выглядит правильно:
> firewall-cmd --list-all --zone=internal
internal (active)
target: default
icmp-block-inversion: no
interfaces:
sources: 192.168.1.65 192.168.1.66
services: dhcpv6-client ssh
ports: 8000-8999/tcp
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
> firewall-cmd --list-all --zone=public
public (active)
target: default
icmp-block-inversion: no
interfaces: enp2s0
sources:
services: cockpit dhcpv6-client http https ssh
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
Однако, когда я проверяю это, я могу нажать http://192.168.1.65:8080 . Я могу выполнить его с машины в той же внутренней сети (192.168.128.128), а также сделать публичный запрос с внешней машины. Поскольку ни один из них не был указан в 'ssources
Я предположил, что firewalld не пропустит запросы.
У меня есть автонастройкаdocker
зона сdocker0
интерфейс, но его удаление, похоже, не меняет мою способность подключаться к внутреннему порту.
Почему я могу успешно запросить :8080 из источников, которых нет в списке?internal
?
1 ответ
Мне удалось решить эту проблему, воссоздавDOCKER-USER
цепочку и хотел бы поделиться ею, если кто-нибудь еще найдет ее полезной.
Это основано на решении, которое я нашел на Github (https://github.com/firewalld/firewalld/issues/869) и в блоге какого-то гения (https://roosbertl.blogspot.com/2019/06/securing-docker ). -ports-with-firewalld.html), но мне пришлось его немного адаптировать/доработать.
# 1. Stop Docker
systemctl stop docker.socket
systemctl stop docker.service
# 2. Recreate DOCKER-USER iptables chain with firewalld. Ignore warnings, do not ignore errors
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
# 3. Add iptables rules to DOCKER-USER chain - unrestricted outbound, restricted inbound to private IPs
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment 'Allow containers to connect to the outside world'
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 -j RETURN -s 127.0.0.0/8 -m comment --comment 'allow internal docker communication, loopback addresses'
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 -j RETURN -s 172.16.0.0/12 -m comment --comment 'allow internal docker communication, private range'
# 3.1 optional: for wider internal networks
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 -j RETURN -s 10.0.0.0/8 -m comment --comment 'allow internal docker communication, private range'
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 -j RETURN -s 192.168.0.0/16 -m comment --comment 'allow internal docker communication, private range'
# 4. Block all other IPs. This rule has lowest precedence, so you can add rules before this one later.
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 10 -j REJECT -m comment --comment 'reject all other traffic to DOCKER-USER'
# 5. Activate rules
firewall-cmd --reload
# 6. Start Docker
systemctl start docker.socket
systemctl start docker.service