为什么 firewalld 允许公共流量到达绑定到 Docker 容器的非公共端口?

Rus*_*bot 6 networking firewalld fedora-server docker-networking

我正在尝试在 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
Run Code Online (Sandbox Code Playgroud)

当我使用 检查我的配置时--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:
Run Code Online (Sandbox Code Playgroud)

但是,当我对此进行测试时,我可以点击http://192.168.1.65:8080。我可以从同一内部网络 (192.168.128.128) 上的计算机以及来自外部计算机的公共请求来访问它。由于两者均未在internals中列出sources,因此我认为firewalld 不会允许请求通过。

我有一个带有接口的自动配置docker区域docker0,但删除它似乎并没有改变我访问内部端口的能力。

为什么我能够从未列出的来源成功请求 :8080 internal

Rus*_*bot 3

事实证明,问题源于我将 Docker 用于内部端口。为了简化让容器与世界以及彼此通信的过程,Docker 选择对防火墙/网络进行大量控制。这意味着,如果您希望容器可公开访问,并且需要通过与 Docker 守护程序位于同一台计算机上的防火墙来控制公共访问,则需要稍微不同地配置防火墙。Docker 有一些关于如何执行此操作的官方文档。基本上,您有以下选择:

  • 为您的防火墙设置一台单独的计算机。这可能是最简单的,因为 Docker 和防火墙不必共享资源。
  • iptables将您的规则添加到DOCKER-USER链中(这更多的是对用户的回答iptables;我不知道如何firewalld复制这种方法)
  • iptables=false通过在 Docker 服务配置中进行设置来禁用整个功能。(这篇博文讨论了这个选项)

我还发现了一篇我认为是链选项的不错变体的帖子DOCKER-USER。基本上,您创建一个iptables.conf无需刷新即可加载的文件,使用iptables-restore -n. 不幸的是,这是一个iptables解决方案,而不是一个firewalld解决方案。

诊断此问题的困难部分之一是我将运行一个脚本来修改防火墙以匹配我想要的内容,并且在我重新启动计算机或启动 Docker 守护程序之前,这将一直有效。Dockeriptables启动时会覆盖配置。