领事 + iptables = :3

2010年公司 战争游戏 有 50 台服务器和一个简单的网络模型:后端、前端和防火墙。 服务器数量增加,模型变得更加复杂:带有 ACL 的暂存、隔离 VLAN,然后是带有 VRF 的 VPN、在 L2 上带有 ACL 的 VLAN、在 L3 上带有 ACL 的 VRF。 头在旋转? 以后会更好玩的。

当服务器数量达到 16 台时,面对如此多的异构网段,要想不流泪地工作就变得不可能了。 所以我们想出了另一个解决方案。 我们采用了 Netfilter 堆栈,将 Consul 添加到其中作为数据源,这样我们就得到了一个快速的分布式防火墙。 他们替换了路由器上的 ACL,并将其用作外部和内部防火墙。 为了动态管理该工具,我们开发了 BEFW 系统,该系统被广泛使用:从管理用户对产品网络的访问到隔离网段。

领事 + iptables = :3

他会告诉您这一切是如何运作的以及为什么您应该仔细研究这个系统。 伊万·阿加科夫 (安穆奥尔)是公司明斯克开发中心维护部门基础设施安全小组的负责人。 Ivan 是 SELinux 粉丝,热爱 Perl,并且编写代码。 作为信息安全组的负责人,他定期与日志、备份和研发一起工作,以保护Wargaming免受黑客攻击,并确保公司所有游戏服务器的运行。

历史信息

在告诉你我们是如何做到的之前,我首先要告诉你我们是如何做到这一点以及为什么需要它。 为此,让我们回到 9 年前:2010 年,《坦克世界》刚刚问世。 Wargaming 有大约 50 台服务器。

领事 + iptables = :3
公司服务器增长图表。

我们有一个网络模型。 就当时而言,这是最佳的。

领事 + iptables = :3
2010年网络模型。

前端有坏人想要破坏我们,但它有防火墙。 后端没有防火墙,但是那里有50台服务器,我们都知道。 一切都运转良好。

4 年间,服务器群增长了 100 倍,达到 5000 个。第一个孤立的网络出现了——暂存:它们无法投入生产,而且那里运行的东西经常可能存在危险。

领事 + iptables = :3
2014年网络模型。

由于惯性,我们使用相同的硬件,所有工作都在隔离的 VLAN 上进行:ACL 写入 VLAN,允许或拒绝某种连接。

2016年,服务器数量达到8000台。Wargaming吸收了其他工作室,并出现了更多附属网络。 它们似乎是我们的,但又不完全是:VLAN 通常不适用于合作伙伴,您必须使用带有 VRF 的 VPN,隔离变得更加复杂。 ACL 绝缘混合物生长。

领事 + iptables = :3
2016年网络模型。

到2018年初,机器数量已增长到16台。有000个部分,我们没有计算其余部分,包括存储财务数据的封闭部分。 容器网络 (Kubernetes)、DevOps、通过 VPN 连接的云网络(例如从 IVS)已经出现。 有很多规则——这很痛苦。

领事 + iptables = :3
2018年网络模型和隔离方法。

对于隔离,我们使用了:在 L2 上具有 ACL 的 VLAN、在 L3 上具有 ACL 的 VRF、VPN 等等。 太多了。

问题

每个人都生活在 ACL 和 VLAN 之中。 怎么了? 哈罗德将回答这个问题,隐藏痛苦。

领事 + iptables = :3

问题很多,但其中有五个是大问题。

  • 新规则几何涨价。 每条新规则的添加时间都比前一条规则要长,因为需要先查看是否已经存在这样的规则。
  • 网段内没有防火墙。 这些部分不知何故彼此分离,内部资源已经不足。
  • 这些规则被应用了很长时间。 操作员可以在一小时内手写一条本地规则。 全球的一件事花了几天的时间。
  • 审计规则的困难。 更准确地说,这是不可能的。 第一条规则早在 2010 年就已制定,大多数作者已不再为该公司工作。
  • 基础设施控制水平低。 这是主要问题——我们不太了解我们国家正在发生什么。

这就是 2018 年网络工程师听到“需要更多 ACL”时的样子。

领事 + iptables = :3

解决方案

2018年初,决定做点什么。

集成的价格不断增长。 起点是大型数据中心停止支持隔离 VLAN 和 ACL,因为设备内存不足。

解决方案:我们消除了人为因素,并最大限度地自动化提供访问权限。

新规则的实施需要很长时间。 解决方案:加快规则的应用,使其分布式、并行。 这需要一个分布式系统,以便规则能够自行传递,而无需 rsync 或 SFTP 到一千个系统。

网段内没有防火墙。 当同一网络中出现不同的服务时,段内防火墙就开始出现。 解决方案:使用主机级别的防火墙—​​—基于主机的防火墙。 几乎所有地方都有 Linux,所有地方都有 iptables,这不是问题。

审计规则的困难。 解决方案:将所有规则放在一个地方以便审查和管理,这样我们就可以审核一切。

对基础设施的控制水平低。 解决方案:盘点所有服务以及它们之间的访问。

这更多的是一个管理过程,而不是一个技术过程。 有时我们每周发布 200-300 个新版本,特别是在促销和假期期间。 而且,这仅适用于我们 DevOps 的一个团队。 由于版本众多,无法了解需要哪些端口、IP 和集成。 因此,我们需要经过专门培训的服务经理,他们会询问团队:“到底有什么,为什么要提出来?”

在我们推出一切之后,2019 年的网络工程师开始看起来像这样。

领事 + iptables = :3

领事

我们决定将在服务经理的帮助下找到的所有内容放入 Consul 中,然后从那里编写 iptables 规则。

我们是如何决定这样做的?

  • 我们将收集所有服务、网络和用户。
  • 让我们基于它们创建 iptables 规则。
  • 我们自动化控制。
  • ....
  • 的利润。

Consul不是一个远程API,它可以在每个节点上运行并写入iptables。 剩下的就是想出自动控制装置来清理不必要的东西,大多数问题都会得到解决! 我们将边走边解决剩下的问题。

为什么是领事?

已经很好地证明了自己。 2014-15 年,我们将其用作 Vault 的后端,在其中存储密码。

不丢失数据。 在使用过程中,Consul没有出现过一次意外丢失数据的情况。 这对于防火墙管理系统来说是一个巨大的优势。

P2P连接加速变革的传播。 有了P2P,所有的改变都来得很快,不需要等待几个小时。

方便的 REST API。 我们还考虑了 Apache ZooKeeper,但它没有 REST API,因此您必须安装拐杖。

既可用作密钥保管库 (KV) 又可用作目录(服务发现)。 您可以同时存储服务、目录和数据中心。 这不仅对我们来说很方便,对邻近的团队也很方便,因为在构建全球服务时,我们会胸怀大志。

用 Go 编写,是 Wargaming 堆栈的一部分。 我们喜欢这门语言,我们有很多 Go 开发人员。

强大的ACL系统。 在 Consul 中,您可以使用 ACL 来控制谁写什么。 我们保证防火墙规则不会与其他规则重叠,因此我们不会遇到任何问题。

但 Consul 也有其缺点。

  • 除非您有商业版本,否则无法在数据中心内扩展。 它只能通过联盟来扩展。
  • 非常依赖网络质量和服务器负载。 如果网络中存在任何滞后(例如速度不均匀),Consul 将无法作为繁忙服务器上的服务器正常工作。 这是由于 P2P 连接和更新分发模型。
  • 难以监控可用性。 以领事身份他可以说一切都很好,但他已经死了很久了。

我们在使用 Consul 时解决了大部分问题,这就是我们选择它的原因。 该公司计划提供替代后端,但我们已经学会了如何处理问题,目前正在与 Consul 合作。

领事如何工作

有条件的数据中心我们会安装三到五台服务器。 一两台服务器将无法工作:当数据不匹配时,它们将无法组织法定人数并决定谁是对的,谁是错的。 超过五个就没有意义,生产力会下降。

领事 + iptables = :3

客户端以任意顺序连接到服务器:相同的代理,仅带有标志 server = false.

领事 + iptables = :3

此后,客户端收到 P2P 连接列表并在它们之间建立连接。

领事 + iptables = :3

在全球范围内,我们连接多个数据中心。 他们还连接 P2P 并进行通信。

领事 + iptables = :3

当我们想要从另一个数据中心检索数据时,请求会从一个服务器发送到另一个服务器。 这个方案被称为 农奴协议。 Serf 协议和 Consul 一样,都是由 HashiCorp 开发的。

关于 Consul 的一些重要事实

Consul 有描述其工作原理的文档。 我只会提供一些值得了解的精选事实。

领事服务器从选民中选择一个主人。 Consul从每个数据中心的服务器列表中选择一个主服务器,所有请求都只发送到它,而不管服务器数量有多少。 Master冻结不会导致重选。 如果未选择主服务器,则任何人都不会处理请求。

您想要水平缩放吗? 抱歉,没有。

对另一个数据中心的请求从一个主服务器发送到另一个主服务器,无论它来自哪个服务器。 选定的主服务器接收 100% 的负载,转发请求的负载除外。 数据中心中的所有服务器都有最新的数据副本,但只有一台服务器做出响应。

扩展的唯一方法是在客户端上启用陈旧模式。

在陈旧模式下,您可以在没有法定人数的情况下做出响应。 这是一种我们放弃数据一致性,但读取速度比平常快一点,并且任何服务器都会响应的模式。 当然,只能通过大师来录制。

Consul 不会在数据中心之间复制数据。 当一个联邦组装起来时,每个服务器将只有自己的数据。 对于别人,他总是求助于别人。

在事务之外不保证操作的原子性。 请记住,您不是唯一可以改变事情的人。 如果您有不同的需求,请使用锁进行事务。

阻塞操作并不能保证锁定。 请求从一个主服务器发送到另一个主服务器,而不是直接发送,因此不能保证当您阻塞时阻塞会起作用,例如,在另一个数据中心中。

ACL 也不保证访问(在许多情况下)。 ACL 可能无法工作,因为它存储在一个联合数据中心 - ACL 数据中心(主 DC)中。 如果 DC 不回答您,ACL 将不起作用。

一个冻结的主宰就会导致整个联邦冻结。 例如,一个联邦有10个数据中心,其中一个网络不好,一个master出现故障。 每个与他通信的人都会陷入一个循环:有请求,没有答复,线程冻结。 无法知道什么时候会发生,一两个小时后整个联邦就会崩溃。 你对此无能为力。

状态、法定人数和选举由单独的线程处理。 重新选举不会发生,状态不会显示任何内容。 你认为你有一位活着的领事,你问,但没有任何反应 - 没有答案。 同时,状态显示一切都很好。

我们遇到过这个问题,并且不得不重建数据中心的特定部分来避免它。

Consul Enterprise的商业版不存在上面的一些缺点。 它有许多有用的功能:选择选民、分配、缩放。 只有一个“但是”——分布式系统的许可系统非常昂贵。

生活黑客: rm -rf /var/lib/consul ——一剂包治百病的药剂。 如果某些内容对您不起作用,只需删除您的数据并从副本下载数据即可。 最有可能的是,领事会工作。

北风卫士

现在我们来谈谈 Consul 中添加的内容。

北风卫士 是缩写 BACKEndF忿怒W全部。 当我创建存储库时,我必须以某种方式命名该产品,以便将第一个测试提交放入其中。 这个名字仍然保留着。

规则模板

这些规则是用 iptables 语法编写的。

  • -N BEFW
  • -P 输入下降
  • -A 输入 -m 状态—状态相关、已建立 -j 接受
  • -A 输入 -i lo -j 接受
  • -A 输入 -j BEFW

所有东西都进入 BEFW 链,除了 ESTABLISHED, RELATED 和本地主机。 模板可以是任何东西,这只是一个例子。

BEFW 有什么用?

服务

我们有一个服务,它总是有一个端口,一个它运行的节点。 从我们的节点,我们可以在本地询问代理并发现我们有某种服务。 您还可以放置标签。

领事 + iptables = :3

任何正在运行并注册到 Consul 的服务都会变成 iptables 规则。 我们有 SSH - 打开端口 22。Bash 脚本很简单:curl 和 iptables,不需要其他任何东西。

客户

如何不向所有人开放访问权限,而是有选择地开放访问权限? 按服务名称将 IP 列表添加到 KV 存储。

领事 + iptables = :3

例如,我们希望第十个网络上的每个人都能够访问 SSH_TCP_22 服务。 添加一个小的 TTL 字段? 现在我们有临时许可证,例如一天的许可证。

使用权

我们连接服务和客户端:我们有一个服务,KV 存储已为每个服务做好准备。 现在我们不是向所有人提供访问权限,而是有选择地提供访问权限。

领事 + iptables = :3

如果我们每次写几千个IP来访问的话,我们会很累。 让我们提出分组——KV 中的一个单独的子集。 我们将其称为别名(或组)并根据相同的原理将组存储在那里。

领事 + iptables = :3

让我们连接:现在我们可以打开SSH,不是专门针对P2P,而是针对整个组或多个组。 同样,还有 TTL - 您可以添加到组中并暂时从组中删除。

领事 + iptables = :3

积分

我们的问题是人为因素和自动化。 目前为止我们都是这样解决的。

领事 + iptables = :3

我们与 Puppet 合作,并将与系统(应用程序代码)相关的所有内容转移给他们。 Puppetdb(常规 PostgreSQL)存储在那里运行的服务列表,可以通过资源类型找到它们。 在那里您可以找到谁在哪里申请。 为此,我们还有一个拉取请求和合并请求系统。

我们编写了befw-sync,一个有助于传输数据的简单解决方案。 首先,同步cookie由puppetdb访问。 在那里配置了一个 HTTP API:我们请求我们拥有什么服务,需要做什么。 然后他们向领事提出请求。

有整合吗? 是的:他们编写了规则并允许接受 Pull 请求。 您是否需要某个端口或将主机添加到某个组? Pull 请求、审查 - 不再需要“查找 200 个其他 ACL 并尝试对此采取措施”。

优化

使用空规则链 Ping 本地主机需要 0,075 毫秒。

领事 + iptables = :3

让我们向该链添加 10 个 iptables 地址。 结果,ping会增加000倍:iptables是完全线性的,处理每个地址需要一些时间。

领事 + iptables = :3

对于迁移数千个 ACL 的防火墙,我们有很多规则,这会带来延迟。 这对于游戏协议来说是不利的。

但如果我们把 ipset 中有 10 个地址 ping甚至会下降。

领事 + iptables = :3

关键是,无论有多少规则,ipset 的“O”(算法复杂度)始终等于 1。 确实,有一个限制 - 规则不能超过 65535 个。目前我们接受这一点:您可以将它们组合起来,扩展它们,将两个 ipset 合而为一。

存储

迭代过程的逻辑延续是将有关服务的客户端的信息存储在 ipset 中。

领事 + iptables = :3

现在我们有相同的SSH,并且我们不是一次写入100个IP,而是设置我们需要通信的ipset的名称,以及以下规则 DROP。 可以转化为一条规则“谁不在,DROP”,但更清晰。

现在我们有了规则和设定。 主要任务是在编写规则之前先进行设置,因为否则 iptables 将不会编写规则。

一般计划

以图表的形式来说,我所说的一切都是这样的。

领事 + iptables = :3

我们承诺Puppet,一切都发送到主机,服务在这里,ipset在那里,任何没有在那里注册的人都是不允许的。

允许否认

为了快速拯救世界或快速禁用某人,在所有链的开头我们创建了两个 ipset: rules_allow и rules_deny. 这个怎么运作?

例如,有人正在使用机器人在我们的网络上创建负载。 以前,你必须从日志中找到他的IP,并将其交给网络工程师,以便他们找到流量的来源并禁止他。 现在看起来不一样了。

领事 + iptables = :3

我们将其发送给 Consul,等待 2,5 秒,就完成了。 由于 Consul 通过 P2P 快速分发,因此它可以在世界任何地方、任何地方工作。

有一次,由于防火墙的错误,我以某种方式完全停止了 WOT。 rules_allow - 这是我们针对此类情况的保险。 如果我们在防火墙的某个地方犯了错误,某处被阻止了,我们总是可以发送一个条件 0.0/0快速捡起所有东西。 稍后我们将手工修复所有内容。

其他套装

您可以在空间中添加任何其他集合 $IPSETS$.

领事 + iptables = :3

为了什么? 例如,有时有人需要 ipset 来模拟集群某些部分的关闭。 任何人都可以带任何套装,给它们命名,然后领事就会把它们拿走。 同时,集合既可以参与iptables规则,也可以作为一个团队 NOOP:一致性将由守护进程维护。

用户

以前是这样的:用户连接到网络,通过域接收参数。 在新一代防火墙出现之前,思科不知道如何了解用户在哪里以及IP在哪里。 因此,只能通过计算机的主机名授予访问权限。

我们做了什么? 当我们收到地址时,我们陷入了困境。 通常是 dot1x、Wi-Fi 或 VPN - 一切都通过 RADIUS。 对于每个用户,我们按用户名创建一个组,并在其中放置一个 IP,其 TTL 等于其 dhcp.lease - 一旦过期,该规则就会消失。

领事 + iptables = :3

现在我们可以像其他组一样通过用户名开放对服务的访问。 我们减轻了主机名更改带来的痛苦,也减轻了网络工程师的负担,因为他们不再需要思科。 现在,工程师自己在他们的服务器上注册访问权限。

绝缘

与此同时,我们开始拆除隔热层。 服务经理进行了盘点,我们分析了所有网络。 让我们将它们分成相同的组,并在必要的服务器上添加这些组,例如拒绝。 现在,相同的暂存隔离最终出现在生产的 Rules_deny 中,但不在生产本身中。

领事 + iptables = :3

该方案运行快速且简单:我们从服务器中删除所有 ACL,卸载硬件,并减少隔离 VLAN 的数量。

完整性控制

以前,我们有一个特殊的触发器,可以在有人手动更改防火墙规则时进行报告。 我正在编写一个巨大的 linter 来检查防火墙规则,这很困难。 Integrity 现在由 BEFW 控制。 他热心地确保他制定的规则不会改变。 如果有人改变了防火墙规则,一切都会变回来。 “我很快就设置了一个代理,这样我就可以在家工作”——没有更多这样的选择了。

BEFW 从服务中控制 ipset,并在 befw.conf 中列出,即 BEFW 链中服务的规则。 但它不监控其他链和规则以及其他 ipset。

碰撞保护

BEFW 始终将最后一个已知的良好状态直接存储在 state.bin 二进制结构中。 如果出现问题,它总是回滚到这个state.bin。

领事 + iptables = :3

这是针对 Consul 操作不稳定的保险,当它没有发送数据或有人犯了错误并使用了无法应用的规则时。 为了确保我们不会失去防火墙,如果任何阶段发生错误,BEFW 都会回滚到最新状态。

在危急情况下,这可以保证我们保留有效的防火墙。 我们开放所有灰色网络,希望管理员能够来修复它。 有一天我会将其放入配置中,但现在我们只有三个灰色网络:10/8、172/12 和 192.168/16。 在我们的 Consul 中,这是一个帮助我们进一步发展的重要功能。

演示:报告中,Ivan演示了BEFW的演示模式。 观看演示更方便 视频。 提供演示源代码 在GitHub上.

陷阱

我会告诉你我们遇到的错误。

ipset 添加设置 0.0.0.0/0。 如果将 0.0.0.0/0 添加到 ipset 会发生什么? 所有IP都会被添加吗? 可以访问互联网吗?

不,我们会遇到一个错误,导致我们停机两个小时。 此外,该错误自 2016 年以来就不再起作用,它位于 RedHat Bugzilla 中,编号为#1297092,我们是从开发人员的报告中偶然发现的。

BEFW 现在有一条严格的规定: 0.0.0.0/0 变成两个地址: 0.0.0.0/1 и 128.0.0.0/1.

ipset 恢复集 < 文件。 当你告诉 ipset 时它会做什么 restore? 你认为它的工作原理和 iptables 一样吗? 会恢复数据吗?

没有那样的 - 它进行合并,旧地址不会去任何地方,你不会阻止访问。

我们在测试隔离时发现了一个错误。 现在有一个相当复杂的系统 - 而不是 restore 保持 create temp,然后 restore flush temp и restore temp。 交换结束时:为了原子性,因为如果你先这样做 flush 此时,某个数据包到达,它将被丢弃,并且会出现问题。 所以这里面有一点黑魔法。

领事 kv get -datacenter=other。 正如我所说,我们认为我们正在要求一些数据,但我们要么得到数据,要么得到错误。 我们可以通过本地的 Consul 来完成此操作,但在这种情况下,两者都会冻结。

本地 Consul 客户端是 HTTP API 的包装器。 但它只是挂起并且不响应 Ctrl+C、Ctrl+Z 或任何其他操作 kill -9 在下一个控制台中。 我们在构建大型集群时遇到了这个问题。 但我们还没有解决方案;我们正准备在 Consul 中修复这个错误。

领事领导没有回应。 我们数据中心的master没有反应,我们想:“也许重选算法现在可以工作了?”

不,这不起作用,监控也不会显示任何内容:Consul 会说有承诺指数,已找到领导者,一切都很好。

我们该如何处理这个问题? service consul restart 每小时以 cron 形式执行。 如果你有 50 台服务器,没什么大不了的。 当它们达到 16 个时,你就会明白它是如何工作的。

结论

结果,我们获得了以下优势:

  • 100%覆盖所有Linux机器。
  • 速度。
  • 自动化。
  • 我们将硬件和网络工程师从奴役中解放出来。
  • 集成的可能性几乎是无限的:即使使用 Kubernetes,即使使用 Ansible,甚至使用 Python。

缺点:领事,我们现在必须忍受它,并且错误的成本非常高。 举个例子,有一次下午 6 点(俄罗斯的黄金时间),我正在编辑网络列表中的一些内容。 当时我们刚刚在 BEFW 建造隔热层。 我在某个地方犯了一个错误,似乎我指示了错误的面具,但一切都在两秒钟内倒下了。 监控亮起,值班人员跑过来:“我们什么都有了!” 当部门负责人向业务解释为什么会发生这种情况时,他的脸色变得灰白。

错误的成本是如此之高,以至于我们制定了自己的复杂预防程序。 如果您在大型生产站点上实现此功能,则无需通过 Consul 向每个人提供主令牌。 这会很糟糕地结束。

成本。 我一个人就写了 400 个小时的代码。 我的 4 人团队每月花费 10 个小时为每个人提供支持。 与任何新一代防火墙的价格相比,它是免费的。

计划。 长期计划是寻找替代交通来替代或补充 Consul。 也许是卡夫卡或类似的东西。 但未来几年我们将依靠 Consul 生活。

近期计划:与 Fail2ban、监控、nftables 集成,可能与其他发行版、指标、高级监控、优化集成。 Kubernetes 支持也在计划中,因为现在我们有几个集群和愿望。

更多来自计划:

  • 寻找交通异常情况;
  • 网络地图管理;
  • Kubernetes 支持;
  • 为所有系统组装软件包;
  • 网络用户界面。

我们不断致力于扩展配置、增加指标和优化。

加入该项目。 该项目结果很酷,但不幸的是,它仍然是一个单人项目。 来到 GitHub上 并尝试做某事:提交、测试、提出建议、给出评估。

同时我们正在准备 圣高负载++,将于 6 月 7 日至 XNUMX 日在圣彼得堡举行,我们邀请高负载系统的开发人员 申请报告。 经验丰富的演讲者已经知道该怎么做,但对于那些刚开始演讲的人,我们至少建议 试试。 作为演讲者参加会议有很多好处。 例如,您可以在最后阅读哪些内容 这篇文章.

来源: habr.com

添加评论