有个 Docker 的网络问题想问问大家

2024-01-06 12:58:04 +08:00
 TravisMtg


---

背景:如图,B 机器是 ArchLinux ,systemd-networkd 未开启 IPForward 。
1. 图中黑色的 ip 地址为校内局域网,A/B 处于 10.112.0.0/16 子网内,而 C 在另一个子网
2. 橙色地址为 tailscale 创建的局域网,B 和 C 都在 tailscale 创建的网络中

此时在 B 机器上启动一个 docker 服务,映射到 8080 端口,A 机器和 B 机器都可以正常通过 http://10.112.91.240:8080 访问;但是在机器 C 上则不行,通过 tailscale 的 ip 可以正常访问。

查阅文档后发现是 ArchLinux 的 systemd-networkd 默认没开 IPForward ,开启后一切正常。

---

问题:想询问下,为什么开启 IPForward 后就正常了?我理解是因为网络请求没有被宿主机转发到 docker0 上,但是这样解释不了相同网段的机器可以正常访问。查了点 docker 的资料感觉也云里雾里,求求各位指个路。
1468 次点击
所在节点    Docker
17 条回复
bruce0
2024-01-06 14:17:54 +08:00
我的理解, docker 默认是桥接模式, 黑色的 IP 默认和 docker 的虚拟网卡做了转发, 橙色的 IP 没有和 docker 的网络做转发

如果不正确 还请指正 我好学习一下
Andim
2024-01-06 14:56:33 +08:00
我脑中的信息过时了么? 10.112.0.0/16 10.129.0.0/16 这是两个不同的网段呀
This is what you need when you have for example a system setup that is sitting between two different networks and needs to pass traffic between them
Honkaiteio
2024-01-06 15:39:45 +08:00
B 机器上运行,就能让 10.129.0.0/16 网段访问 10.112.0.0/16

```bash
sudo tailscale up --advertise-routes=10.112.0.0/16
```


https://tailscale.com/kb/1019/subnets
IvanLi127
2024-01-06 16:19:45 +08:00
因为 b 机子没开转发的话,就不能像路由一样在两个网口之间交换数据。

大概这样,不太专业,我最近也在折腾组网,我是这么理解的
klo424
2024-01-06 16:41:53 +08:00
@Andim 建议先去了解一下 tailscale 。
Jat001
2024-01-06 16:53:39 +08:00
systemd-networkd 的 IPForward 跟 sysctl 直接修改 net.ipv4.ip_forward 等参数有什么区别?

sysctl -a | grep forward 我懒得试了,你看看开启前后有什么变化

参考资料:
https://wiki.archlinux.org/title/Systemd-networkd#[Network]
https://wiki.archlinux.org/title/Internet_sharing#Enable_packet_forwarding
Andim
2024-01-06 17:35:49 +08:00
@klo424 tailscale 可以从 C 以 http://10.112.91.240:8080 访问 B 么?没用过 tailscale
Andim
2024-01-06 17:47:12 +08:00
@Andim 花了几分钟搜了下,这个 tailscale 确实有路由 可以网段转换
TravisMtg
2024-01-06 20:35:16 +08:00
@Jat001
> systemd-networkd 的 IPForward 跟 sysctl 直接修改 net.ipv4.ip_forward 等参数有什么区别?
> sysctl -a | grep forward 我懒得试了,你看看开启前后有什么变化

这个我看 archlinux 论坛还有官方文档里面说的是 systemd-networkd 会把 sysctl 设置的东西覆盖掉,systemd-networkd 的 ipforward 默认 off ,修改为 on 之后应该是和 net.ipv4.ip_forward 的效果是一样的。

之前我试了试,前后的这个 net.ipv4.ip_forward 是一致的。
TravisMtg
2024-01-06 20:36:16 +08:00
@Andim 确实是两个不同网段。我这儿的表现是,相同网段的机器可以正常访问,但是不同网段则访问不了。
TravisMtg
2024-01-06 20:40:59 +08:00
@IvanLi127 嗯嗯,我大概也能理解到这儿。
我不太能理解的是——如果我的流量是从 tailscale 的网口进来的话,按道理也需要路由转发到 docker 才能访问到 docker 中的服务。但是在我开启 IPForward 之前,确实是可以通过 http://100.64.70.88:8080 访问的(也就是通过 tailscale 访问)。
(这儿的请求貌似没有吃到这个 IPForward=off 的规则
IvanLi127
2024-01-07 02:00:48 +08:00
@TravisMtg 我猜测是 docker 自己或者他配的规则已经能把所有网卡的这个端口的流量转给容器内了,所以 100.64.70.88 能访问,不能访问是出在 100.96.113.29 -> 100.64.70.88 -x -> 10.112.91.240 这个不能的地方需要机子开转发。
Jat001
2024-01-07 12:25:47 +08:00
tailscale 为什么能转发我知道,ip route show table all 看看就知道了,它给每个 ip 都配置了路由

不同网段,不同 interface 之间转发,要用 ip route add <cidr> via <gateway> dev <interface> 指定路由
Jat001
2024-01-07 12:30:43 +08:00
然后你再看看 tailscale 的 iptables 规则,还要加 iptables -t nat -A POSTROUTING -s <cidr> -j MASQUERADE 起到 nat 的效果
Jat001
2024-01-07 13:05:53 +08:00
再讲个好玩的,ip route add default via <gateway> dev <interface> 是添加默认路由,但你可以用 ip route add default via <gateway> dev <interface> table <table_id> 的方式只给某个 table 添加默认路由

table 有什么用呢,你可以用 ip rule 看看

ip rule add from <cidr> table <table_id> priority <更小的值> 可以让来自某个网段的流量走特定 table
同理,ip rule add to <cidr> ...,ip rule add fwmark <id> ... 等都可以
TravisMtg
2024-01-07 23:01:23 +08:00
@Jat001 ヽ( ̄▽ ̄)و
klo424
2024-01-08 08:26:42 +08:00
@Andim tailscale 可以从 C 以 http://100.64.70.88:8080 访问 B 。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1006389

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX