当 Linux conntrack 不再是你的朋友时

当 Linux conntrack 不再是你的朋友时

连接跟踪(“conntrack”)是 Linux 内核网络堆栈的核心功能。 它允许内核跟踪所有逻辑网络连接或流,从而识别构成每个流的所有数据包,以便可以按顺序一起处理它们。

Conntrack 是一个重要的内核功能,在一些基本情况下会用到:

  • NAT 依赖于来自 conntrack 的信息,因此它可以平等地对待来自同一流的所有数据包。 例如,当 Pod 访问 Kubernetes 服务时,kube-proxy 负载均衡器使用 NAT 将流量定向到集群内的特定 Pod。 Conntrack 记录对于给定的连接,所有发往 IP 服务的数据包都必须发送到同一个 pod,并且后端 pod 返回的数据包必须通过 NAT 回到发出请求的 pod。
  • Calico 等状态防火墙依赖来自 connecttrack 的信息将“响应”流量列入白名单。 这允许您编写一个网络策略来表示“允许我的 pod 连接到任何远程 IP 地址”,而无需编写策略来显式允许响应流量。 (如果没有这个,您将不得不添加安全性低得多的“允许数据包从任何 IP 发送到我的 pod”规则。)

此外,conntrack 通常会提高系统性能(通过减少 CPU 消耗和数据包延迟),因为只有流中的第一个数据包
必须遍历整个网络堆栈来确定如何处理它。 参见帖子“kube-proxy模式对比” 查看其工作原理的示例。

然而,conntrack 有其局限性......

那么这一切到底是哪里出了问题呢?

conntrack 表具有可配置的最大大小,如果它已满,连接通常会开始被拒绝或丢弃。 表中有足够的可用空间来处理大多数应用程序的流量,这永远不会成为问题。 但是,在某些情况下您可能需要考虑使用 conntrack 表:

  • 最明显的情况是您的服务器处理大量并发活动连接。 例如,如果您的 conntrack 表配置为 128k 条目,但您有 >128k 并发连接,那么您肯定会遇到问题!
  • 一个不太明显的情况:如果您的服务器每秒处理大量连接。 即使连接是短暂的,Linux 也会继续监视它们一段时间(默认为 120 秒)。 例如,如果您的 conntrack 表配置为 128k 条目,并且您尝试每秒处理 1100 个连接,则即使连接非常短暂(128k/120s = 1092 个连接/秒),它们也将超出 conntrack 表的大小)。

有几种利基类型的应用程序属于这些类别。 此外,如果您有很多不良行为者,则用大量半打开连接填充服务器的 conntrack 表可能会被用作拒绝服务 (DOS) 攻击的一部分。 在这两种情况下,conntrack 都可能成为系统中的限制瓶颈。 在某些情况下,调整 conntrack 表参数可能足以满足您的需求 - 通过增加大小或减少 conntrack 超时(但如果您做错了,您将遇到很多麻烦)。 对于其他情况,有必要绕过 conntrack 以获取攻击性流量。

真实例子

让我们举一个具体的例子:我们合作的一家大型 SaaS 提供商在主机(不是虚拟机)上有许多 memcached 服务器,每个服务器每秒处理 50K 以上的短期连接。

他们尝试了 conntrack 配置,增加表大小并减少跟踪时间,但配置不可靠,RAM 消耗显着增加,这是一个问题(大约是 GBytes!),而且连接太短,conntrack 没有创建其通常的性能优势(减少 CPU 消耗或数据包延迟)。

他们转向 Calico 作为替代方案。 Calico 网络策略允许您不对某些类型的流量使用 conntrack(使用 doNotTrack 策略选项)。 这为他们提供了所需的性能水平,以及 Calico 提供的附加安全级别。

你需要走多远才能绕过 conntrack?

  • 不跟踪网络策略通常应该是对称的。 对于 SaaS 提供商来说:他们的应用程序在受保护区域内运行,因此,使用网络策略,他们可以将来自允许访问 memcached 的其他特定应用程序的流量列入白名单。
  • 不跟踪策略不考虑连接的方向。 因此,如果 memcached 服务器被黑客攻击,理论上您可以尝试连接到任何 memcached 客户端,只要它使用正确的源端口即可。 但是,如果您为 memcached 客户端正确定义了网络策略,那么这些连接尝试仍将在客户端被拒绝。
  • 不跟踪策略应用于每个数据包,这与仅应用于流中的第一个数据包的普通策略相反。 这会增加每个数据包的 CPU 消耗,因为必须对每个数据包应用该策略。 但对于短期连接,此费用可以通过减少 conntrack 处理的资源消耗来平衡。 例如,对于 SaaS 提供商,每个连接的数据包数量非常小,因此对每个数据包应用策略时的额外 CPU 消耗是合理的。

让我们开始测试

我们在具有 memcached 服务器的单个 Pod 和在远程节点上运行的多个 Memcached 客户端 Pod 上运行测试,以便我们每秒可以运行大量连接。 具有 memcached 服务器 Pod 的服务器有 8 个核心,conntrack 表中有 512k 条目(主机的标准配置表大小)。
我们测量了以下之间的性能差异:无网络策略; 符合常规 Calico 政策; 和 Calico 不跟踪政策。

对于第一个测试,我们将连接数设置为每秒 4.000 个,因此我们可以重点关注 CPU 消耗的差异。 无策略和常规策略没有显着差异,但 do-not-track 的 CPU 消耗增加了约 20%:

当 Linux conntrack 不再是你的朋友时

在第二个测试中,我们启动了客户端可以生成的尽可能多的连接,并测量了 memcached 服务器每秒可以处理的最大连接数。 正如预期的那样,“无策略”和“常规策略”情况都达到了每秒超过 4,000 个连接的 conntrack 限制(512k / 120s = 4,369 个连接/秒)。 通过不跟踪策略,我们的客户每秒发送 60,000 个连接,没有出现任何问题。 我们确信可以通过添加更多客户端来增加这个数字,但我们认为这些数字已经足以说明本文的要点!

当 Linux conntrack 不再是你的朋友时

结论

Conntrack 是一个重要的内核功能。 他完美地完成了他的工作。 它经常被关键系统组件使用。 然而,在某些特定场景下,conntrack 造成的拥塞超过了它提供的正常好处。 在这种情况下,Calico 网络策略可用于选择性地禁用 conntrack,同时提高网络安全性。 对于所有其他流量,conntrack 仍然是您的朋友!

另请阅读我们博客上的其他文章:

来源: habr.com

添加评论