Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RabbitMQ security design to declare queues from server (and use from client)

Tags:

I have a test app (first with RabbitMQ) which runs on partially trusted clients (in that i don't want them creating queues on their own), so i will look into the security permissions of the queues and credentials that the clients connect with.

For messaging there are mostly one-way broadcasts from server to clients, and sometimes a query from server to a specific client (over which the replies will be sent on a replyTo queue which is dedicated to that client on which the server listens for responses).

I currently have a receive function on the server which looks out for "Announce" broadcast from clients:

agentAnnounceListener.Received += (model, ea) =>
{
    var body = ea.Body;
    var props = ea.BasicProperties;
    var message = Encoding.UTF8.GetString(body);

    Console.WriteLine(
        "[{0}] from: {1}. body: {2}",
        DateTimeOffset.FromUnixTimeMilliseconds(ea.BasicProperties.Timestamp.UnixTime).Date,
        props.ReplyTo,
        message);

      // create return replyTo queue, snipped in next code section
};

I am looking to create the return to topic in the above receive handler:

var result = channel.QueueDeclare(
    queue: ea.BasicProperties.ReplyTo,
    durable: false,
    exclusive: false,
    autoDelete: false,
    arguments: null);

Alternatively, i could store the received announcements in a database, and on a regular timer run through this list and declare a queue for each on every pass.

In both scenarioes this newly created channel would then be used at a future point by the server to send queries to the client.

My questions are please:

1) Is it better to create a reply channel on the server when receiving the message from client, or if i do it externally (on a timer) are there any performance issues for declaring queues that already exist (there could be thousands of end points)?

2) If a client starts to miss behave, is there any way that they can be booted (in the receive function i can look up how many messages per minute and boot if certain criteria are met)? Are there any other filters that can be defined prior to receive in the pipeline to kick clients who are sending too many messages?

3) In the above example notice my messages continuously come in each run (the same old messages), how do i clear them out please?

like image 985
morleyc Avatar asked Jan 13 '18 22:01

morleyc


People also ask

How do you create a durable queue in RabbitMQ?

Create a durable queue by specifying durable as true during creation of your queue. You can check in the RabbitMQ Management UI, in the queue tab that the queue is marked with a "D" to ensure that the queue is durable.

Does RabbitMQ automatically create queues?

What do you mean "auto-creating" queues? RabbitMQ doesn't create them, the application code does.

How do you consume messages from RabbitMQ?

In order to consume messages there has to be a queue. When a new consumer is added, assuming there are already messages ready in the queue, deliveries will start immediately. The target queue can be empty at the time of consumer registration. In that case first deliveries will happen when new messages are enqueued.

Can two consumers consume the same message RabbitMQ?

RabbitMQ has a plugin for consistent hash exchange. Using that exchange, and one consumer per queue, we can achieve message order with multiple consumers. The hash exchange distributes routing keys among queues, instead of messages among queues. This means all messages with the same routing key will go the same queue.


1 Answers

I think preventing clients from creating queues just complicates the design without much security benefit. You are allowing clients to create messages. In RabbitMQ, its not very easy to stop clients from flooding your server with messages.

If you want to rate-limit your clients, RabbitMQ may not be the best choice. It does rate-limiting automatically when servers starts to struggle with processing all the messages, but you can't set a strict rate limit on per-client basis on the server using out-of-the-box solution. Also, clients are normally allowed to create queues.

Approach 1 - Web App

Maybe you should try to use web application instead:

  • Clients authenticate with your server
  • To Announce, clients send a POST request to a certain endpoint, ie /api/announce, maybe providing some credentials that allow them to do so
  • To receive incoming messages, GET /api/messages
  • To acknowledge processed message: POST /api/acknowledge

When client acknowledges receipt, you delete your message from database.

With this design, you can write custom logic to rate-limit or ban clients that misbehave and you have full control of your server

Approach 2 - RabbitMQ Management API

If you still want to use RabbitMQ, you can potentially achieve what you want by using RabbitMQ Management API

You'll need to write an app that will query RabbitMQ Management API on timer basis and:

Get all the current connections, and check message rate for each of them.

If message rate exceed your threshold, close connection or revoke user's permissions using /api/permissions/vhost/user endpoint.

In my opinion, web app may be easier if you don't need all the queueing functionality like worker queues or complicated routing that you can get out of the box with RabbitMQ.

like image 83
Alex Buyny Avatar answered Sep 23 '22 13:09

Alex Buyny