Secure RabbitMQ broker in virtualized Ubuntu Server
The main purpose of the blog posts is to persist some instructions I have written for myself. However, I'm happy if someone else finds these beneficial too.
(updated ) – Petri Kannisto
DISCLAIMER. This guide comes "as is". This means that the author does not have any liability. You must consider carefully before exposing any server to the public Internet, because this is always risky. It is up to you to estimate if you know what you are doing.
Introduction
This guide provides you step-by-step instructions to install RabbitMQ in a virtualized Ubuntu Linux that:
- runs "somewhere" (this guide excludes where exactly)
- is exposed to the public Internet
- is accessible via SSH (the system has no graphical user interface!)
- requires "secure" connections to RabbitMQ, i.e.:
- TLS encryption and server certificate
- user authentication with username and password
- for security reasons, does not expose the graphical management UI of RabbitMQ
- you will manage RabbitMQ from the command line
- has a local RabbitMQ admin user
I originally wrote this guide in 2017-2018 for RabbitMQ 3.6 in Ubuntu Server 16.04.6 LTS. However, the content is likely still valid, although some sections have been updated without trying if they truly work.
Update 3 Jul 2022! Instead of installing RabbitMQ from the bottom, you could run a Docker container ( https://hub.docker.com/_/rabbitmq ). See this post for more information.
Update 3 Jul 2022! Instead of configuring RabbitMQ to directly use TLS, you could set up a termination proxy. This would simplify the configuration. See https://en.wikipedia.org/wiki/TLS_termination_proxy .
Prerequisites
This guide assumes that you know the following. If you don't, the Internet is full of guides anyway.
- Basic usage of Linux command line (copying/moving files, navigating in folders, etc.)
- Basic understanding about networking and security certificates
- Basic understanding about RabbitMQ (how to create a simple client to test it by yourself, what queues and exchanges are, etc.)
- You can find good code examples in RabbitMQ website
Furthermore, your server must have a domain name. Otherwise, you cannot get yourself a certificate.
Known shortcomings
This guide could improve at least the following.
- set up an operating-system-level mechanism to prevent brute force attacks to crack RabbitMQ credentials
- use certificates to authenticate clients with RabbitMQ
Ubuntu setup
This guide assumes that you install RabbitMQ on top of Ubuntu Server following this blog post: Virtualized Ubuntu Server for Internet services. If your system differs from this, be ready to adapt.
Firewall
By default, RabbitMQ exposes port 5671 for encrypted client connections. Assuming you use UFW as the firewall, you can open this port as follows.
sudo ufw allow 5671
The risk of the above is that the connections may come from any IP address. Therefore, if you can, you should limit this to a subset of IPs. For instance:
sudo ufw allow proto tcp from 192.168.144.1/24 to any port 5671
Disable automatic updates for Erlang
This section assumes you have enabled the tool Unattended-Upgrades.
There's one automatic update you want to avoid, namely Erlang, which is the runtime of RabbitMQ. You want this because an update may handicap RabbitMQ.
To blacklist Erlang from automatic updates, you must edit a file. I believe the file exists by default:
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
If an entry called "Unattended-Upgrade::Package-Blacklist" is there, add the following line:
"erlang";
If the blacklist entry is missing, add it as follows:
Unattended-Upgrade::Package-Blacklist {
"erlang";
};
Install RabbitMQ
This part has been updated from the previous installation, but it has not been tried with a fresh machine.
Add Erlang repository to Ubuntu software sources (execute this in a directory under /home
):
wget https://packages.erlang-solutions.com/erlang-solutions_2.0_all.deb
sudo dpkg -i erlang-solutions_2.0_all.deb
Install/update Erlang:
sudo apt-get install erlang
Add RabbitMQ signing key as a trusted key:
curl -fsSL https://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc | sudo apt-key add -
Enable HTTPS transport with Apt:
sudo apt-get install apt-transport-https
Add RabbitMQ repository to Ubuntu software sources. This will create the file "bintray.rabbitmq.list". In deb command, "bionic" is for Ubuntu 20.04. For other versions, see https://www.rabbitmq.com/install-debian.html
echo "deb https://dl.bintray.com/rabbitmq/debian bionic main" | sudo tee /etc/apt/sources.list.d/bintray.rabbitmq.list
Install RabbitMQ server:
sudo apt-get install rabbitmq-server
Next, it is advisable to try that RabbitMQ works. Create a simple piece of software that both publishes messages and subscribes for messages. If you fail, the logs may help. See /var/log/rabbitmq
.
Configure RabbitMQ users
Change username of "guest"
By default, RabbitMQ has a user called "guest". This has a default password "guest", which is nice for quick experiments but a risk in actual use.
To change the password (replace "PWD" with an actual password):
rabbitmqctl change_password guest PWD
Create RabbitMQ admin user
To manage RabbitMQ, you should have a dedicated admin user. This is user is different from the user accounts of Ubuntu and works only in the context of RabbitMQ. Furthermore, you aren't supposed to authenticate any RabbitMQ clients with this user.
This guide assumes you pick "localrmqadmin" as the username, because this is descriptive. Create the user as follows; replace "PWD" with a good password:
sudo rabbmitmqctl add_user localrmqadmin PWD
Set the permissions of user "localrmqadmin" to configure/read/write any RabbitMQ resource (this applies to at least queues and exchanges):
sudo rabbitmqctl set_permissions localrmqadmin ".*" ".*" ".*"
Set the user tag of "localrmqadmin" to "administrator":
sudo rabbitmqctl set_user_tags localrmqadmin administrator
Create client users and set permissions
Next, you need the user accounts that communicate via RabbitMQ. These can be as many as you want and have any permissions you want (or are able to set). However, these users are for communication instead of administration.
To create a user account (make sure to replace PWD with a strong password):
sudo rabbmitmqctl add_user exampleuser PWD
If you have multiple users, you may want to restrict their access. You could, for instance, specify that a user can only use a particular exchange or only exchanges that start with a certain prefix. Honestly, the permission management of RabbitMQ sucks, because you must use regular expressions and because each rule affects both exchanges and queues. However, it is doable.
With RabbitMQ, I have always used topic-based communication with randomly generated topic names. Because autogenerated queue names have the common "amq" prefix, the permissions work nicely if you allow a certain exchange name and the prefix.
For example, this allows any item that matches "myexample" or starts with "amq":
sudo rabbitmqctl set_permissions exampleuser myexample|^amq.* myexample|^amq.* myexample|^amq.*
In the example, the regex is repeated three times for different items: "configure", "write" and "read". Write and read are for messaging, but you need configure to create something. My use cases have always been happy with an identical value in each of the three.
Once you have created a rule, it's best to try if it works. Regexes are sometimes painful.
Once you have created all the beautiful regexes, you can view the result with:
sudo rabbitmqctl list_permissions
For reference, see: https://www.rabbitmq.com/rabbitmqctl.8.html
Install rabbitmqadmin tool
To enable more powerful administration, you should install the tool Rabbitmqadmin. This enables you to manage queues and exchanges. You could use the RabbitMQ browser interface instead, but the operating system has no graphical user interface and we don't want to expose the browser interface to the outside due to security risks.
In you home folder, download the "rabbitmqadmin" tool:
wget http://localhost:15672/cli/rabbitmqadmin
To make this tool accessible from any folder, move it as follows:
sudo mv rabbitmqadmin /usr/local/bin
To manage queues and exchanges with this tool, you use the RabbitMQ user "localrmqadmin" you created earlier. Example command (please note you must assign the password):
rabbitmqadmin -u localrmqadmin -p PWD delete queue name=my-fancy-queue
For more information, see https://www.rabbitmq.com/management-cli.html
Get certificates
You need a certificate and keys to set up an encrypted connection. For more information, see this blog post.
Configure RabbitMQ
Update 13 Jun 2022! The config format suggested here has been deprecated since
RabbitMQ 3.7. It
still works as of version 3.10, but you should use the more convenient format
along with the filename rabbitmq.conf
. See https://www.rabbitmq.com/configure.html
This section explains how to enable and enforce encrypted connections as well as prevent the remote usage of admin users.
You can create/edit the config file as follows:
sudo nano /etc/rabbitmq/rabbitmq.config
Use the following in the file content.
Make sure the filepath to certificates and key is correct as well as the
format of the certificates.
The keys and certificates are expected to be located at
/home/hostadmin/certs
.
The config file does, for instance:
- block non-encrypted connections as
tcp_listeners
is empty - only accept TLS 1.2 (in two locations in the config for some reason)
- listen to connections at port 5671
- prevent "guest" and "localrmqadmin" from connecting remotely for increased security
- localrmqadmin has admin permissions
- guest is the default user and therefore vulnerable if not a loopback user
[
{ssl, [{versions, ['tlsv1.2']}]},
{rabbit, [
{loopback_users, [<<"guest">>, <<"localrmqadmin">>]},
{tcp_listeners, []},
{ssl_listeners, [5671]},
{ssl_options, [
{cacertfile,"/home/hostadmin/certs/rootca.pem"},
{certfile,"/home/hostadmin/certs/server.pem"},
{keyfile,"/home/hostadmin/certs/server.key"},
{verify,verify_none},
{fail_if_no_peer_cert,false},
{versions, ['tlsv1.2']}
]}
]}
].
Next, re-start RabbitMQ to apply the configuration:
sudo service rabbitmq-server restart
Next, try with a client program if you can access RabbitMQ. If problems occur (which is probable), see RabbitMQ logs. These reside in /var/log/rabbitmq
.