Kafka Broker Security Protocols
Concept
A message broker (Kafka, RabbitMQ) that accepts unauthenticated or unencrypted connections is a single point where anyone on the network — a compromised host, a misconfigured service, an attacker who's gained a foothold — can read every message flowing through it or inject fabricated ones. Kafka's security.protocol setting controls both halves of that exposure independently: whether the connection is encrypted (is the wire readable by a network observer) and whether it's authenticated (does the broker know who's connecting). Four values combine those two axes:
- PLAINTEXT — no encryption, no authentication. Anyone who can reach the broker on the network can read and write to any topic.
- SSL — encrypts the connection (TLS) but authenticates only the broker's identity to the client by default; client authentication requires additionally enabling mutual TLS (see Mutual TLS (mTLS)).
- SASL_PLAINTEXT — authenticates the client (via a SASL mechanism — PLAIN, SCRAM, GSSAPI/Kerberos, or OAUTHBEARER) but does not encrypt the connection. Credentials and message contents both travel in the clear.
- SASL_SSL — both: TLS encrypts the wire, SASL authenticates the client. This is the combination that provides real security for anything not fully inside a locked-down private network.
The critical distinction buried in the naming: SASL's PLAIN mechanism (a username/password check) is a different thing from the PLAINTEXT protocol (no encryption at all). Using SASL/PLAIN authentication without SSL — i.e. SASL_PLAINTEXT — sends that username and password over the wire unencrypted, which defeats the purpose of authenticating in the first place. Kafka's own security documentation is explicit that SASL/PLAIN should only ever be paired with SSL.
Kafka also separates client-to-broker security from inter-broker security (security.inter.broker.protocol, defaulting to PLAINTEXT if not set explicitly) — a cluster can be locked down for external clients while brokers still talk to each other unencrypted, which is easy to miss since it's a separate configuration surface from the client-facing listener.
Tradeoffs
| Protocol | Encryption | Client auth | Where it's acceptable |
|---|---|---|---|
| PLAINTEXT | None | None | Local dev only, or a fully isolated network with no untrusted hosts ever reachable — never over the public internet, never in a shared VPC with other tenants |
| SSL (no mTLS) | Yes | Broker→client only (unless mTLS enabled) | Encrypting traffic where authorization is handled another way (e.g. network-layer ACLs) is enough, but there's no cryptographic proof of client identity |
| SASL_PLAINTEXT | None | Yes | Rarely correct — authenticating a client while sending its credentials unencrypted is close to no security at all; only defensible transiently on a network that's already encrypted at a lower layer (e.g. inside an already-encrypted service mesh) |
| SASL_SSL | Yes | Yes | Default choice for anything outside a fully trusted, isolated private network — production Kafka clusters generally belong here |
SASL_SSL vs mTLS-only SSL is its own smaller tradeoff: SASL centralizes authentication and lets an ops team rotate credentials without reissuing client certificates, while mTLS ties identity to a certificate that also carries the encryption — simpler infrastructure (no separate SASL mechanism/credential store) but harder to rotate at scale, since every client needs a new cert. Some deployments use both: mTLS for encryption and coarse network-level trust, SASL for finer-grained per-client authentication and authorization mapping.
When to use / when not to
- Use SASL_SSL as the default for any Kafka deployment reachable from more than one team, service, or trust boundary — which in practice is nearly every production deployment.
- PLAINTEXT is acceptable only for local development or CI, never for anything that touches real data or crosses a network boundary that isn't fully controlled.
- If the deployment is already entirely inside a service mesh that terminates mTLS at every hop (see Service Mesh), broker-level SASL_SSL can be partially redundant with the mesh's own transport security — but broker-level authorization (topic-level ACLs) still needs SASL or mTLS client identity to key off of, so dropping broker-level auth entirely is rarely the right call even with a mesh in place.
- Don't rely on network segmentation (a private VPC) alone as a substitute for encryption/authentication — it protects against external attackers but not against a compromised host or misconfigured service already inside that network, which is a common real-world breach vector.
Common pitfall
Enabling SASL for client-facing listeners and stopping there, leaving security.inter.broker.protocol at its PLAINTEXT default. Inter-broker traffic — replication data, partition leader elections — then flows unencrypted and unauthenticated between brokers even though external clients are properly locked down, which both leaks the same sensitive message contents and gives an attacker who reaches the broker network a path to inject or intercept replication traffic directly. Every Kafka security hardening pass needs to explicitly set the inter-broker protocol, not just the client listener.
Engineering Lens
The useful audit question isn't "is Kafka using SSL" — it's naming, for each listener (client-facing and inter-broker separately), which of the two protections (encryption, authentication) is actually active, and why PLAINTEXT survives anywhere it does. Teams that inherit a Kafka cluster from an earlier, smaller-scope deployment often find PLAINTEXT client listeners left over from a dev setup that quietly became production, or inter-broker traffic that was never touched during a client-side security hardening pass — both invisible until someone asks the question directly per-listener rather than assuming "we did the Kafka security work" covers everything.