1

I'm programming an Android application and want to define rooms. The rooms would hold all the users of certain game. This is like poker with 4 players, where each room can hold 4 users. I also want to use rabbitmq for scalability and customobility. The problem is that the Android application uses the same username:password to connect all users to a RabbitMQ server (specific virtual host).

I guess I'm worried that one user might be able to read/write messages from different queues that it should. There are multiple solutions that are not satisfactory:

  1. Use a different user in each Android application: This really can't be done, because the Android Market doesn't allow different applications for each user that downloads it. Even if it did, it's a stupid idea anyway.

  2. Set appropriate access controls: http://www.rabbitmq.com/access-control.html . I guess this wouldn't prevent the problem of a malicious attacker reading/writing messages from/to queues it doesn't have access to.

  3. Set appropriate routing keys: I guess if each user creates another queue from which it can read messages and published messages to specifically defined queue, this can work. But I guess the problem is the same, since users will be connecting to the RabbitMQ with the same username:password: therefore this user can read all queues and write to them (based on the access rules).

My question is: how to allow an attacker from reading/writing to queues that represent only the rooms he's currently joined in, and preventing access to other queues?

eleanor
  • 1,514
  • 3
  • 19
  • 40
  • you can emulate pub/sub with rmq by creating a queue for each client and they can receive realtime events through that queue. In your case, each table could be a non-persistent fanout exchange where every client receives server-sent game state every time server decides to propagate a move. Then your game server will only know the exchange (table) and send/receive events from that. If you have 4 people per table and 2500 exchanges, that's already a big game server. – nurettin Feb 26 '19 at 13:44

2 Answers2

2

Perhaps I don't understand the application too well, but in my experience RabbitMQ is usually used on the backend, for example, while creating a distributed system with databases and application servers and other loosely coupled entities. Message queuing is an important tool for asynchronous application design, and the fact that each messaging queue can in theory be spawned into a separate process by RabbitMQ makes it remarkably scalable.

What you are alluding to in your question seems more like a access control mechanism for users. I would see this in the front end of a system. For example, having filtering mechanisms on the incoming messages before passing them on to the messaging queues. You might even want to consider DoS prevention via rate control per user.

Cheers!

Sachin
  • 915
  • 6
  • 10
  • 1
    I want to use the following: http://simonwdixon.wordpress.com/2011/06/03/getting-started-with-rabbitmq-on-android-part-1/ . I guess this makes it a frontend system, but it doesn't matter. The users are still being connected to the RabbitMQ with the same username:password. If you can suggest more accurate/precise answer I'll accept your answer. – eleanor Aug 14 '12 at 15:36
  • Well, the example does not speak of access control, in general, if an exchange queue is publicly accessible then anyone with the routing key for a queue could (should IMO) post messages to the queue. – Sachin Aug 14 '12 at 17:40
  • Well, the example does not speak of access control, in general, if an exchange queue is publicly accessible then anyone with the routing key for a queue could (should IMO) post messages to the queue. IMO the blog post does not consider security at all. Consider a HTTP server as the go-between for access control mechanisms. Another thing to consider - you may not want a RabbitMQ connection to the client connection - it requires TCP ports to be open in the network - firewalls may block the underlying TCP connection between the client and RabbitMQ server. Stick to HTTP for client-server. – Sachin Aug 14 '12 at 17:51
  • I have to use the TCP connection, because I need real time networking: consider a poker game. When someone makes a move it must be validated and taken into account as soon as possible not to delay the game further. This is why each client needs a TCP connection. I can't use REST or something like that. I still need an answer how to implement the features that I want securely. – eleanor Aug 14 '12 at 18:10
  • Well, you need access control and the way I think of implementing it is via a proxy that can apply The access control rules you need. Make it a Tcp-amqp proxy if you want to avoid http or rest overhead. In any case using the message queue will solve any synchronization. Or race issues between client moves. Good luck! – Sachin Aug 14 '12 at 18:56
  • Hi, can you tell me if I can do that with node.js, so that all the Android clients talk to node.js asynchronously: a client A joins room N and then waits for the messages from the other clients also connected to room N: this has to be asynchronous. The end result is that each client has a TCP connection established to the node.js through which it's receiving/sending all the messages that in the backend communicate with the rabbitmq? – eleanor Aug 15 '12 at 17:56
  • Hi, sure you can do this. With node.js you use the libraries to connect to RabbitMQ (https://github.com/postwait/node-amqp) and then if you have a node TCP server listening (http://nodejs.org/api/net.html) you can use this as the proxy to connect the client to the RabbitMQ server. In your application you essentially want to setup the TCP connection, and have the server push data to the client over the TCP connection every time the rabbitMQ delivers a message. Should be pretty straightforward IMO. – Sachin Aug 16 '12 at 14:03
2

I am working on a Poker application myself =)

I am relying on something like Akka/Actors (check out Erlang) based traffic over streaming web sockets and hoping it works out (still kind of worried about secure web sockets).

That said, I am also considering RabbitMQ for receiving player actions. I do not think you want to ever expose the username or password to the rabbit queue. As a matter of fact, you probably don't even want the queue server accessible from the outside world.

Instead, set up some server that your users can establish a connection to. This will be your "front end" that the android clients will talk to. Each user will connect to the server via a secure TCP connection and then log into your system. This is where the users will have their own usernames and passwords. If authentication is successful, keep the socket alive (this is where my knowledge of TCP is weak) and then associate the user information with this socket.

When a player makes an action, such as folding or raising, send their action over the secure TCP connection to your "front end" (this connection should still be established). The "front end" then checks which user is connected to this socket, then publishes a message to the queue that would ideally contain the user id, action taken, and the table id. In other words, the only IP allowed to hit the queue is your front end server, and the front end server just uses the single username/password for the rabbit queue.

It's up to you to handle the exchange of the queue message and routing the message to the right table (or making sure the table only handles messages that it's responsible for - which is why I am loving Akka right about now :) Once the message arrives to the table, verify that the user id in the message is the user id whose turn it actually is, and then verify that the action sent is an acceptable one based on the table's state. For example, if I receive a CHECK request and the user can only CALL/FOLD/RAISE, then I will just reply saying invalid action or just throw out the whole message.

Do not let the public get to the queue, and always make sure you do not have security holes, especially if you start dealing with real currencies.

Hope this helps...

EDIT: I just want to be clear. Any time clients make actions, they simply need to send the action and table id or whatever information you need. Do not let them send their user id or any user specific information. Your "front end" server should auto associate the user id based on the socket the request is coming in on. If they submit any user information with their request, it may be a good idea to log it, and then throw out the data. I would log it just because I don't like people trying to cheat, and that's probably what they're doing if they send you unexpected data.

Lo-Tan
  • 2,725
  • 1
  • 26
  • 27
  • Thanks dude, this was exactly what I was looking for; step-by-step flow of events in a poker game client. I'm thinking of using ZeroMQ, any thoughts? – Mark Aug 01 '13 at 10:59