我正在尝试使用 nginx 反向代理(不在容器中,而是在主机上)在 docker 容器中设置一个简单的 web 应用程序。
以下是我运行容器的方式:
docker run -d --name mywebapp -v /webapp/:/data/ --restart unless-stopped -p 5665:80 mywebapp/server:latest
Web 应用程序监听80
容器内的端口,我将其转发到5665
主机端口。
nginx 反向代理监听端口5666
并将请求转发到转发的容器端口5665
。
输出netstat -lntup
(仅相关行):
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:5666 0.0.0.0:* LISTEN 29369/nginx: master
tcp 0 0 0.0.0.0:5665 0.0.0.0:* LISTEN 151974/docker-proxy
我想配置防火墙来阻止除5666
端口之外的所有外部连接。
以下是我的nftables
规则(精确复制,没有删除任何内容):
define IIFNAME = "ens3";
table inet filter {
chain input {
type filter hook input priority filter
policy drop
ct state invalid drop comment "early drop of invalid connections"
ct state {established, related} accept comment "allow tracked connections"
iifname lo accept comment "allow from loopback"
ip protocol icmp accept comment "allow icmp"
meta l4proto ipv6-icmp accept comment "allow icmp v6"
tcp dport ssh accept comment "allow sshd"
tcp dport 5666 accept comment "webserver";
pkttype host limit rate 5/second counter reject with icmpx type admin-prohibited
counter
}
chain forward {
type filter hook forward priority filter
policy drop
iifname "docker0" oifname $IIFNAME accept;
iifname $IIFNAME oifname "docker0" accept;
}
我可以连接到端口5666
,这是预期和期望的。但是,问题是,尽管到5665
端口的连接被阻止(至少我是这样认为的),我仍然可以连接到5665
端口,绕过 nginx 反向代理。
经过反复试验后,我发现问题出在“前向”链规则上,即:
iifname "docker0" oifname $IIFNAME accept;
iifname $IIFNAME oifname "docker0" accept;
删除这些规则可以解决这个问题,但也会阻止容器访问互联网。
我的两个问题:
为什么“转发”规则如此重要?我认为“转发”规则仅适用于数据包应该由另一台机器(或容器)接收的情况。但是,端口
5665
正在通过 监听当前主机端口docker-proxy
。即使数据被“转发”到容器,它也不是由内核转发的,而是由用户空间应用程序转发的 -docker-proxy
,因此我希望内核使用INPUT
chain 而不是FORWARD
chain。然而,规则似乎确实FORWARD
很重要。(也许这个问题的答案在有了上一个问题的答案之后就很清楚了,但我还是会问)我如何阻止
5665
从外部(从接口)访问转发端口,同时允许容器访问互联网(即通过主机上的接口ens3
发出请求)?ens3