白皮书
车云灵活数采方案:释放数据价值,加速智能创新 →

通过速率限制保障 MQTT 服务器的稳定与安全

EMQX Team
2023-7-20
通过速率限制保障 MQTT 服务器的稳定与安全

引言

速率限制通常是指在网络中对单位时间内的数据传输速率进行限制,以确保网络流量在可接受范围内,避免在接收端造成拥堵和过载,进而影响它的稳定性和可靠性。

本文将探讨速率限制在另一方面的作用,即它如何为物联网平台和应用提供安全上的保障。

速率限制如何保障系统安全?

常规意义上的速率限制通常是指对网络中的正常流量进行调控,这些流量通常来自合法的接入端,并且会因接入端的行为发生变化。例如流入系统的流量因用户起床而增加,因用户入睡而减少。而本文中我们想讨论的是速率限制对恶意流量的影响。

尽管我们可能已经部署了认证、授权等服务,尽可能地减少系统被恶意攻击的可能。但我们仍然不妨假设有一天某个用户账号遭到泄漏或被窃取,如果我们没有设置任何速率限制策略,这意味着攻击者只需要持有这一个账号,就可以使大量的恶意流量涌入我们的系统,增加系统负载。如果系统当前恰好处于流量高峰时期,甚至有可能使系统过载,使其无法为其他合法的接入端继续提供及时、可靠的服务。

但如果我们设置了合理的速率限制策略,一个攻击者即便持有泄漏账号,也只能有限制地访问系统,他带来的这些流量并不会超过系统预期的承受范围。

MQTT 中常见的速率限制策略

限制客户端的发布速率或配额

我们可以对单个客户端的发布速率进行限制,例如限制客户端每秒可以发布的消息数量上限,以及每秒可以发布的消息总大小的上限。后者可以有效避免攻击者通过发送少量但是巨大的消息快速消耗服务端资源。配合权限管理机制,我们还可以为不同权限等级的客户端设置不同的速率限制。

除了速率限制,我们还可以对客户端的配额进行限制。例如虽然客户端每秒最多可以发布 100 条消息,但可能它每天的配额只有 5000。这表示如果它耗尽了配额,那么它在配额刷新前将无法再向我们发布任何消息。

考虑到 MQTT 中不同 QoS 需要消耗的系统资源不同,我们还可以针对消息的 QoS 进行更细粒度的控制,例如允许客户端每秒最多发布 100 条 QoS 0 消息,但其每秒最多只能发布 50 条 QoS 1 和 2 消息等等。这可以有效避免攻击者使用较高的 QoS 快速消耗服务端资源。

限制客户端的订阅速率

MQTT 不需要我们提前创建或者注册订阅,但相应地,这个步骤被转移到了客户端连接到服务端以后。每当有客户端发起新的订阅,服务端不可避免地需要进行更新路由表等操作。攻击者可能会利用这一点,例如让客户端在短时间内发起大量订阅,使服务端忙于各种写操作,从而影响服务端的正常服务。为了解决这个问题,我们可以对单个客户端每秒能够发起的订阅数量进行限制。

限制客户端的连接速率和最大连接数量

与订阅类似,每当客户端发起连接,服务端同样需要完成不少工作,例如创建一个新的线程、注册 Client ID 等等。如果我们启用了认证服务,那么每个连接请求都会在服务端触发一次认证流程,服务端可能需要去数据库中查询对应的认证数据,以及执行一些哈希计算。通常哈希算法的安全性越高,运行消耗的 CPU 也就越多。

所以限制客户端的最大连接速率可以有效防止攻击者在短时间内发起大量连接来耗尽服务端的资源。

另外,维护连接也需要消耗服务端的 CPU、内存等资源,因此攻击者可能会尝试与服务端建立大量的闲置连接,来影响服务端的正常运行。所以,对服务端允许的最大连接数进行限制也是非常有必要的。

防范异常行为

前面我们提到的,本质都还是攻击者伪装成一个合法用户以后可能发起的攻击。但很多时候,攻击者并不需要发起正确的请求就能够影响我们服务的稳定性。例如,攻击者尝试向大量无法通过授权的主题发送消息,虽然他最终并不能让服务端为他转发这些消息,但他成功地让服务端在检查他是否具备相应权限的过程中消耗了计算资源。

我们通常将这类攻击称为 DOS 攻击或 DDOS 攻击。在 MQTT 中,类似的行为可能还有重复连接以发起认证请求等等,虽然最终他会因为达到最大连接速率限制无法继续发起连接,但这同样会导致其他合法客户端的连接请求得不到处理。

所以服务端需要检测这些可能存在安全风险的行为,并及时地做出响应。常见的办法是将这些行为异常的客户端的 IP 地址或 Client ID 加入到黑名单中,从源头上封锁这些客户端。

总结

速率限制限制和平衡流量的能力,除了能够应对正常业务变化带来的流量波动,还能够防止攻击者恶意消耗服务端资源,影响服务的可靠性。但某些攻击并不需要攻击者发起正确的请求,这可能会绕过速率限制,所以服务端还需要检测这些存在潜在安全风险的行为。

作为广泛使用的 MQTT Broker,EMQX 在以其高扩展性和可用性著称的同时,也始终将用户安全放在首位。在 EMQX 中,您可以轻松地为每个监听器添加不同的最大连接数、最大连接速率、消息发布速率等限制:

listeners.tcp.default {
  ...
  max_connections = 1024000
  max_conn_rate = 1000
  messages_rate = "1000/s"
  bytes_rate = "100KB/s"
  ...
}

您可以在访问 EMQX 的 速率限制黑名单 功能文档以了解更多。

免费试用 EMQX Cloud
全托管的 MQTT 消息云服务
开始试用 →

推荐阅读