AMQP, the Advanced Message Queuing Protocol, is an open binary protocol that lets applications hand messages to each other reliably, usually through a broker. The name covers two different protocols: AMQP 0-9-1 (2008), which defines the broker model of exchanges, queues and bindings, and AMQP 1.0 (OASIS Standard, 29 October 2012, later ISO/IEC 19464), a symmetric transfer protocol that leaves broker internals open.
This post covers both on the wire, where SASL and TLS fit, the weakness classes seen in real deployments, and the RabbitMQ and ActiveMQ Artemis settings and commands a defender uses to check a broker they run. For a cross platform hardening checklist that also covers Kafka, see our message queue security guide.
Key takeaways
- AMQP 0-9-1 and AMQP 1.0 share a name and a port, not a wire format. The RabbitMQ compatibility page states plainly that AMQP 1.0 "is a completely different protocol" from 0-9-1 and uses different client libraries.
- AMQP 0-9-1 specifies the wire protocol and the broker model: publish to an exchange, bindings route into queues, consumers read queues.
- AMQP 1.0 specifies only transfer: a connection carries sessions, sessions carry links, links carry transfers. What a node is, is left to the implementation.
- IANA registers port 5672 (
amqp) and 5671 (amqps, AMQP over TLS). AMQP 1.0 can also upgrade a 5672 connection to TLS in band by sending a protocol header with protocol id 2, and to SASL with protocol id 3. - AMQP by itself gives you framing and delivery semantics, not confidentiality or integrity. Those come from TLS. Authentication comes from SASL, and the 1.0 standard tells a peer that does not need authentication to offer the
ANONYMOUSmechanism. - In RabbitMQ, a blank node creates a
guestuser with passwordguestthat can connect only from localhost, and theANONYMOUSSASL mechanism is enabled by default and maps toguest. The production guidance is to deleteguestand removeANONYMOUS. - Most broker problems are exposure and configuration: reachable management and cluster ports, wide permission regexes, unbounded queues, and consumers that deserialise untrusted bodies.
What AMQP is for, the layer and the standard
AMQP lets independent programs exchange business messages without sharing a database or calling each other synchronously. A producer hands a message to the broker and moves on; the broker keeps it until a consumer is ready, and redelivers it if the consumer fails before acknowledging. That is why AMQP sits behind order pipelines, job queues and service to service events. The OASIS abstract calls AMQP 1.0 "an open internet protocol for business messaging".
Why 0-9-1 and 1.0 are effectively different protocols
The two versions disagree on what should be standardised.
AMQP 0-9-1 standardises the broker. Its scope section says it "defines both the network protocol and the server-side services": the AMQ model of exchanges, queues and bindings, which clients declare and wire together over the protocol. The RabbitMQ concepts guide calls it a "programmable protocol".
AMQP 1.0 standardises the transfer. Part 2 defines "an efficient, binary, peer-to-peer protocol for transporting messages between two processes" and "is not concerned with the internal workings of any sort of node". There are no exchanges or bindings, and the RabbitMQ AMQP 1.0 guide notes that what an address refers to "is not defined by the AMQP 1.0 specification". Apache Qpid describes 1.0 as "fully symmetric (peer-to-peer)", usable with or without a broker.
So a 0-9-1 client cannot talk to a 1.0 endpoint, and security settings in one may not exist in the other. When someone says "we use AMQP", ask which one.
Where it sits in the stack
Both versions are application layer protocols over a reliable, ordered byte stream: in practice TCP, optionally wrapped in TLS. IANA also lists SCTP for port 5672, but TCP is what brokers deploy. Some brokers also accept AMQP over WebSocket; the ActiveMQ Artemis documentation describes it as supported "via a normal AMQP acceptor". Everything our TCP vs UDP eavesdropper post says about plaintext TCP applies to AMQP on 5672 without TLS.
The defining standards
| Version | Publisher and date | Status today |
|---|---|---|
| AMQP 0-9-1 | AMQP working group specification, 13 November 2008 | Widely deployed through RabbitMQ and its client libraries |
| AMQP 1.0 Final | AMQP working group, 7 October 2011 | Superseded by the OASIS Standard |
| OASIS AMQP Version 1.0 | OASIS Standard, 29 October 2012, in six parts (0 Overview, 1 Types, 2 Transport, 3 Messaging, 4 Transactions, 5 Security) | Current |
| ISO/IEC 19464 | AMQP 1.0 approved by ISO and IEC through JTC 1, announced by OASIS on 1 May 2014 | Same protocol as OASIS AMQP 1.0, maintained by the OASIS AMQP Technical Committee |
How AMQP 1.0 works on the wire
Containers, nodes, connections, sessions and links
AMQP 1.0 has a small vocabulary that is worth learning precisely.
- A container is an application: a broker, or a client program. Each container holds nodes.
- A node is something that sends, receives or stores messages: a producer, a consumer or a queue.
- A connection is a "full-duplex, reliably ordered sequence of frames" between two containers. It is divided into a negotiated number of unidirectional channels.
- A session pairs two unidirectional channels into "a bidirectional, sequential conversation" and provides flow control based on the number of transfer frames.
- A link is a unidirectional route between a source on one node and a target on another, attached to a session. Links are named, and "Links are named so that they can be recovered when communication is interrupted."
- A delivery is one message moving across a link, identified by a delivery tag.
A client that wants to send to a broker queue opens a connection, begins a session, attaches a sending link whose target is the queue's address, and transfers messages on it. To consume, it attaches a receiving link whose source is the queue and grants credit.
Protocol header and version negotiation
Before any frame, each side sends an 8 octet protocol header: AMQP, a protocol id byte, then major, minor and revision. The TCP client sends first. A server that does not support the requested version replies with one it does support and closes the socket. A multi protocol broker reads the client's header and picks the matching protocol, which is how RabbitMQ serves 0-9-1 and 1.0 on one port.
| Byte offset | 0 to 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|
| AMQP 1.0 header | AMQP | protocol id (0 AMQP, 2 TLS, 3 SASL) | major (1) | minor (0) | revision (0) |
| AMQP 0-9-1 header | AMQP | 0 | 0 | 9 | 1 |
Frame layout
Every AMQP 1.0 frame starts with a fixed 8 byte header.
| Field | Position | Meaning |
|---|---|---|
| SIZE | Bytes 0 to 3 | Unsigned 32 bit total frame size, header included. Fewer than 8 is malformed |
| DOFF | Byte 4 | Data offset in 4 byte words, where the body starts. Less than 2 is malformed |
| TYPE | Byte 5 | 0x00 for an AMQP frame, 0x01 for a SASL frame |
| Channel | Bytes 6 to 7 | Channel number for AMQP frames; ignored for SASL frames |
| Extended header | Byte 8 to DOFF times 4 | Reserved extension point |
| Body | Rest of the frame | A performative, then an optional opaque payload |
Before the peers negotiate limits, the maximum frame size is 512 bytes (the constant MIN-MAX-FRAME-SIZE) and the maximum channel number is 0. Both peers must accept frames up to 512 octets. A frame with a header and no body is valid and is used as a keepalive.
The nine performatives
The body of every AMQP frame begins with one of nine performatives, each encoded in the AMQP type system defined in Part 1.
| Performative | Scope | What it does |
|---|---|---|
| open | Connection, channel 0 only | Announces container id, maximum frame size, channel max, idle timeout and capabilities |
| begin | Session | Starts a session on a channel, with transfer windows |
| attach | Link | Attaches a named link with a source and target, roles and settlement modes |
| flow | Session and link | Updates session windows and link credit |
| transfer | Link | Carries all or part of a message, with a delivery tag |
| disposition | Session | Reports delivery state and settlement for a range of deliveries |
| detach | Link | Detaches a link, optionally closing it |
| end | Session | Ends a session |
| close | Connection | Closes the connection, optionally with an error |
A full exchange, step by step
The text diagram below shows a client publishing one message to a broker over TLS and SASL, using the in band upgrade the standard defines. Each line is one direction of traffic.
TCP client (producer) TCP server (broker)
--------------------- -------------------
TCP connect accept
"AMQP" 2.1.0.0 (ask for TLS layer) ---->
<---- "AMQP" 2.1.0.0
TLS handshake (client validates server certificate)
"AMQP" 3.1.0.0 (ask for SASL layer) ---->
<---- "AMQP" 3.1.0.0
<---- sasl-mechanisms [PLAIN, EXTERNAL]
sasl-init (mechanism PLAIN, response) ---->
<---- sasl-outcome (code ok)
"AMQP" 0.1.0.0 (plain AMQP inside) ---->
<---- "AMQP" 0.1.0.0
open (container-id, max-frame-size) ---->
<---- open
begin (channel 0, windows) ---->
<---- begin
attach (name, role sender, target) ---->
<---- attach
<---- flow (link-credit 100)
transfer (delivery-tag 1, message) ---->
<---- disposition (accepted, settled)
detach / end / close ---->
<---- detach / end / close
A client connecting to port 5671 skips the first header exchange: the standard's "alternative establishment" lets a server run "a pure TLS server", so the TLS handshake happens straight after TCP connect and the SASL header follows inside it.
Flow control: session windows and link credit
At the session layer, each side advertises an incoming window of transfer frames it will accept. At the link layer, the receiver grants link credit, the number of messages the sender may send; the sender must stop at zero. A synchronous get grants a credit of 1, a streaming consumer grants more and tops it up, and credit 0 stops delivery. The drain flag asks the sender to use up or return remaining credit, so a receiver can tell an empty queue from a slow one.
Settlement and delivery guarantees
AMQP 1.0 builds its delivery guarantees out of settlement: the point at which an endpoint forgets a delivery. Each link declares settlement modes at attach.
| Mode | Values | Effect |
|---|---|---|
| Sender settle mode | unsettled (0), settled (1), mixed (2, the default) | Settled means the sender forgets the message as soon as it sends it: at most once |
| Receiver settle mode | first (0, the default), second (1) | Second means the receiver settles only after the sender confirms, the basis for exactly once |
The receiver reports an outcome with a disposition. The Messaging part defines four terminal outcomes: accepted (processed successfully), rejected (invalid and unprocessable), released (not and will not be processed, so it can be redelivered) and modified (not processed, with changed annotations). Unsettled deliveries survive a dropped connection because both ends keep their unsettled maps, and reattaching a link by name lets them reconcile.
One property matters for security reviews: the Messaging part says the bare message "MUST NOT be modified" by intermediaries, which "preserves message hashes, HMACs and signatures" that an application computes over it. AMQP does not sign messages, but it is designed not to break signatures you add yourself.
How AMQP 0-9-1 works: exchanges, queues and bindings
The AMQ model
In 0-9-1 the broker is the protocol. Its entities, which the RabbitMQ guide calls "AMQP entities", are:
- Virtual hosts. "A data partition within the server" with its own exchanges and queues. "Each connection MUST BE associated with a single virtual host", chosen after authentication; authorisation "MAY be unique to each virtual host".
- Exchanges. Routing agents that copy published messages to queues according to bindings.
- Queues. Stores that hold messages for consumers: durable, exclusive or auto delete.
- Bindings. Rules linking an exchange to a queue, usually with a routing key or pattern.
| Exchange type | Default name | How it routes |
|---|---|---|
| Direct | Empty string (the default exchange) and amq.direct | To queues whose binding key equals the routing key |
| Fanout | amq.fanout | To every bound queue, ignoring the routing key |
| Topic | amq.topic | By pattern match on dot separated routing keys |
| Headers | amq.match (and amq.headers in RabbitMQ) | By message header values, with x-match set to any or all |
The default exchange is a direct exchange with no name to which every queue is automatically bound by its own name, which "makes it seem like it is possible to deliver messages directly to queues". It is still an exchange, and RabbitMQ checks permissions on it under the name amq.default.
Connection setup
The 0-9-1 connection life cycle is a fixed method exchange on channel 0.
Client Server (broker)
------ ---------------
TCP connect, then "AMQP" 0 0 9 1 ---->
<---- Connection.Start (version, mechanisms)
Connection.Start-Ok (mechanism, response) -->
<---- Connection.Secure (challenge, optional)
Connection.Secure-Ok (response) ---->
<---- Connection.Tune (channel-max, frame-max, heartbeat)
Connection.Tune-Ok ---->
Connection.Open (virtual host) ---->
<---- Connection.Open-Ok
Channel.Open on channel 1 ---->
<---- Channel.Open-Ok
Basic.Publish + content header + body ---->
...
Connection.Close ---->
<---- Connection.Close-Ok
Authentication "uses the SASL challenge-response model"; with PLAIN the response is a login name and password. The specification also says "There are no confirmations in AMQP. Success is silent, and failure is noisy." Operational errors such as insufficient access rights close the channel; structural errors close the connection. Consumers acknowledge with Basic.Ack, but the base specification gives a publisher no positive answer; RabbitMQ documents its own 0-9-1 extensions on top.
Frame format
Every 0-9-1 frame is a 7 octet header, a payload and a single frame end octet.
| Field | Size | Meaning |
|---|---|---|
| Type | 1 octet | 1 METHOD, 2 HEADER (content header), 3 BODY (content body), heartbeat (see note) |
| Channel | 2 octets | 0 for connection level frames, 1 to 65535 for channels |
| Size | 4 octets | Payload length, excluding the frame end octet |
| Payload | Size octets | Method arguments, content properties or body bytes |
| Frame end | 1 octet | Always 0xCE. A wrong value is a fatal protocol error |
A published message is a method frame (Basic.Publish), then a content header frame with the body size and properties, then zero or more body frames, so a broker can route or discard a message after reading only its properties.
One documented inconsistency is worth knowing if you read packet captures. The 0-9-1 prose lists the heartbeat frame as type 4, while the formal grammar writes it as %d8. The RabbitMQ errata page resolves it: RabbitMQ, Qpid and OpenAMQ all send an eight byte heartbeat frame of type 8 on channel 0 with an empty payload and the 0xCE frame end.
How SASL and TLS layer in, and what ports 5672 and 5671 are
Security layers in AMQP 1.0
Part 5 of the OASIS standard defines security layers that wrap the AMQP connection and can be stacked, "for instance a security layer used by the peers to do authentication might be tunneled through a security layer established for encryption purposes". There are two:
- TLS, requested with protocol id 2. The rules are short and strict: the TLS client "SHOULD use the server name indication extension", and "The TLS client MUST validate the certificate presented by the TLS server."
- SASL, requested with protocol id 3. SASL frames use frame type 0x01, are capped at 512 bytes with no way to negotiate larger, and carry five bodies: sasl-mechanisms, sasl-init, sasl-challenge, sasl-response and sasl-outcome.
The server lists its mechanisms in decreasing order of preference. The client "MUST authenticate using the highest-level security profile it can handle from the list provided by the partner". The outcome carries a code: 0 ok, 1 auth (bad credentials), 2 sys, 3 sys-perm and 4 sys-temp. The sasl-init frame also carries an optional hostname, which proxies can use to pick a backend; if TLS SNI was used, the hostname should match it or be null.
Note that a peer that "does not require its partner to authenticate" SHOULD offer only ANONYMOUS: anonymous access is a documented mode, not a bug. In practice brokers rely on TLS for confidentiality and SASL for identity.
Authentication in AMQP 0-9-1
In 0-9-1 there is no separate security layer header. Authentication happens inside the Connection.Start, Start-Ok, Secure and Secure-Ok methods, and TLS is a separate listener. RabbitMQ's built in mechanisms are PLAIN, AMQPLAIN (a non standard variant of PLAIN kept for compatibility), ANONYMOUS, RABBIT-CR-DEMO, and EXTERNAL through a plugin for x.509 certificate authentication. PLAIN sends the password inside the protocol, which is why the access control guide pairs passwords with TLS.
Ports
| Port | IANA service name | Protocol | Registered |
|---|---|---|---|
| 5672 | amqp | TCP, UDP, SCTP | 2006 (TCP and UDP), 2007 (SCTP) |
| 5671 | amqps | TCP, UDP ("amqp protocol over TLS/SSL") | 26 March 2008 |
The 1.0 transport chapter defines PORT 5672 and SECURE-PORT 5671 as constants. A broker also opens other ports that are not AMQP. The RabbitMQ networking guide lists them, and every one belongs in your firewall review:
| Port | Used for (RabbitMQ) | Should it be public? |
|---|---|---|
| 5672, 5671 | AMQP 0-9-1 and AMQP 1.0, without and with TLS | Only 5671, and only to the clients that need it |
| 15672, 15671 | Management UI and HTTP API, without and with TLS, when the management plugin is enabled | No |
| 25672 | Inter node and CLI tool traffic (Erlang distribution) | No; the guide says these ports "should not be publicly exposed" |
| 4369 | epmd, peer discovery for nodes and CLI tools | No |
| 35672 to 35682 | CLI tool client port range | No |
| 5552, 5551 | RabbitMQ Stream protocol, without and with TLS | Only if used |
| 15692, 15691 | Prometheus metrics, if the plugin is enabled | Monitoring network only |
Other brokers differ. The ActiveMQ Artemis documentation says that by default it has acceptors accepting AMQP connections on ports 61616 and 5672.
Versions and history
AMQP went through versions numbered 0-8, 0-9, 0-9-1 and 0-10 before 1.0. RabbitMQ supports 0-8, 0-9 and 0-9-1 on the same port and does not implement the 0-9-1 classes that were deprecated (access, dtx, file, stream, test and tunnel). The working group released "AMQP v1.0 Final" on 7 October 2011, OASIS made it a standard on 29 October 2012, and OASIS announced ISO/IEC approval as ISO/IEC 19464 on 1 May 2014. What changed between 0-9-1 and 1.0 is close to everything:
| Aspect | AMQP 0-9-1 | AMQP 1.0 |
|---|---|---|
| Scope | Wire protocol plus broker model | Wire protocol and message format only |
| Topology | Exchanges, queues, bindings declared over the wire | Nodes addressed by name; topology is implementation defined |
| Symmetry | Client and server roles | Peer to peer; works with or without a broker |
| Frame header | 7 octets plus 0xCE frame end | 8 bytes with SIZE, DOFF, TYPE and channel |
| Flow control | Consumer prefetch (Basic.Qos) and channel flow | Session windows and per link credit |
| Delivery states | Consumer ack and reject; brokers add extensions | Accepted, rejected, released, modified, with settlement modes |
| Security setup | SASL inside Connection.Start; TLS as a separate port | Explicit TLS and SASL layers by protocol id, or TLS on 5671 |
| Encoding | Field tables and method arguments | Self describing AMQP type system |
Both are deployed today. Since 4.0, RabbitMQ supports 1.0 natively alongside 0-9-1 on the same listener, says it "will continue to support AMQP 0-9-1 indefinitely", and has deprecated its v1 address format for 1.0 clients in favour of v2. Apache Qpid components and ActiveMQ Artemis implement 1.0. Expect both protocols in a large fleet.
Security properties: what AMQP does and does not guarantee
Neither version has its own cryptography. Both lean on TLS for transport security and on SASL or the broker for identity.
| Property | AMQP by itself | Where it comes from |
|---|---|---|
| Confidentiality | None; message bodies, routing keys and PLAIN credentials are cleartext on 5672 | TLS on 5671, or the 1.0 TLS layer upgrade |
| Integrity | 0-9-1 frame end octet and 1.0 SIZE and DOFF checks catch framing bugs, not tampering | TLS; application signatures over the bare message |
| Client authentication | SASL mechanism of the broker's choosing, including ANONYMOUS | Strong passwords over TLS, x.509 through EXTERNAL, external identity backends |
| Server authentication | None in AMQP itself | TLS, where the 1.0 standard says the client "MUST validate" the server certificate |
| Authorisation | Not defined by 1.0; 0-9-1 says only that it may differ per virtual host | Broker permission models (RabbitMQ regex triples, Artemis role based security settings) |
| Replay protection | None at the AMQP layer | TLS |
| Delivery guarantees | At most once, at least once and, in 1.0, exactly once by settlement mode | Correct client settlement and acknowledgement code |
| Availability | Session windows, link credit, frame size limits, idle timeouts | Broker resource limits, queue length limits, memory and disk alarms |
The 0-9-1 security chapter relies on "length-specified buffers in all places" and treats errors during connection negotiation as hostile: pause, close, and "log all such exceptions and flag or block clients provoking multiple failures". The 1.0 security part is about layers, not threats, so most practical guidance comes from broker documentation.
Weakness classes, explained as concepts
These are the recurring ways AMQP deployments go wrong. Each is described at the level of what fails and why the design allows it, not how to abuse it.
Default credentials and anonymous login
Brokers ship with a known starting identity so they work on first install. A blank RabbitMQ node creates "a user named guest with a default password of guest, granted full access to the / virtual host", limited to localhost by the loopback_users setting. The weakness appears when an operator sets loopback_users to none to make a remote client work, which the documentation labels a "DANGER ZONE". Anonymous login is the same class: RabbitMQ's ANONYMOUS mechanism "is enabled by default", and unauthenticated clients act as anonymous_login_user, which defaults to guest. Inherit a default identity, loosen its network restriction, and the broker is effectively unauthenticated.
Exposed management interfaces and cluster ports
A broker is more than its AMQP port. RabbitMQ's management UI and HTTP API on 15672 can, depending on user tags, manage policies, users and permissions. Ports 25672 and 4369 serve nodes and CLI tools, authenticated by the Erlang cookie, which the rabbitmq-diagnostics manual calls "the shared secret used by the target node to authenticate CLI tools and peers", and epmd "will listen on all interfaces by default". The weakness class is control plane exposure: operator interfaces reachable from untrusted networks, guarded by one shared secret or weak management passwords. Our posts on RabbitMQ management CVEs and RabbitMQ server CVEs by listener show why each listener needs its own exposure decision.
Overbroad authorisation
RabbitMQ permissions are "a triple of regular expressions, one each for configure, write and read", per virtual host. The documented example uses .* for all three; copied into production, it lets every application declare, delete, publish to and read every resource. The restrictive pattern, ^$, must be chosen deliberately. Management tags (management, policymaker, monitoring, administrator) are a separate model for UI and API access, which makes mistakes in both directions easy. ActiveMQ Artemis has the same shape: role based permissions such as send, consume, browse and manage matched against address wildcards, with security enabled by default unless security-enabled is set to false.
Unbounded queues and resource exhaustion
A queue is storage that someone else fills. If consumers stall, it grows until memory or disk runs out. AMQP flow control protects buffers between two peers, not the broker's total storage. In RabbitMQ, a queue has a length limit only if you set one; at the limit, the default drops or dead letters the oldest messages, and reject-publish pushes back on producers instead. Per user and per virtual host limits keep one tenant from exhausting the broker for the others. The MQTT broker limits post covers the same idea for MQTT brokers.
Message deserialisation in consumers
AMQP moves opaque bytes; the risk sits in the consumer. If it rebuilds objects from message bodies with a language's native object serialisation, anyone allowed to publish to that queue can influence which objects the consumer constructs, and broker permissions become the only barrier. The ActiveMQ Artemis guide shows the default for JMS ObjectMessage: both allow and deny lists are empty, "meaning any serializable object is allowed to be deserialized". Use data only formats such as JSON or Protocol Buffers with schema validation, or strict allow lists. Our insecure deserialisation explainer and deserialisation attacks in Java and Python go deeper.
Cleartext listeners and unverified certificates
AMQP on 5672 without TLS exposes PLAIN credentials, routing keys, headers and bodies to the path. Adding 5671 while leaving 5672 open "for internal clients" keeps the cleartext path available. The mirror image is a client that skips server certificate validation, which the 1.0 standard forbids, giving encryption to whoever answers rather than to your broker.
Pre authentication parsing and negotiation
Brokers parse headers, frames and SASL exchanges from unauthenticated clients, and a multi protocol port widens that parser surface. Bugs here are implementation bugs in the broker or client library, so knowing exactly which versions you run is a security control in its own right.
Secure configuration, with defender side check commands
The commands below come from the official RabbitMQ documentation and man pages, the ActiveMQ Artemis documentation and the Linux ss man page, all cited in Sources. Only run them against systems you own or are authorised to test. RabbitMQ commands assume a 4.x node; check the documentation for your version.
Listeners and exposure
Start with what the node actually listens on. rabbitmq-diagnostics listeners prints each interface, port, protocol and purpose. Cross check from the operating system with ss (-t TCP, -l listening, -n numeric, -p process).
rabbitmq-diagnostics listeners
rabbitmq-diagnostics check_port_listener 5672
ss -tlnp
check_port_listener fails if no listener uses the given port, so automation can prove a port is closed or open. To accept only TLS clients, the TLS guide gives this rabbitmq.conf pattern:
# disables non-TLS listeners, only TLS-enabled clients will be able to connect
listeners.tcp = none
listeners.ssl.default = 5671
ssl_options.cacertfile = /path/to/ca_certificate.pem
ssl_options.certfile = /path/to/server_certificate.pem
ssl_options.keyfile = /path/to/server_key.pem
ssl_options.verify = verify_peer
ssl_options.fail_if_no_peer_cert = true
If plain TCP must stay for local tools, bind it to loopback (listeners.tcp.1 = 127.0.0.1:5672). Limit epmd with the ERL_EPMD_ADDRESS environment variable, and keep 25672, 4369 and 35672 to 35682 on the cluster network.
TLS versions, ciphers and peer verification
Erlang 26 and 27 enable TLSv1.3 and TLSv1.2 by default; set a floor with ssl_options.versions:
listeners.ssl.1 = 5671
ssl_options.cacertfile = /path/to/ca_certificate.pem
ssl_options.certfile = /path/to/server_certificate.pem
ssl_options.keyfile = /path/to/server_key.pem
ssl_options.versions.1 = tlsv1.2
Then verify from the node and from a client host, using the checks in the TLS guides and the rabbitmq-diagnostics man page:
rabbitmq-diagnostics --silent tls_versions
rabbitmq-diagnostics cipher_suites --format openssl -q
rabbitmq-diagnostics certificates
rabbitmq-diagnostics check_certificate_expiration --unit weeks --within 6
# should succeed
openssl s_client -connect 127.0.0.1:5671 -tls1_3
openssl s_client -connect 127.0.0.1:5671 -tls1_2
For client certificates, ssl_options.verify = verify_peer verifies a certificate the client sends, and fail_if_no_peer_cert = true rejects clients that send none; with verify_none, "peer verification will be disabled". Make sure client libraries validate the broker's certificate and hostname. To see which live connections use TLS, and with which mechanism:
rabbitmqctl list_connections user peer_host ssl ssl_protocol auth_mechanism protocol
Any row with ssl set to false, an old ssl_protocol, or auth_mechanism showing ANONYMOUS deserves a follow up.
Users, virtual hosts and permissions
Delete guest in production, create one user per application with a generated password, and use a virtual host per tenant or environment. To review what exists:
rabbitmqctl list_users
rabbitmqctl list_vhosts
rabbitmqctl list_permissions -p my-vhost
rabbitmqctl list_topic_permissions -p my-vhost
rabbitmqctl list_user_permissions janeway
rabbitmqctl authenticate_user janeway verifyit
list_users shows tags, so unexpected administrator accounts stand out; flag any .* in list_permissions that is not a deliberate admin grant. authenticate_user confirms a credential works after a rotation (use a test account). To remove the default account and anonymous logins:
rabbitmqctl delete_user guest
# rabbitmq.conf: offer only named-user mechanisms
auth_mechanisms.1 = PLAIN
auth_mechanisms.2 = AMQPLAIN
# none means no user is configured for anonymous logins
anonymous_login_user = none
The EXTERNAL mechanism, through the rabbitmq_auth_mechanism_ssl plugin, ties identity to a client certificate instead of a password.
Limits and queue bounds
Set queue length limits by policy, so operators control them:
rabbitmqctl set_policy my-pol "^one-meg$" '{"max-length-bytes":1048576}' --apply-to queues
rabbitmqctl set_policy my-pol "^two-messages$" '{"max-length":2,"overflow":"reject-publish"}' --apply-to queues
rabbitmqctl list_policies -p my-vhost
rabbitmqctl list_queues -p my-vhost messages consumers
list_queues shows queues growing with no consumers. For tenants, use virtual host and user limits:
rabbitmqctl set_vhost_limits -p qa_env '{"max-connections": 64}'
rabbitmqctl set_user_limits limited_user '{"max-channels": 16}'
rabbitmqctl list_vhost_limits -p qa_env
The production checklist recommends a memory high watermark between 0.4 and 0.7 of RAM (the default is 0.6) and a disk_free_limit well above the 50 MB default, about the size of the memory watermark.
The management interface
Port 15672 "does not support AMQP 0-9-1, AMQP 1.0, STOMP or MQTT connections", so application clients never need it. Keep it on an operator network, serve it over TLS on 15671, give dashboards monitoring rather than administrator tags, and prefer external monitoring, as the management guide recommends.
If you run ActiveMQ Artemis or Apache Qpid
In Artemis, check that broker.xml does not set security-enabled to false, that each security-setting grants send, consume and queue management only to the roles that need them, and that acceptors on 5672 and 61616 bind where you intend and use TLS off host. Configure the JMS deserialisation allow list. Setting amqpIdleTimeout=0 tells clients not to send keepalives and leaves dead connection detection to TCP. Qpid Broker-J documents authentication providers, ports and connection limits in its broker book.
When to use AMQP versus the alternatives
| Protocol | Model and transport | Best fit | Security model | Operational cost |
|---|---|---|---|---|
| AMQP 0-9-1 | Broker with exchanges, queues and bindings over TCP or TLS | Work queues, routing by key or pattern, RPC style replies, mature client libraries | SASL in Connection.Start, TLS listener, per vhost regex permissions | Broker cluster to run; topology lives in application code |
| AMQP 1.0 | Symmetric links with credit and settlement over TCP, TLS or WebSocket | Interoperable messaging across brokers and vendors, standards driven environments, exactly once handoffs | TLS and SASL security layers, broker specific authorisation | More concepts; address meaning varies by broker |
| MQTT 5.0 | Pub/sub through a broker over TCP, TLS or WebSocket | Many small devices pushing telemetry, unreliable links | TLS, username and password or enhanced AUTH, broker topic ACLs | Light clients; broker ACL design per device |
| Kafka protocol | Request and response API over TCP to a partitioned log | High throughput event streams, replay from offsets, many independent readers | SASL handshake and TLS, ACLs per resource | Cluster sizing, partitions and retention to manage |
| Managed cloud queue services | Provider HTTPS APIs, sometimes with an AMQP endpoint | Teams that want queues without running a broker | Provider identity and access policies, TLS by default | Per request cost and provider coupling; less control over placement |
Kafka uses "a binary protocol over TCP" of request and response pairs, and consumers fetch from a retained log by offset, whereas AMQP queues remove a message once it is settled or acknowledged. Choose AMQP 0-9-1 for a flexible broker that routes work to competing consumers, AMQP 1.0 when interoperability or precise delivery state matters, MQTT for constrained devices (see our MQTT 5 explainer), and a log when consumers need to replay history.
Common mistakes
- Treating "AMQP" as one protocol. 0-9-1 and 1.0 clients are not interchangeable.
- Opening 5671 and leaving 5672 open as well. Use
listeners.tcp = noneor bind plain TCP to loopback. - Fixing a remote login failure by setting
loopback_usersto none. That letsguestwith its public password log in from anywhere. Create a real user instead. - Leaving ANONYMOUS in
auth_mechanisms. It is enabled by default in RabbitMQ and maps toanonymous_login_user. - Granting
.*for configure, write and read to every application because the documentation example does. - Publishing the management UI on 15672 to the internet, or giving dashboards
administratortags. - Exposing 25672 and 4369 outside the cluster network, which puts the CLI and inter node control plane behind one shared cookie.
- Running queues with no length limit and assuming consumers will always keep up.
- Using language native object serialisation for message bodies, or leaving the JMS deserialisation allow list empty.
- Disabling certificate verification in clients to get past a hostname mismatch.
FAQ
What port does AMQP use?
TCP 5672 for plain AMQP and TCP 5671 for AMQP over TLS, registered with IANA as amqp and amqps. RabbitMQ accepts both AMQP 0-9-1 and AMQP 1.0 on 5672 and 5671 and tells them apart by the protocol header.
Is AMQP encrypted?
Not by itself. Use TLS, either on port 5671 or, for AMQP 1.0, by upgrading the connection with the TLS security layer (protocol id 2). Without TLS, PLAIN passwords and message bodies cross the network in cleartext.
What is the difference between AMQP 0-9-1 and AMQP 1.0?
AMQP 0-9-1 (2008) standardises a broker model of exchanges, queues and bindings plus the wire protocol to drive it. AMQP 1.0 (OASIS 2012, ISO/IEC 19464) standardises a symmetric transfer protocol of connections, sessions, links, credit and settlement, and leaves broker internals to implementations. They use different frame formats and client libraries.
What is the default RabbitMQ username and password?
On a blank node RabbitMQ creates user guest with password guest in virtual host /, restricted to connections from localhost. The production checklist says to delete it and create a user per application with a generated password.
What are exchanges, queues and bindings in AMQP?
They are AMQP 0-9-1 concepts. Producers publish to an exchange, bindings tell the exchange which queues should get a copy based on routing keys or headers, and consumers read from queues. The four exchange types are direct, fanout, topic and headers.
AMQP vs MQTT: which should I use?
MQTT for large numbers of constrained devices sending small messages through a broker, AMQP for service to service messaging that needs routing, competing consumers and richer delivery states. Many systems bridge the two, with devices on MQTT and back end services on AMQP.
AMQP vs Kafka: what is the difference?
AMQP moves messages through queues and removes them once they are acknowledged or settled; flow is pushed by the broker within the consumer's prefetch or credit. Kafka uses its own request and response protocol to append to and read from a partitioned, retained log, so consumers can replay history by offset.
Is it safe to expose a RabbitMQ broker to the internet?
Only the TLS AMQP port, only with named users or client certificates, with ANONYMOUS and guest removed, tight permissions, and resource limits. Keep the management UI, Erlang distribution, epmd and CLI ports off public networks.
Fix it without waiting for upstream
AMQP problems that are not configuration usually live in code you depend on: the broker image in your cluster, the Erlang or Java runtime under it, or the AMQP client library compiled into every producer and consumer. Safeguard's software composition analysis, generally available, inventories those libraries with their full transitive dependencies, alongside SBOM generation in SPDX and CycloneDX and container image scanning, with vulnerability findings enriched with EPSS and CISA KEV data and ranked by reachability analysis, all generally available; Safeguard does not inspect, filter or block AMQP traffic.
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.
3. Gold Registry: start from components that are already fixed
registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | The Gold scan GitHub Action in CI, plus Safeguard policies and gates |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch (early access) |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would help
These demos show dependency, SBOM and remediation workflows, not message broker monitoring. You can download Safeguard and follow the CLI docs to try them on your own projects.
This demo sets up the Safeguard runner on your own machine, approves it with its device code and then scans from the terminal. Pointed at your broker's container image, or at a service that publishes or consumes AMQP messages, the same scan lists the broker, runtime and AMQP client libraries inside with their versions and any known vulnerabilities.
Click through it at your own pace, or open it full screen.
This demo is a real CLI session: install, open the interactive terminal, ask it to fix the lodash CVE in a repository, and watch it read the finding and advisory, ask before each command, move lodash to 4.17.21, run npm install and npm test with approval, and print a summary without pushing anything. The same approve each step flow applies when the package to bump is an AMQP client library or a serialisation library used by a consumer.
Click through it at your own pace, or open it full screen.
This demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. Once connected, you can ask in plain language which of your projects include a particular AMQP client or broker version, and get the answer from your own scan data rather than from memory.
Click through it at your own pace, or open it full screen.
Quick check
A team adds a TLS listener on 5671 and keeps 5672 open for internal services. What have they actually secured?
Only the clients that choose 5671. Anything that can reach 5672 can still connect in cleartext, and PLAIN credentials sent there are readable on the path. Disable the plain listener with listeners.tcp = none, or bind it to loopback, and confirm with rabbitmq-diagnostics listeners and ss -tlnp.
An AMQP 1.0 sender attaches with sender settle mode "settled". What delivery guarantee does that give?
At most once. A settled sender forgets each message as soon as it sends it, so a message lost in transit is not resent. At least once needs unsettled deliveries and a receiver disposition, and exactly once also needs the receiver to use settle mode "second".
Sources
- OASIS: AMQP Version 1.0, OASIS Standard, 29 October 2012 (complete PDF)
- OASIS: AMQP Version 1.0 Part 0, Overview
- OASIS: AMQP Version 1.0 Part 2, Transport
- OASIS: AMQP Version 1.0 Part 3, Messaging
- OASIS: AMQP Version 1.0 Part 5, Security
- OASIS: ISO and IEC Approve OASIS AMQP, 1 May 2014
- amqp.org: AMQP home
- AMQP 0-9-1 Protocol Specification, 13 November 2008 (as published by RabbitMQ)
- RabbitMQ: AMQP 0-9-1 errata
- RabbitMQ: Compatibility and conformance
- RabbitMQ: AMQP 0-9-1 model explained
- RabbitMQ: AMQP 1.0
- RabbitMQ: TLS support
- RabbitMQ: Troubleshooting TLS
- RabbitMQ: Authentication, authorisation, access control
- RabbitMQ: Networking and RabbitMQ
- RabbitMQ: Management plugin
- RabbitMQ: Production deployment guidelines
- RabbitMQ: Queue length limit
- RabbitMQ: Configuration
- RabbitMQ: rabbitmqctl(8)
- RabbitMQ: rabbitmq-diagnostics(8)
- Apache ActiveMQ Artemis: Security
- Apache ActiveMQ Artemis: AMQP
- Apache Qpid: AMQP
- Apache Qpid Broker-J book
- Apache Kafka: Protocol guide
- IANA: Service Name and Transport Protocol Port Number Registry
- man7.org: ss(8)
Last reviewed: 23 October 2026. Broker option names and defaults change between releases; check the documentation for the RabbitMQ, Artemis or Qpid version you run.