10个版本 (6个稳定版)
1.3.0 | 2024年1月7日 |
---|---|
1.2.1 | 2020年12月13日 |
1.2.0 | 2020年7月13日 |
1.0.1 | 2019年9月28日 |
0.0.1-placeholder |
|
在网络编程中排名第1825
220KB
3.5K SLoC
DFW - Rust中的Docker防火墙框架
概述
DFW在概念上基于Docker防火墙框架,DFWFW。其目标是使使用Docker进行防火墙管理变得更加简单,并通过尝试替换Docker内置的防火墙处理来使其更加全面。
这是通过一个灵活的配置来实现的,该配置定义了如何构建防火墙。在DFW运行期间,将监视Docker容器事件,并在必要时重建规则。
DFW(及其之前的DFWFW)的一个关键特性是不需要正在运行的容器在主机上发布它们的端口(类似于docker container run --publish 80:8080
),而是使用主机防火墙的网络地址转换(NAT)功能直接将数据包转发到容器中的端口。1
DFW支持以下防火墙后端
- iptables
- nftables
您可以选择最适合您的选项。2
1 这仅适用于您在主机上使用IPv4的情况。如果您需要IPv6支持,您仍然需要发布端口。有关更多信息,请参阅[IPv6支持](#configuration-ipv6)。2 请确保不要混合防火墙后端:如果您已经在主机上使用了一个,请不要与DFW一起使用另一个。
示例
假设您想在Docker中运行一个反向代理,该代理将流量代理到也在Docker中运行的Web应用程序。使用Docker提供的常规工具,您只需绑定端口,将两个Docker容器放在同一个Docker网络上,就可以得到一个可行的解决方案。
虽然这个方法相当有效,但让Docker处理防火墙规则有一些潜在的缺点。
-
默认情况下,主机挂载端口的流量不受限制。
虽然这通常是期望的行为,但如果您只想本地启动并测试一个服务,可能会给您带来麻烦。
使用DFW,您必须明确:如果您想您的服务可以被访问,您必须配置确切地知道哪些容器可以从哪里访问。虽然这会带来一定的前期成本,但它可以在之后通过确保您不会意外暴露您不想暴露的服务来回报您。
-
同一Docker网络上的容器之间的流量不受限制。
再次强调:大多数情况下这是期望的行为。当它不是期望的行为时,Docker不会提供限制这种流量的工具。
DFW允许您配置容器之间如何相互通信,无论是在同一Docker网络上还是在Docker网络之间。
在上面的例子中,我们希望反向代理能够与Web应用程序通信,但Web应用程序不应该能够发起到反向代理的连接。DFW允许您实现这种场景。
如果您没有遇到上述缺点,并且对Docker提供的功能感到满意,您可能不需要DFW。但如果您有,或者只是想尝试DFW,请查看反向代理示例,该示例将引导您通过提出的示例。
3当然,您可以将端口绑定到`127.0.0.1`,但您必须明确指出这一点,这很容易忘记。入门指南
如果您是新手,第一步是选择一个防火墙后端。
-
nftables可以看作是iptables的新一代实现,它将在大多数Linux发行版中替代iptables。例如,它已经是在Debian 10 Buster中的默认设置。
如果您在一个尚未使用过任何后端的主机上开始,nftables是建议的后端。
-
虽然iptables是较老的netfilter实现,但它仍然是一个有效的防火墙后端,并在许多发行版中得到了广泛的应用。
如果您已经使用iptables,并且有一个您不想重新设置的配置,您可以自由使用DFW的iptables后端。
一旦您决定使用哪个后端,请参阅后端特定的文档了解如何进一步操作。
如果您已经是DFW的用户并且想要升级到新版本,请参阅相应的迁移文档。
配置
一般配置发生在六个类别中
-
global_defaults
这个类别定义了DFW和其他类别将使用的全局默认值。
-
backend_defaults
这个类别定义了特定于使用的防火墙后端的配置值。
-
container_to_container
此功能控制容器之间以及与Docker网络之间的通信。
-
container_to_wider_world
此功能控制容器是否以及如何访问更广泛的世界,即它们可以在主机上的
OUTPUT
链中与哪些内容进行通信。 -
container_to_host
要限制或允许对主机的访问,请使用本节。
-
wider_world_to_container
此功能控制更广泛的世界(即通过主机上的
INPUT
链进入的内容)如何与容器或Docker网络通信。 -
container_dnat
此类别允许您定义特定规则的特定目标网络地址转换,尤其是在Docker网络中。
此外,您还可以使用命令行参数配置DFW的通用行为,这些参数可以通过执行dfw --help
来描述。
dfw
Docker firewall framework, in Rust
USAGE:
dfw [OPTIONS]
OPTIONS:
--burst-timeout <TIMEOUT>
Time to wait after a event was received before processing the rules, in milliseconds
[default: 500]
-c, --config-file <FILE>
Set the configuration file
--check-config
Verify if the provided configuration is valid, exit afterwards.
--config-path <PATH>
Set a path with multiple TOML configuration files
--container-filter <FILTER>
Filter the containers to be included during processing
[default: running]
-d, --docker-url <URL>
Set the URL to the Docker instance (e.g. unix:///tmp/docker.sock)
--disable-event-monitoring
Disable event monitoring
--dry-run
Don't touch firewall-rules, just show what would be done. Note that this requires Docker
and the containers/networks referenced in the configuration to be available. If you want
to check the config for validity, specify --check-config instead.
--firewall-backend <BACKEND>
Select the firewall-backend to use
[default: nftables]
[possible values: nftables, iptables]
-h, --help
Print help information
-i, --load-interval <INTERVAL>
Interval between rule processing runs, in seconds (0 = disabled)
[default: 0]
--log-level <SEVERITY>
Define the log level
[default: info]
-m, --load-mode <MODE>
Define if the config-fields get loaded once, or before every run
[default: once]
[possible values: once, always]
--run-once
Process rules once, then exit.
-V, --version
Print version information
故障排除
如果您在使用DFW时遇到问题,可以查阅故障排除文档,了解已知的潜在障碍。如果您找不到您的问题,请在GitHub上创建一个问题描述您的问题。
IPv6支持
如果您将容器公开,DFW将使用“目标NAT”和“伪装”将传入的包重定向到容器的正确内部IPv6地址,并正确地将响应重定向回原始请求者。默认情况下,Docker不会将私有IPv6地址分配给网络和容器,它只分配私有IPv4地址。
通常,也不需要私有IPv6地址:Docker使用一个代理二进制文件,将容器的端口绑定到主机以执行从主机到容器的流量转换。此主机绑定与IPv4和IPv6兼容,这意味着内部只需要一个IPv4地址。
正如所提到的,DFW的运行方式不同:因为它使用NAT来管理流量,所以它实际上需要将传入的IPv6包从IPv6转换为IPv4,并将IPv4响应转换为IPv6,而nftables和iptables不支持这种转换。
因此,如果您想要通过IPv6访问您的服务,您需要确保以下事项:
-
您必须使用Docker的--publish选项公开您希望在主机上访问的容器的端口。
您选择的宿主端口是之后可以从外部公开访问的端口。例如,如果您想通过主机端口号80和443访问您的web服务器,您需要将容器端口公开为80和443。
-
在您的wider_world_to_container规则中,您的公开端口的宿主端口部分必须与您公开容器端口时使用的端口匹配(尽管它不需要与容器端口本身匹配)。
作为wider_world_to_container规则的一部分,DFW将为使宿主端口可通过IPv6访问而创建必要的防火墙规则。为此,端口需要匹配您在公开容器端口时选择的端口。
(如果您遇到问题,请确保您的wider_world_to_container规则中没有将expose_via_ipv6设置为=。)
示例:通过IPv6访问web服务器
假设您想在Docker容器中运行一个web服务器,并且希望将您的主机端口号80和443用于HTTP和HTTPS以将流量转发到该容器。您使用的容器内部使用端口号8080和8443分别用于HTTP和HTTPS。
以下是您需要配置容器的步骤:
$ docker run \
--name "your_container" \
--network "your_network" \
--publish 80:8080 \
--publish 443:8443 \
...
这是您配置规则的方法
[[wider_world_to_container.rules]]
network = "your_network"
dst_container = "your_container"
expose_port = [
"80:8080",
"443:8443",
]
结果是,您的容器将从主机的80和443端口,无论是IPv4还是IPv6,都可访问。
重大更改
从v0.x到v1.x
从1.0版本开始,DFW引入了nftables后端,并将其作为默认的防火墙后端使用。如果您正在升级DFW但不想切换到nftables,您可以为DFW提供--firewall-backend iptables
参数(这需要至少DFW v1.2)。
请注意,无论您是否过渡到nftables,v1.0都对配置引入了重大更改。请参阅迁移文档了解如何更新您的配置。
支持的架构
DFW的Docker镜像预先构建了以下架构
amd64
(即x86_64
)arm64
(即aarch64
)arm / v7(特别是
armhf
)
您不需要做任何特别的事情来使用正确的架构:只需docker pull pitkley/dfw:1.3.0
。Docker会负责拉取与主机架构匹配的镜像。
一般来说,DFW应该能够在Rust支持的任何架构上运行,并且对于存在nftables
或iptables
二进制文件的架构。
支持的Docker版本
至少需要Docker 1.13.0。
DFW会持续自动测试以下稳定版本的Docker(使用最新的补丁版本)
24.0
23.0
20.10
19.03
18.09
18.06
18.03和1.13之间的Docker版本也应正常工作,但由于缺少Docker BuildKit支持,不再自动测试。
版本提升策略
一般来说,DFW的版本方案遵循语义版本规范
- 当进行向后兼容的修复时,会提升补丁版本(这包括对依赖项的更新)。
- 当引入新功能但保留向后兼容性时,会提升次要版本。
- 当进行向后不兼容的更改时,会提升主版本。
特殊情况
-
最小支持Rust版本(MSRV)的提升,对于DFW目前是1.67.0,将在次要版本更新中完成(即它们不需要主版本提升)。
-
DFW既可作为直接使用的二进制文件,也可作为crates.io上的库使用。
DFW的目标受众是二进制文件的用户,并且只提供基于最佳努力的库公共API支持。
因此,破坏库API的更改将在次要版本更新中完成,即库的消费者可能需要预期在非主要版本中的破坏性更改。
许可证
DFW根据您的选择,受以下任何一个许可证的许可
- Apache许可证第2版(《LICENSE-APACHE》或https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT许可证(《LICENSE-MIT》或https://open-source.org.cn/licenses/MIT》)
。
贡献
除非您明确声明,否则您根据Apache-2.0许可证定义的任何有意提交以包含在DFW中的贡献,应如上所述双重许可,无需任何附加条款或条件。
依赖项
~19-32MB
~510K SLoC