在 lxc 容器中通过 url 访问网页

在 lxc 容器中通过 url 访问网页

我在 lxc 容器中安装了一个 Web 服务器。借助以下 iptable 规则,外界可以通过其 URL 访问此 Web 服务器:

sudo iptables -t nat -A PREROUTING -i eno1 -p tcp --dport 80 -j DNAT --to 10.42.XXX.XXX:80

我的问题是,当我尝试访问我的网络服务器时来自 lxc 容器网络服务器本身,它不起作用。

curl http://my.url.com
curl: (7) Failed to connect to my.url.com port 80: Connection refused

请注意,它在另一台计算机上也能正常运行。

我尝试添加另一条 iptable 规则:

sudo iptables -t nat -A PREROUTING -i lxcbr0 -p tcp --dport 80 -j DNAT --to 10.42.XXX.XXX:80

我得到:

curl http://my.url.com
curl: (7) Failed to connect to my.url.com port 80: Connection timed out

答案1

添加第二条 PREROUTING 规则后,容器会收到镜像到自身的请求,其源 IP 为源(以及目标)。出于各种原因,这种做法行不通:rp_filter 触发、网络堆栈不知道此连接尝试(它将其发送到 my.url.com,而不是自身)等。如果同一 LAN 中有第二个容器执行请求,则仍会存在非对称路由 + NAT 问题,从而导致其无法正常工作。

如果不改变,那就行不通了源地址。所以最后必须做双重NAT。

用这条规则来完成已经完成的事情:

sudo iptables -t nat -A POSTROUTING -o lxcbr0 -s 10.42.XXX.XXX -j SNAT 10.43.XXX.XXX

它将正常工作,因为唯一的 IP 10.42.XXX.XXX 是即将lxcbr0 而不是是上一个 PREROUTING DNAT 规则触发的时间。请注意,现在是 43,不再是 42,而是 10.43.XXX.XXX。在日志中仍然很容易知道请求来自哪里,因为那将在本例中保留。任何 IP 都可以,无论是公共的、私有的、现有的还是不存在的,甚至属于 LXC 主机(例如:my.url.com),只要它不在同一个 LAN 并且由 LXC 主机路由

作为一种变体,可以使用 NETMAP 对整个子网进行 NAT,从而允许 lxcbr0 后面的其他容器执行相同的请求,而不再存在路由问题,并且仍然具有有用的日志。因此,对于 /24,以前的规则将是(OP 的信息不够精确,无法猜测 LAN 网络掩码是什么。对于 /16,将下面的规则替换为 10.42.0.0/16 和 10.43.0.0/16):

sudo iptables -t nat -A POSTROUTING -o lxcbr0 -s 10.42.XXX.0/24 -j NETMAP 10.43.XXX.0/24

还有一个问题:使用 OP 的第二条规则进行测试,容器无法再在互联网上执行 http 请求,因为每个请求都会返回到 10.42.XXX.XXX。因此,最终使用这 2 条规则重写并分解总共 3 条规则可能会更有用:

sudo iptables -t nat -A PREROUTING -d my.url.com -p tcp --dport 80 -j DNAT --to 10.42.XXX.XXX
sudo iptables -t nat -A POSTROUTING -o lxcbr0 -s 10.42.XXX.0/24 -j NETMAP --to 10.43.XXX.0/24

完成此操作后,即可从 LXC 执行相同的请求主持人本身:

sudo iptables -t nat -A OUTPUT -d my.url.com -p tcp --dport 80 -j DNAT --to 10.42.XXX.XXX

更复杂的情况可能需要在 PREROUTING 中标记数据包并在 POSTROUTING 中匹配标记,但这里不需要。

相关内容