在某个节点上,容器进程 A 默认是将数据包发给容器进程 B ,考虑到进程 B 升级,需要将流量转到其他机器上。
使用 ebpf 劫持 connect 系统调用可以做,以及使用 tc-ebpf 实现 nat ,但是被否了!理由是不够安全,存在影响其他容器的风险。
有大佬说可以使用 tc mirror 将流量镜像到 tun ,走隧道,发给本地进程 B 的就 drop 掉(暂时还没弄明白,可不可行,有无大佬解答)
iptables contrack 被禁止使用,导致无法使用其 nat 能力。
求问实现如上功能的方式
1
FishBear 72 天前
haproxy
|
2
Charlie17Li OP @FishBear 感谢,不过事实上进程 A 和 B 是在同一个 Pod 中,如果引入另外一个
proxy 需要添加一个容器 C ,可能不太符合需求。 |
3
leconio 72 天前 via iPhone
感觉原理很像透明代理和分流。看看 tproxy?
|
4
Charlie17Li OP @leconio tproxy 会将流量发到机器的某个端口,然后透明代理进程监听这个端口并实现转发,这个实际上还是引入了一个 proxy 。
引入另外一个 proxy 的有两个风险:proxy 稳定性和资源占用;数据包从 app 发到内核后,又从内核发到 proxy ,接着 proxy 又将数据包发给内核,最终才转发出去,性能可能有一定影响,不过核心还是第一个风险。 |
5
zhangeric 72 天前
这个是端口转发吧
|
6
Charlie17Li OP @zhangeric 数据包需要转到另外一个机器上,端口转发是将数据包转到当前机器,不太一样?
|
7
bingfengfeifei 72 天前
感觉像是同时做 DNAT+SNAT ,然后转发到其他机器上。
本机:192.168.1.1 其他机器:192.168.1.2 两进程 localhost 通信 127.0.0.1:12345->127.0.0.1:8080 入站先使用 DNAT 变成 127.0.0.1:12345->192.168.1.2:80 出站使用 SNAT 变成 192.168.1.1:12345->192.168.1.2:80 这样其他机器的响应报文也可以发回来。 主要问题就是 localhost 好像和物理网卡的入站流量不太一样,iptables 拦截不太清楚能不能走到 PREROUTING 和 POSTROUTING 链,可能要开个 route_localnet 的选项 |
8
muziyu58 72 天前
@Charlie17Li A 机器端口数据包,转发到 B 机器端口上,看起来行得通呀
|
9
Charlie17Li OP @bingfengfeifei 是的,可以视作 FNAT(full nat)(疑似)
""" 入站先使用 DNAT 变成 127.0.0.1:12345->192.168.1.2:80 出站使用 SNAT 变成 192.168.1.1:12345->192.168.1.2:80 """ 这个入站是指其他机器发给本机的包吗? 如果是,实际上入站需要 SNAT ,将其他机器的 IP 改成 127.0.0.1 ;因为从本机的 client 看来,他是与本机(127.0.0.1)的进程通信,如果收到的包 src_ip 不是 127.0.0.1 就会发 RST 。这个我通过 epbf 做 NAT 时遇到过这个问题。 出站需要 DNAT ,将本地 server 从 127.0.0.1:80 改成 192.168.1.2:80 """ iptables 拦截不太清楚能不能走到 PREROUTING 和 POSTROUTING 链 """ lo 和 eth0 的出入流量均需要经过协议栈,理论上应该会经过,不过我没弄明白经过这两个链时可以做啥处理吗? """ 可能要开个 route_localnet 的选项 """ 目前,我正在使用 tc-nat 尝试,目前我的思路是: 当前本地通信的数据包流转是这样子的: client -> netfilter -> lo -> tc(egress) -> ... -> tc(ingress) -> netfilter -> server 我在 netfilter 的(OUTPUT)链中给流量打标记,然后在 ingress 处执行 DNAT ,试图通过 forward 链后发到 eth0 。 不过目前 ingress 处执行 DNAT 后,数据包并没有进入 eth0 ,而是被奇怪的丢掉了 route_localnet 这个参数大佬可以详细讲讲使用场景吗? |
10
Charlie17Li OP @muziyu58 很多实践是基于 Iptables nat 做的,我的场景里无法使用 Iptables-nat
|