问题描述
在使用 Docker 时面临一个需求,需要让 Docker 容器 C 能够在不被容器 A 和容器 B 察觉的情况下拦截它们之间的通信。实际上,用户在试图对自己的容器执行标准的中间人攻击。目前容器 A 和容器 B 是桥接模式的。用户尝试了不同的 com.docker.network.bridge
选项,但似乎没有一个有效的方法。用户的网络配置如下:
[
{
"Name": "PKKJKO6WJEVH936CQ12H",
"Id": "5033f8958b845153f94beaa4b3bdbe17879ee331ad9441737687eac70b37fbc4",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1/16"
}
]
},
"Containers": {
"41411a497edf7a632b042d71879d1c0b5941af0361325d2dbe4fefa9bbb30727": {
"Name": "insane_goldstine",
"EndpointID": "5c9ffaa6270e8a1823464fa1cdd9f64868083d32cfc7576a5843b1c76944353f",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
},
"849135f83dca0d7261f03952b1648851dfb4c85a0cda0a7d1f5ab5b24e31a014": {
"Name": "berserk_ramanujan",
"EndpointID": "68a1ac542dea9fcfa1e35a209f571fc8c670f8d8ec33cf126c4dcde1bca1729d",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
},
"af80dbfaf424fb4b8ce192a8d2e0e946d97ae1abb731bf3fc75918d31c084625": {
"Name": "clever_goldwasser",
"EndpointID": "0b2b3a4d24b63168abfbd0d32138ead9f1e053de60a1ac4487b2af87938e7cbd",
"MacAddress": "02:42:ac:12:00:04",
"IPv4Address": "172.18.0.4/16",
"IPv6Address": ""
}
},
"Options": {}
}
]
用户怀疑 Docker 桥接模式的行为类似标准的网络桥接,即学习哪个 MAC 地址在哪里,并且不会将流量发送到其他地方。用户希望了解 Docker 桥接是否可以配置为更像是网络集线器(hub)的行为,可能是通过保持其 MAC 内存为空,或者持续擦除的方式来实现?
综上所述,用户的问题是,是否有办法配置 Docker 或容器 C 以便 C 可以监听流量?
解决方案
请注意以下操作可能需要iptables,根据你的环境和需求进行安装和配置。
方案1
根据最佳回答,用户可以使用 iptables 来实现目标。用户可以添加一个简单的规则,允许容器 C 接收来自容器 A 和容器 B 之间的流量,并实现拷贝(clone)的效果。下面是示例命令:
sudo iptables -I FORWARD -s <Container1 IP> -j TEE --gateway <Wireshark Container IP>
sudo iptables -I FORWARD -s <Container2 IP> -j TEE --gateway <Wireshark Container IP>
通过以上操作,用户可以将容器 A 和容器 B 之间的所有流量克隆到 Wireshark 容器,从而实现监听的目的。
请注意,这个解决方案是一个概念验证,可能需要根据实际需求进行进一步的优化和配置。
方案2(补充)
使用脚本或工具来管理容器的启动顺序可能会增加复杂性,并且需要确保容器 A 和容器 B 之间的依赖关系正确设置。
另一种方法是编写脚本或使用工具来控制容器的运行顺序。用户可以使用docker run
命令来手动控制容器的启动顺序,或者使用一些第三方工具来管理容器的依赖关系。
以下是一个简单的 Bash 脚本示例,可以在容器 A 启动后启动容器 B:
#!/bin/bash
# 启动容器 A
docker run -d --name container_a your_image_a
# 等待容器 A 完全启动
while ! docker exec container_a echo "Container A is ready"; do
sleep 1
done
# 启动容器 B
docker run -d --name container_b your_image_b
在这个示例中,我们首先使用 docker run
命令启动容器 A,并将其命名为 container_a
。然后,使用一个循环来等待容器 A 完全启动(这里是通过在容器内运行 echo
命令来测试)。一旦容器 A 就绪,我们再使用 docker run
命令启动容器 B,并将其命名为 container_b
。
这种方法可以保证容器 A 启动后再