skip to content

How do you control which TLS protocol versions and cipher suites Kafka negotiates, and what are sane defaults?

level: seniorimportance: should knowfreq 40%

answer

  1. ssl.enabled.protocols = TLSv1.2,TLSv1.3
  2. ban TLS 1.0/1.1, never SSLv3
  3. ssl.cipher.suites = explicit allow-list
  4. prefer ECDHE + AES-GCM/ChaCha20 (forward secrecy)
  5. JDK caps what's available; both sides must share one

basics

~10 s

Use ssl.enabled.protocols to allow versions (e.g. TLSv1.2,TLSv1.3) and ssl.protocol for the default context; restrict algorithms with ssl.cipher.suites. Sane defaults: enable only TLSv1.2 and TLSv1.3, disable TLSv1.0/1.1, and rely on strong AEAD ciphers (GCM/ChaCha20).

solid answer

~50 s

Three knobs govern the TLS algorithm envelope. ssl.enabled.protocols lists the allowed protocol versions the SSL context will offer/accept — modern default is TLSv1.2,TLSv1.3. ssl.protocol sets the SSLContext's primary protocol (commonly TLSv1.3, which still allows 1.2 if enabled). ssl.cipher.suites optionally pins the exact cipher suites; if unset, the JVM's defaults for the negotiated protocol apply. Best practice: enable only TLSv1.2 and TLSv1.3 (TLS 1.0/1.1 are deprecated and weak), and for 1.2 prefer forward-secret AEAD suites (ECDHE + AES-GCM or ChaCha20-Poly1305). TLS 1.3 simplifies this — its cipher suites are a small fixed set of AEAD ciphers with forward secrecy, and it can't be downgraded to legacy ciphers. These settings exist on both brokers and clients; broker and client must share at least one common protocol and cipher or the handshake fails. The JDK version also caps what's available.

go deeper

for a junior

Knows ssl.enabled.protocols restricts TLS versions and that 1.2/1.3 are the good ones.

for a middle

Configures protocol and cipher allow-lists and understands handshake mismatch failures.

for a senior

Explains forward secrecy, AEAD, TLS 1.3 advantages, and JDK-capped availability.

for a principal

Sets fleet TLS policy balancing security and client compatibility, and plans the 1.2→1.3 migration.

## What gets negotiated Every TLS connection negotiates two things during the handshake: a **protocol version** (TLS 1.2, 1.3, …) and a **cipher suite** (the bundle of algorithms for key exchange, bulk encryption, and integrity). Kafka exposes both as configuration so you can forbid weak choices. ## The properties - **`ssl.enabled.protocols`** — comma list of allowed versions, e.g. `TLSv1.2,TLSv1.3`. The endpoint will only offer/accept these. This is the primary lever for banning legacy TLS 1.0/1.1. - **`ssl.protocol`** — the name used to construct the `SSLContext` (default historically `TLSv1.2`, often set to `TLSv1.3`). The context can still negotiate any version in `ssl.enabled.protocols`; this mainly sets the 'highest/default' protocol family. - **`ssl.cipher.suites`** — an explicit allow-list of cipher suites. If empty, the JVM's default suites for the negotiated protocol are used. Use it to drop non-forward-secret or CBC suites on TLS 1.2. - **`ssl.provider` / `ssl.secure.random.implementation`** — advanced: choose the security provider / RNG (rarely changed). All of these apply on **both broker and client**. The handshake succeeds only if the two sides share at least one enabled protocol and one mutually acceptable cipher. ## Sane defaults - **Protocols:** enable only `TLSv1.2,TLSv1.3`. TLS 1.0 and 1.1 are deprecated (RFC 8996) and vulnerable to known attacks; do not enable them. SSLv3 is broken (POODLE) and must never be enabled. - **Ciphers on TLS 1.2:** prefer **ECDHE** key exchange (gives forward secrecy) with **AES-GCM** or **ChaCha20-Poly1305** AEAD bulk encryption. Avoid RC4, 3DES, static-RSA key exchange, and CBC-mode suites where possible. - **TLS 1.3:** its only cipher suites are AEAD with forward secrecy (`TLS_AES_128_GCM_SHA256`, `TLS_AES_256_GCM_SHA384`, `TLS_CHACHA20_POLY1305_SHA256`). There's nothing weak to remove, and 1.3 removes downgrade-prone legacy mechanisms — so enabling 1.3 is the simplest hardening win. ## Forward secrecy — why it matters A forward-secret suite (ECDHE/DHE) uses an ephemeral key exchange so that even if the broker's long-term private key is later stolen, past recorded sessions stay undecryptable. Static-RSA suites lack this. Prefer ECDHE everywhere. ## Operational notes - **JDK caps availability.** The set of usable protocols/ciphers is bounded by the JVM. A new TLS 1.3 cipher or curve may need a newer JDK; conversely some legacy ciphers are disabled at the JDK level via `java.security`. - **Pinning ciphers is brittle.** Over-tight `ssl.cipher.suites` lists break when a client/JDK lacks one of them, causing 'no cipher suites in common' handshake failures. Pin a small, well-supported set, not a single suite. - **Mismatch symptoms:** broker enabling only TLS 1.3 while an old client only speaks TLS 1.2 (and you disabled 1.2) → handshake failure. Keep 1.2 enabled until all clients support 1.3. - **Don't conflate with hostname verification or auth** — protocol/cipher selection is about the *strength* of encryption, independent of `ssl.endpoint.identification.algorithm` and mTLS.

  • Why prefer ECDHE-based cipher suites over static-RSA ones?
    ECDHE provides forward secrecy via ephemeral keys: even if the broker's long-term private key is later compromised, previously recorded sessions can't be decrypted. Static-RSA key exchange lacks this.
  • What happens if a broker enables only TLSv1.3 but a legacy client supports only TLSv1.2?
    The handshake fails — there's no common protocol. You must keep TLSv1.2 in ssl.enabled.protocols until all clients support 1.3, or the connection is rejected.

saying these in an interview costs you the question

  • Enabling TLSv1.0/1.1 for 'compatibility' — they're deprecated and weak.
  • Pinning a single cipher suite, which breaks clients lacking it ('no cipher suites in common').
  • Believing you can enable a TLS 1.3 cipher the JDK doesn't support — the JVM caps the available set.
  • Confusing cipher/protocol hardening with authentication — it's about encryption strength only.

context