【问题标题】:RabbitMQ - Game Rooms and Security ConsiderationsRabbitMQ - 游戏室和安全注意事项
【发布时间】:2012-08-14 14:30:46
【问题描述】:

我正在编写一个 Android 应用程序并想定义房间。房间将容纳某些游戏的所有用户。这就像扑克有 4 个玩家,每个房间可以容纳 4 个用户。我还想使用 rabbitmq 来实现可扩展性和可定制性。问题是 Android 应用程序使用相同的用户名:密码将所有用户连接到 RabbitMQ 服务器(特定虚拟主机)。

我想我担心一个用户可能能够读取/写入来自不同队列的消息,这是应该的。有多种解决方案不满意:

  1. 在每个 Android 应用程序中使用不同的用户:这确实无法做到,因为 Android Market 不允许每个下载它的用户使用不同的应用程序。就算是这样,那也是个愚蠢的主意。

  2. 设置适当的访问控制:http://www.rabbitmq.com/access-control.html。我想这不会阻止恶意攻击者从/向它无权访问的队列读取/写入消息的问题。

  3. 设置适当的路由键:我猜如果每个用户创建另一个队列,它可以从中读取消息并将消息发布到特定定义的队列,这可以工作。但我猜问题是一样的,因为用户将使用相同的 username:password: 连接到 RabbitMQ,因此该用户可以读取所有队列并写入它们(基于访问规则)。

我的问题是:如何允许攻击者读取/写入仅代表他当前加入的房间的队列,并阻止访问其他队列?

【问题讨论】:

  • 您可以通过为每个客户端创建一个队列来使用 rmq 模拟 pub/sub,并且他们可以通过该队列接收实时事件。在您的情况下,每个表都可能是一个非持久的扇出交换,每次服务器决定传播移动时,每个客户端都会接收服务器发送的游戏状态。然后您的游戏服务器将只知道交换(表)并从中发送/接收事件。如果你每桌有 4 个人和 2500 次交易,那已经是一个大型游戏服务器了。

标签: python security webserver messaging rabbitmq


【解决方案1】:

也许我不太了解应用程序,但根据我的经验,RabbitMQ 通常用于后端,例如,在创建具有数据库和应用程序服务器以及其他松散耦合实体的分布式系统时。消息队列是异步应用程序设计的重要工具,理论上每个消息队列都可以通过 RabbitMQ 生成一个单独的进程,这一事实使其具有显着的可扩展性。

您在问题中提到的内容似乎更像是用户的访问控制机制。我会在系统的前端看到这一点。例如,在将传入消息传递到消息传递队列之前对传入消息进行过滤。您甚至可以考虑通过每个用户的速率控制来预防 DoS。

干杯!

【讨论】:

  • 我想使用以下内容:simonwdixon.wordpress.com/2011/06/03/…。我想这使它成为一个前端系统,但这没关系。用户仍然使用相同的用户名:密码连接到 RabbitMQ。如果您能提出更准确/准确的答案,我会接受您的答案。
  • 好吧,这个例子并没有谈到访问控制,一般来说,如果交换队列是可公开访问的,那么任何拥有队列路由密钥的人都可以(应该 IMO)向队列发布消息。
  • 好吧,这个例子并没有谈到访问控制,一般来说,如果交换队列是可公开访问的,那么任何拥有队列路由密钥的人都可以(应该 IMO)向队列发布消息。 IMO 博客文章根本不考虑安全性。将 HTTP 服务器视为访问控制机制的中间人。另一件需要考虑的事情 - 你可能不希望 RabbitMQ 连接到客户端连接 - 它需要在网络中打开 TCP 端口 - 防火墙可能会阻止客户端和 RabbitMQ 服务器之间的底层 TCP 连接。客户端-服务器坚持使用 HTTP。
  • 我必须使用 TCP 连接,因为我需要实时网络:考虑一个扑克游戏。当有人采取行动时,必须尽快对其进行验证和考虑,以免进一步拖延比赛。这就是为什么每个客户端都需要一个 TCP 连接。我不能使用 REST 或类似的东西。我仍然需要一个如何安全地实现我想要的功能的答案。
  • 嗯,你需要访问控制,我认为实现它的方式是通过代理,可以应用你需要的访问控制规则。如果您想避免 http 或休息开销,请将其设为 Tcp-amqp 代理。无论如何,使用消息队列将解决任何同步问题。或者客户端移动之间的竞争问题。祝你好运!
【解决方案2】:

我自己正在开发一个扑克应用程序 =)

我依赖于基于 Akka/Actors(查看 Erlang)之类的基于流式 Web 套接字的流量,并希望它能够成功(仍然有点担心安全 Web 套接字)。

也就是说,我也在考虑使用 RabbitMQ 来接收玩家动作。我认为您不想将用户名或密码暴露给兔子队列。事实上,您可能甚至不希望从外部世界访问队列服务器。

相反,设置一些您的用户可以建立连接的服务器。这将是您的“前端”,Android 客户端将与之交谈。每个用户将通过安全的 TCP 连接连接到服务器,然后登录到您的系统。这是用户将拥有自己的用户名和密码的地方。如果身份验证成功,让套接字保持活动状态(这是我对 TCP 知识薄弱的地方),然后将用户信息与此套接字相关联。

当玩家做出动作(例如弃牌或加注)时,通过安全 TCP 连接将他们的动作发送到您的“前端”(此连接仍应建立)。 “前端”然后检查哪个用户连接到此套接字,然后将消息发布到理想情况下包含用户 ID、采取的操作和表 ID 的队列。换句话说,唯一允许访问队列的 IP 是您的前端服务器,而前端服务器只使用兔子队列的单个用户名/密码。

由您来处理队列消息的交换并将消息路由到正确的表(或确保该表只处理它负责的消息 - 这就是我现在喜欢 Akka 的原因 :) 一次消息到达表,验证消息中的用户 id 是实际轮到的用户 id,然后根据表的状态验证发送的操作是可接受的。例如,如果我收到一个 CHECK 请求,而用户只能 CALL/FOLD/RAISE,那么我只会回复无效操作或直接丢弃整个消息。

不要让公众排队,并始终确保您没有安全漏洞,尤其是在您开始处理真实货币时。

希望这会有所帮助...

编辑:我只想说清楚。任何时候客户端进行操作,他们只需要发送操作和表 ID 或您需要的任何信息。不要让他们发送他们的用户 ID 或任何用户特定信息。您的“前端”服务器应该根据请求进入的套接字自动关联用户 ID。如果他们在请求中提交了任何用户信息,最好将其记录下来,然后丢弃数据。我会记录它只是因为我不喜欢人们试图作弊,如果他们向您发送意外数据,他们可能就是这样做的。

【讨论】:

  • 谢谢老兄,这正是我想要的;扑克游戏客户端中事件的逐步流程。我正在考虑使用 ZeroMQ,有什么想法吗?
猜你喜欢
  • 2019-04-19
  • 2014-08-19
  • 1970-01-01
  • 2010-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-18
相关资源
最近更新 更多