如何:Podman rootless 将容器端口暴露给外部并查看真实的客户端 IP

Saq*_*ria 4 networking debian nftables podman rootless

这是我第一次在 stackoverflow 上问问题。我已经潜伏多年,但现在我终于决定自己注册。因此,如果我的问题/信息格式不正确,我深表歉意。

现在的情况:

我慢慢地越来越熟悉 Podman,并且正在将一些容器从 docker(有根)转移到 podman(无根)。我在Debian 11上使用Podman 4.3.1。我已经设法让一些容器正常工作并且能够从外部连接到它们。但是,容器显示客户端/源 IP“127.0.0.1”,而不是我真实客户端的 IPv4。我想知道下面这样的事情是否可能?

理想情况:

为容器分配特定的 IPv4(无根)。使用 nftables/iptables 将数据包从主机网络转发到容器 ipv4(例如 192.168.1.12)。能够在容器中看到真实客户端的 IPv4,仍然能够使用fail2ban 等。

正如您可能注意到的,我仍然处于学习容器化如何工作的过程中,特别是对于网络而言。出于安全原因,我不想将主机网络用于我的容器。如果有不清楚的地方请告诉我,我会尽力更好地解释自己。

感谢您花时间阅读本文:)

lar*_*sks 5

当您以非 root 用户身份运行 Podman 时,代表容器接口的虚拟Tap 设备eth0无法直接连接到桥接设备。这意味着无法使用 netfilter 规则将流量引导到容器中;相反,Podman 依赖于代理进程。

这里有一些关于此配置的注释。

默认情况下,Podman 使用代理rootlessport,它将连接的源 ip 替换为容器命名空间中的内部 ip。但是,您可以显式请求 Podman 用作slirp4netns端口处理程序,这保留源地址,但会牺牲一些性能。

例如,如果我启动一个这样的容器:

podman run --name darkhttpd --rm -p 8080:8080 docker.io/alpinelinux/darkhttpd
Run Code Online (Sandbox Code Playgroud)

然后从某处连接到此:

curl 192.168.1.200:8080
Run Code Online (Sandbox Code Playgroud)

我会在访问日志中看到:

10.0.2.100 - - [12/Feb/2023:15:30:54 +0000] "GET / HTTP/1.1" 200 354 "" "curl/7.85.0"
Run Code Online (Sandbox Code Playgroud)

10.0.2.100实际上容器的地址在哪里:

$ podman exec darkhttpd ip a show tap0
2: tap0: <BROADCAST,UP,LOWER_UP> mtu 65520 qdisc fq_codel state UNKNOWN qlen 1000
    link/ether 26:77:5b:e8:f4:6e brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.100/24 brd 10.0.2.255 scope global tap0
       valid_lft forever preferred_lft forever
    inet6 fd00::2477:5bff:fee8:f46e/64 scope global dynamic flags 100
       valid_lft 86391sec preferred_lft 14391sec
    inet6 fe80::2477:5bff:fee8:f46e/64 scope link
       valid_lft forever preferred_lft forever
Run Code Online (Sandbox Code Playgroud)

但是如果我明确请求slirp4netns作为端口处理程序:

podman run --name darkhttpd --rm -p 8080:8080 --network slirp4netns:port_handler=slirp4netns docker.io/alpinelinux/darkhttpd
Run Code Online (Sandbox Code Playgroud)

然后在访问日志中我将看到请求的实际源ip:

192.168.1.97 - - [12/Feb/2023:15:32:17 +0000] "GET / HTTP/1.1" 200 354 "" "curl/7.74.0"
Run Code Online (Sandbox Code Playgroud)

在大多数情况下,您不想依赖源 IP 地址来进行身份验证/授权,因此默认行为是有意义的。

如果您需要远程 IP 进行日志记录,则此处提供的选项将起作用,或者您也可以考虑在全局命名空间中运行前端代理,将客户端 IP 放入标头中X-Forwarded-For并将其用于日志。