我正在使用裸机 Kubernetes 集群(使用 calico CNI 插件),在将外部流量重定向到节点时遇到了麻烦。我设置了 nginx kubernetes 入口控制器,以便通过NodePort
(在端口 30528 上)公开 HTTPS 服务。我可以在端口 30528 上正常访问该服务,因此流量是在 kubernetes 中被正确重定向。
当然,我希望将其暴露在端口 443 上,而不是 30528 上,因此我使用了通常用于服务器进行端口重新映射的工具 --- 端口重定向 iptables 规则。这个特定的系统使用 shorewall 来管理 iptables 规则,我对此很熟悉,所以很好。我从一个测试 shorewall 规则开始,将端口 1443 重定向到 30528。shorewall 规则如下所示:
REDIRECT net 30528 tcp 1443
对于那些不熟悉 shorewall 的人来说,这会在PREROUTING
表中生成一个条目,如下所示:
$ iptables -t nat -L -v -n
Chain PREROUTING (policy ACCEPT 160 packets, 8642 bytes)
pkts bytes target prot opt in out source destination
<snip k8s/calico rules>
0 0 REDIRECT tcp -- eth0 * 192.168.1.0/24 0.0.0.0/0 tcp dpt:1443 redir ports 30528
<snip following rules>
<snip following chains>
当我尝试从服务器外部连接到该端口时,发生了一些奇怪的事情。
$ curl -v -v https://<server-ip>:1443/
* Trying 192.168.3.1:1443...
* Connected to <hostname> (<server-ip>) port 1443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
然后 TCP 连接就会挂起,直到我将其终止。Wireshark 显示正在发送 TLS Client Hello
、服务器ACK
正在发送数据包,以及每 60 秒发送一次的 TCP Keep-Alive,但没有任何内容能够到达 Kubernetes。如果我使用redir
从 1443 到 30528 的反弹连接,一切都会正常工作。(当然,如果我将 1443 重定向到端口 2000 并使用 netcat 监听端口 2000,一切都会按预期工作,所以我不会思考设置的其他部分是否存在任何异常。
有人知道这里可能出了什么问题吗?对我来说最有意义的事情是,由于 calico/kubernetes 在PREROUTING
iptables 之前将其自己的重定向规则插入表中redir
,因此由于排序而错过了对端口 30528 的处理。不过,在这种情况下,我真的很困惑为什么连接实际上是建立的 --- 我本以为它只是简单地失败!
(由于这台机器位于另一个用于 NAT 的防火墙后面,我可以调整防火墙,将发往端口 443 的流量重定向到 30528,这个问题易溶,但我更愿意弄清楚发生了什么,以供将来参考......)