Dockerコンテナ用の透過的なプロキシを構築するために、TPROXYがどのように機能するかを理解しようとしています.
多くの調査の後、私はネットワーク名前空間を作成し、そこに 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
その後、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()
そして最後に、実行ip netns exec ns0 curl 1.2.4.8することで からの接続を観察し、「hello world」メッセージを受け取る192.168.3.2ことができました。1.2.4.8
問題は、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 を正常に動作させるにはどうすればよいですか?