iptables 在 PREROUTING 链的末尾使用 docker DNAT 静默丢弃数据包,而不是继续 INPUT 链

如何解决iptables 在 PREROUTING 链的末尾使用 docker DNAT 静默丢弃数据包,而不是继续 INPUT 链

我有一个 docker compose 文件,其中包含 2 个服务,我想同时侦听端口 80,但使用不同的 IP 地址(反向代理不适合这些)。我有一个带有单独 IP 的虚拟网络接口,供第二个服务侦听。 当我列出要绑定到的服务的特定 IP 地址时,无法再从网络访问它。但它是在没有指定 IP 并且只有 1 个服务绑定到端口 80 的情况下。

示例: 当我的 docker-compose 文件包含:

    ports:
      - "192.168.1.2:80:80"

我可以使用 curl 192.168.1.2 从我的本地机器成功连接,但不能从本地网络上的机器连接。

但是,当我的 docker-compose 文件包含:

    ports:
      - "80:80"

我可以使用 curl 192.168.1.2 从网络成功连接。这是我之前绑定的同一个IP!所以这显然是我的一个网络接口的 IP 地址。

它似乎与防火墙无关,因为如果我运行 sudo python3 -m http.server 80 --bind 192.168.1.2,我也可以从网络访问它。那么为什么 docker 在配置了特定的 IP 地址后不会响应外部请求呢?

编辑: 是的,我使用 Linux。来自 iptables -t nat -S 的输出,为端口 80 指定了 IP:

-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N DOCKER
-N OUTPUT_direct
-N POSTROUTING_ZONES
-N POSTROUTING_ZONES_SOURCE
-N POSTROUTING_direct
-N POST_public
-N POST_public_allow
-N POST_public_deny
-N POST_public_log
-N PREROUTING_ZONES
-N PREROUTING_ZONES_SOURCE
-N PREROUTING_direct
-N PRE_public
-N PRE_public_allow
-N PRE_public_deny
-N PRE_public_log
-A PREROUTING -j PREROUTING_direct
-A PREROUTING -j PREROUTING_ZONES_SOURCE
-A PREROUTING -j PREROUTING_ZONES
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT -j OUTPUT_direct
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 192.168.240.0/20 ! -o br-d7a59c2d8d7f -j MASQUERADE
-A POSTROUTING -s 172.18.0.0/16 ! -o br-a6d78077661d -j MASQUERADE
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -j POSTROUTING_direct
-A POSTROUTING -j POSTROUTING_ZONES_SOURCE
-A POSTROUTING -j POSTROUTING_ZONES
-A POSTROUTING -s 192.168.240.4/32 -d 192.168.240.4/32 -p tcp -m tcp --dport 8080 -j MASQUERADE
-A POSTROUTING -s 172.18.0.2/32 -d 172.18.0.2/32 -p tcp -m tcp --dport 53 -j MASQUERADE
-A POSTROUTING -s 192.168.240.4/32 -d 192.168.240.4/32 -p tcp -m tcp --dport 7890 -j MASQUERADE
-A POSTROUTING -s 172.18.0.2/32 -d 172.18.0.2/32 -p udp -m udp --dport 53 -j MASQUERADE
-A POSTROUTING -s 192.168.240.4/32 -d 192.168.240.4/32 -p tcp -m tcp --dport 443 -j MASQUERADE
-A POSTROUTING -s 192.168.240.4/32 -d 192.168.240.4/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A DOCKER -i br-d7a59c2d8d7f -j RETURN
-A DOCKER -i br-a6d78077661d -j RETURN
-A DOCKER -i docker0 -j RETURN
-A DOCKER ! -i br-d7a59c2d8d7f -p tcp -m tcp --dport 8080 -j DNAT --to-destination 192.168.240.4:8080
-A DOCKER ! -i br-a6d78077661d -p tcp -m tcp --dport 53 -j DNAT --to-destination 172.18.0.2:53
-A DOCKER ! -i br-d7a59c2d8d7f -p tcp -m tcp --dport 7890 -j DNAT --to-destination 192.168.240.4:7890
-A DOCKER ! -i br-a6d78077661d -p udp -m udp --dport 53 -j DNAT --to-destination 172.18.0.2:53
-A DOCKER ! -i br-d7a59c2d8d7f -p tcp -m tcp --dport 443 -j DNAT --to-destination 192.168.240.4:443
-A DOCKER -d 192.168.1.2/32 ! -i br-d7a59c2d8d7f -p tcp -m tcp --dport 80 -j DNAT --to-destination 192.168.240.4:80
-A POSTROUTING_ZONES -o eth0 -g POST_public
-A POSTROUTING_ZONES -g POST_public
-A POST_public -j POST_public_log
-A POST_public -j POST_public_deny
-A POST_public -j POST_public_allow
-A PREROUTING_ZONES -i eth0 -g PRE_public
-A PREROUTING_ZONES -g PRE_public
-A PRE_public -j PRE_public_log
-A PRE_public -j PRE_public_deny
-A PRE_public -j PRE_public_allow

在添加 TRACE 规则后,我发现外部数据包遵循 PREROUTING 链一直到相关的 DNAT 规则。日志摘录:

TRACE: nat:PREROUTING:rule:4 IN=eth0 OUT= MAC=52:54:00:83:f9:b4:50:ed:3c:23:4d:b9:08:00 SRC=192.168.1.250 DST=192.168.1.2 LEN=64 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=49864 DPT=80 SEQ=400376858 ACK=0 WINDOW=65535 RES=0x00 SYN URGP=0 OPT (020405B4010303060101080A7F6085070000000004020000)

TRACE: nat:DOCKER:rule:9 IN=eth0 OUT= MAC=52:54:00:83:f9:b4:50:ed:3c:23:4d:b9:08:00 SRC=192.168.1.250 DST=192.168.1.2 LEN=64 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=49864 DPT=80 SEQ=400376858 ACK=0 WINDOW=65535 RES=0x00 SYN URGP=0 OPT (020405B4010303060101080A7F6085070000000004020000)

但随后这条路就结束了。它不会继续使用 INPUT 或 FILTER 链。由于我使用的 ip 是虚拟接口的 ip,我在通过 sysctl -w net.ipv4.conf.all.rp_filter=2 读取 https://serverfault.com/questions/586628/packets-sent-on-virtual-ip-dont-hit-iptables-rule?newreg=edb07f9ec9ee416f8bd012ee6d94b8b9 后尝试禁用严格 RPF。然而这并没有帮助。我还尝试将 192.168.1.2 替换为 192.168.1.238,这是物理网卡的 ip,结果类似。 nstat -rsz | grep IPReversePathFilter 计数器在请求之间也没有增加。我不明白为什么只是默默地丢弃了数据包。


我意识到我的网络服务器本身实际上并不需要被 pihole 阻止广告,所以我决定为这个 docker 容器使用 macvlan 网络。这也为其提供了一个单独的 IP 地址,但需要注意的是,它与主机的其余部分无法相互通信。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com(将#修改为@)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?