Safeguard
Supply Chain Security•

AMQP Explained: AMQP 1.0 vs 0-9-1 and How to Secure a Message Broker

AMQP is a binary protocol for reliable business messaging. How AMQP 1.0 and 0-9-1 differ on the wire, and how to secure the broker that runs them.

Safeguard Security Team
38 min read

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 ANONYMOUS mechanism.
  • In RabbitMQ, a blank node creates a guest user with password guest that can connect only from localhost, and the ANONYMOUS SASL mechanism is enabled by default and maps to guest. The production guidance is to delete guest and remove ANONYMOUS.
  • 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

VersionPublisher and dateStatus today
AMQP 0-9-1AMQP working group specification, 13 November 2008Widely deployed through RabbitMQ and its client libraries
AMQP 1.0 FinalAMQP working group, 7 October 2011Superseded by the OASIS Standard
OASIS AMQP Version 1.0OASIS Standard, 29 October 2012, in six parts (0 Overview, 1 Types, 2 Transport, 3 Messaging, 4 Transactions, 5 Security)Current
ISO/IEC 19464AMQP 1.0 approved by ISO and IEC through JTC 1, announced by OASIS on 1 May 2014Same 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 offset0 to 34567
AMQP 1.0 headerAMQPprotocol id (0 AMQP, 2 TLS, 3 SASL)major (1)minor (0)revision (0)
AMQP 0-9-1 headerAMQP0091

Frame layout

Every AMQP 1.0 frame starts with a fixed 8 byte header.

FieldPositionMeaning
SIZEBytes 0 to 3Unsigned 32 bit total frame size, header included. Fewer than 8 is malformed
DOFFByte 4Data offset in 4 byte words, where the body starts. Less than 2 is malformed
TYPEByte 50x00 for an AMQP frame, 0x01 for a SASL frame
ChannelBytes 6 to 7Channel number for AMQP frames; ignored for SASL frames
Extended headerByte 8 to DOFF times 4Reserved extension point
BodyRest of the frameA 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.

PerformativeScopeWhat it does
openConnection, channel 0 onlyAnnounces container id, maximum frame size, channel max, idle timeout and capabilities
beginSessionStarts a session on a channel, with transfer windows
attachLinkAttaches a named link with a source and target, roles and settlement modes
flowSession and linkUpdates session windows and link credit
transferLinkCarries all or part of a message, with a delivery tag
dispositionSessionReports delivery state and settlement for a range of deliveries
detachLinkDetaches a link, optionally closing it
endSessionEnds a session
closeConnectionCloses 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.

ModeValuesEffect
Sender settle modeunsettled (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 modefirst (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 typeDefault nameHow it routes
DirectEmpty string (the default exchange) and amq.directTo queues whose binding key equals the routing key
Fanoutamq.fanoutTo every bound queue, ignoring the routing key
Topicamq.topicBy pattern match on dot separated routing keys
Headersamq.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.

FieldSizeMeaning
Type1 octet1 METHOD, 2 HEADER (content header), 3 BODY (content body), heartbeat (see note)
Channel2 octets0 for connection level frames, 1 to 65535 for channels
Size4 octetsPayload length, excluding the frame end octet
PayloadSize octetsMethod arguments, content properties or body bytes
Frame end1 octetAlways 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

PortIANA service nameProtocolRegistered
5672amqpTCP, UDP, SCTP2006 (TCP and UDP), 2007 (SCTP)
5671amqpsTCP, 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:

PortUsed for (RabbitMQ)Should it be public?
5672, 5671AMQP 0-9-1 and AMQP 1.0, without and with TLSOnly 5671, and only to the clients that need it
15672, 15671Management UI and HTTP API, without and with TLS, when the management plugin is enabledNo
25672Inter node and CLI tool traffic (Erlang distribution)No; the guide says these ports "should not be publicly exposed"
4369epmd, peer discovery for nodes and CLI toolsNo
35672 to 35682CLI tool client port rangeNo
5552, 5551RabbitMQ Stream protocol, without and with TLSOnly if used
15692, 15691Prometheus metrics, if the plugin is enabledMonitoring 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:

AspectAMQP 0-9-1AMQP 1.0
ScopeWire protocol plus broker modelWire protocol and message format only
TopologyExchanges, queues, bindings declared over the wireNodes addressed by name; topology is implementation defined
SymmetryClient and server rolesPeer to peer; works with or without a broker
Frame header7 octets plus 0xCE frame end8 bytes with SIZE, DOFF, TYPE and channel
Flow controlConsumer prefetch (Basic.Qos) and channel flowSession windows and per link credit
Delivery statesConsumer ack and reject; brokers add extensionsAccepted, rejected, released, modified, with settlement modes
Security setupSASL inside Connection.Start; TLS as a separate portExplicit TLS and SASL layers by protocol id, or TLS on 5671
EncodingField tables and method argumentsSelf 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.

PropertyAMQP by itselfWhere it comes from
ConfidentialityNone; message bodies, routing keys and PLAIN credentials are cleartext on 5672TLS on 5671, or the 1.0 TLS layer upgrade
Integrity0-9-1 frame end octet and 1.0 SIZE and DOFF checks catch framing bugs, not tamperingTLS; application signatures over the bare message
Client authenticationSASL mechanism of the broker's choosing, including ANONYMOUSStrong passwords over TLS, x.509 through EXTERNAL, external identity backends
Server authenticationNone in AMQP itselfTLS, where the 1.0 standard says the client "MUST validate" the server certificate
AuthorisationNot defined by 1.0; 0-9-1 says only that it may differ per virtual hostBroker permission models (RabbitMQ regex triples, Artemis role based security settings)
Replay protectionNone at the AMQP layerTLS
Delivery guaranteesAt most once, at least once and, in 1.0, exactly once by settlement modeCorrect client settlement and acknowledgement code
AvailabilitySession windows, link credit, frame size limits, idle timeoutsBroker 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

ProtocolModel and transportBest fitSecurity modelOperational cost
AMQP 0-9-1Broker with exchanges, queues and bindings over TCP or TLSWork queues, routing by key or pattern, RPC style replies, mature client librariesSASL in Connection.Start, TLS listener, per vhost regex permissionsBroker cluster to run; topology lives in application code
AMQP 1.0Symmetric links with credit and settlement over TCP, TLS or WebSocketInteroperable messaging across brokers and vendors, standards driven environments, exactly once handoffsTLS and SASL security layers, broker specific authorisationMore concepts; address meaning varies by broker
MQTT 5.0Pub/sub through a broker over TCP, TLS or WebSocketMany small devices pushing telemetry, unreliable linksTLS, username and password or enhanced AUTH, broker topic ACLsLight clients; broker ACL design per device
Kafka protocolRequest and response API over TCP to a partitioned logHigh throughput event streams, replay from offsets, many independent readersSASL handshake and TLS, ACLs per resourceCluster sizing, partitions and retention to manage
Managed cloud queue servicesProvider HTTPS APIs, sometimes with an AMQP endpointTeams that want queues without running a brokerProvider identity and access policies, TLS by defaultPer 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 = none or bind plain TCP to loopback.
  • Fixing a remote login failure by setting loopback_users to none. That lets guest with 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 to anonymous_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 administrator tags.
  • 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 situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull 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

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.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.