TPROXY 与 Docker 的兼容性

vin*_*163 5 sockets iptables transparentproxy docker

我试图了解 TPROXY 如何工作,以便为 Docker 容器构建透明代理。

经过大量研究,我设法创建一个网络命名空间,向其中注入一个 veth 接口并添加 TPROXY 规则。以下脚本适用于干净的 Ubuntu 18.04.3:

ip netns add ns0
ip link add br1 type bridge
ip link add veth0 type veth peer name veth1
ip link set veth0 master br1
ip link set veth1 netns ns0
ip addr add 192.168.3.1/24 dev br1
ip link set br1 up
ip link set veth0 up
ip netns exec ns0 ip addr add 192.168.3.2/24 dev veth1
ip netns exec ns0 ip link set veth1 up
ip netns exec ns0 ip route add default via 192.168.3.1
iptables -t mangle -A PREROUTING -i br1 -p tcp -j TPROXY --on-ip 127.0.0.1 --on-port 1234 --tproxy-mark 0x1/0x1
ip rule add fwmark 0x1 tab 30
ip route add local default dev lo tab 30
Run Code Online (Sandbox Code Playgroud)

之后,我从Cloudflare 博客启动了一个玩具 Python 服务器:

import socket

IP_TRANSPARENT = 19

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setsockopt(socket.IPPROTO_IP, IP_TRANSPARENT, 1)

s.bind(('127.0.0.1', 1234))
s.listen(32)
print("[+] Bound to tcp://127.0.0.1:1234")
while True:
    c, (r_ip, r_port) = s.accept()
    l_ip, l_port = c.getsockname()
    print("[ ] Connection from tcp://%s:%d to tcp://%s:%d" % (r_ip, r_port, l_ip, l_port))
    c.send(b"hello world\n")
    c.close()
Run Code Online (Sandbox Code Playgroud)

最后,通过运行,ip netns exec ns0 curl 1.2.4.8我能够观察到连接192.168.3.21.2.4.8接收“hello world”消息。

问题是它似乎与 Docker 存在兼容性问题。在干净的环境中一切都运行良好,但是一旦我启动 Docker,事情就开始出错。TPROXY 规则似乎不再起作用。运行ip netns exec ns0 curl 192.168.3.1给出“连接重置”并且运行ip netns exec ns0 curl 1.2.4.8超时(两者都应该产生“hello world”消息)。我尝试恢复所有 iptables 规则,删除 Docker 生成的 ip 路由和规则并关闭 Docker,但即使我没有配置任何网络或容器,也没有任何效果。

幕后发生了什么以及如何让 TPROXY 正常工作?

c10*_*0ud 0

尝试使用-p 1234\n
\n运行docker“默认情况下,当您创建容器时,它不会向外界发布任何端口。要使端口可用于Docker外部的服务,或未连接的Docker容器对于容器\xe2\x80\x99s 网络,请使用 --publish 或 -p 标志。”

\n\n

https://docs.docker.com/config/containers/container-networking/

\n