我需要通过 AWS 网络负载均衡器在 Kubernetes 中公开 wireguard 服务。
除非健康检查通过,否则负载均衡器不会将流量路由到我的 wireguard pod。由于 AWS 负载均衡器不支持 UDP 健康检查,而 wireguard 在 UDP 上运行,因此我将一个简单的 TCP 服务连接到 wireguard pod,但无法访问,因此健康检查失败。
这是相关的 yaml 部署规范片段。
spec:
containers:
- name: "wireguard"
image: "linuxserver/wireguard:latest"
ports:
- containerPort: 51820
protocol: UDP
securityContext:
privileged: true
capabilities:
add:
- NET_ADMIN
- name: healthcheck
image: istio/tcp-echo-server:latest
imagePullPolicy: IfNotPresent
args: [ "9000", "hello" ]
ports:
- containerPort: 9000
如果我省略 wireguard 容器,或者注释掉 NET_ADMIN 部分,从而确保没有网络配置被更改,我就可以成功访问 heathcheck pod,例如运行:
kubectl run -i --rm --restart=Never dummy --image=busybox -- sh -c "echo world | nc wireguard-service.wg-test 9000"
hello world
在 wireguard 的容器日志中,我可以看到这些命令正在执行。我怀疑节点的路由配置中发生了一些变化,导致端口 9000 变得无法访问。
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.11.0.1/16 dev wg0
[#] ip link set mtu 1450 up dev wg0
[#] wg set wg0 fwmark 51820
[#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
[#] ip -4 rule add not fwmark 51820 table 51820
[#] ip -4 rule add table main suppress_prefixlength 0
[#] sysctl -q net.ipv4.conf.all.src_valid_mark=1
[#] iptables-restore -n
[#] iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
[#] sysctl -w -q net.ipv4.ip_forward=1
我尝试添加,iptables -A INPUT -p tcp --dport 9000 -j ACCEPT
但iptables -A FORWARD -p tcp --dport 9000 -j ACCEPT
无济于事。我这里遗漏了什么?
当您使用wg-quick(
AllowedIPs = 0.0.0.0/0
例如您的 WireGuard 容器使用)时,wg-quick 将设置一个自定义路由表,其中包含一些自定义策略路由规则,以通过 WireGuard 隧道路由所有 IPv4 流量(WireGuard 自己的流量和与主表中的明确路由匹配的数据包除外)。由于您不想通过 WireGuard 隧道路由健康检查服务的响应,因此您需要在 pod 中设置自己的自定义策略路由规则以覆盖 wg-quick 的规则。类似下面的规则应该可以解决问题:
由于此规则的优先级值(100)低于 wg-quick 设置的规则,因此它将在它们之前进行评估(wg-quick 的规则配置时没有明确的优先级值,因此它们将在 32000 年代自动分配优先级)。此规则将匹配从健康检查服务的 TCP 端口 9000 发送的数据包,并使用 pod 的主路由表来路由它们。