Security Checklist
This checklist helps you review an EMQX deployment before exposing it to production traffic. It is organized by security layers so you can validate the full path from the operating system to the Dashboard. Use it during the initial rollout, after major topology changes, and as part of periodic security reviews.
Phase 1: Infrastructure and OS
- Raise operating system file descriptor limits and service-level
LimitNOFILEsettings to match your connection scale so the node does not fail under normal or hostile connection pressure. - Harden the TCP stack and firewall posture for long-lived MQTT traffic, including SYN flood protection, connection tracking capacity, and listener exposure on trusted interfaces only.
- Expose only the listeners your clients actually need. On untrusted networks, prefer encrypted listeners such as
8883and8084, and restrict plaintext listeners such as1883to internal or transitional use cases. See Listener Configuration and Enable SSL/TLS Connection. - Restrict inter-node ports with security groups or firewall rules. For the port mapping used inside a cluster, see Cluster Security.
- If nodes have multiple interfaces, bind Erlang distribution traffic to the private network interface only.
- If you deploy EMQX behind a load balancer or TCP proxy, enable Proxy Protocol only on the listeners that need the real client IP address or client certificate details.
- If Proxy Protocol is enabled for a listener, expose that address and port only to the designated proxy or load balancer. Enforce this in EMQX with
listeners.{type}.{name}.access_rules = ["allow <trusted-LB-CIDR>", "deny all"], combined with network-level controls (firewall, private network, or Unix socket). Otherwise, a client that reaches the port directly can craft a PROXY v2 frame with arbitrary peer-cert fields and impersonate any identity. - If a WebSocket listener (
wsorwss) is not behind a trusted proxy that overwrites thex-forwarded-forheader, setlisteners.{type}.{name}.websocket.proxy_address_header = ""(andwebsocket.proxy_port_header = "") so that IP-based authorization rules, banned clients, flapping detection, and audit logs use the real TCP peer address. When the header is honored, the derived source IP is client-supplied unless a trusted proxy overwrites the header; a proxy that only appends to the inbound header does not protect it. See Forwarded Client Address.
Phase 2: Erlang and Cluster
- Replace the default node cookie on every node in the cluster, and use the same high-entropy secret on all members. See Set Node Cookie.
- Protect
emqx.conf, ACL files, certificates, private keys, and other secret material with strict file permissions and secure secret-management processes. - Store secret-typed fields as
file://references instead of inline values whenever possible. For any field documented as a secret, such as SSL key passphrases, bridge and connector passwords, and API keys, set the value tofile:///path/to/secretso EMQX reads the secret from a file at startup and at every reload. This keeps plaintext secrets out of config files, API request bodies, configuration backups, and version control, which lowers the risk of leaking them when you share or export configurations. See Load Secrets from a File. - Keep clustering ports internal, and enable TLS for inter-node communication when traffic crosses less-trusted networks or public cloud boundaries. See Cluster Security.
- Re-check firewall rules, certificates, and cluster membership controls after adding nodes, moving networks, or changing deployment topology.
Phase 3: Transport Security
- Use TLS for production MQTT listeners whenever traffic crosses untrusted networks. See Network and TLS.
- Disable legacy protocol versions and weak cipher suites according to your organization's security baseline, and validate the final listener settings in staging before rollout.
- Use certificates issued by a trusted CA or by your internal PKI, and rotate them before they expire.
- Enable mutual TLS when device identity should be verified through client certificates. In this model, validate both client certificate chains and certificate presence during the TLS handshake. See X.509 Certificate Authentication.
- If you map peer-certificate fields to the MQTT username or client ID (
peer_cert_as_username/peer_cert_as_clientid), the listener must enforce mTLS (verify = verify_peer,fail_if_no_peer_cert = true) with a CA bundle you control. Without it, a client can present a self-signed certificate with an attacker-chosen CN/DN and impersonate any identity. As an additional layer for the empty-username case, setlisteners.{type}.{name}.enable_authn = quick_deny_anonymous. See Certificate Information Mapping. - If certificate revocation matters in your environment, evaluate CRL checks or OCSP stapling.
- Enable TLS for outbound connections to external resources such as HTTP authenticators, databases, and other integrations.
Phase 4: MQTT Access Control and Resource Protection
Configure at least one authenticator before exposing public listeners. By default, EMQX allows all clients to connect if authentication is not enabled. See Authentication.
Prefer per-device or per-application credentials instead of shared usernames, passwords, or certificates.
Bind the MQTT client ID to the authenticated identity whenever the authentication mechanism allows it. For example, verify a JWT
clientidclaim, map a certificate field withpeer_cert_as_clientid, have the HTTP authenticator reject mismatches, or pair the authenticator with a Client-Info rule. Without this binding:- A leaked credential can let an attacker create an unbounded number of sessions under random client IDs with a long Session Expiry Interval, causing idle persistent sessions to accumulate until broker memory is exhausted.
- An attacker holding any valid credential can take over a victim's session if the attacker knows the victim's client ID. MQTT uses the client ID alone to identify and resume a session. When the attacker connects with the same client ID, EMQX disconnects the victim. For MQTT 5.0 clients, EMQX sends a
DISCONNECTpacket with reason code0x8E(Session taken over). - If
Clean Start = 0, the attacker resumes the victim's session and inherits its existing subscriptions. EMQX authorizes a subscription when it is created and does not re-evaluate inherited subscriptions against the resuming identity. The attacker can therefore receive messages that the attacker's own authorization rules would deny.
Binding the client ID to the authenticated identity makes the authentication mechanism reject identity mismatches during connection, preventing this takeover. This inherited-subscription risk does not affect publishing because EMQX authorizes each publish operation against the current identity.
Choose an authentication mechanism that matches your trust model, such as X.509, JWT, SCRAM, or password-based authentication backed by a secure database.
When using password-based authentication, store salted password hashes instead of plaintext secrets, and prefer strong algorithms such as
bcryptorpbkdf2.Define topic permissions as narrowly as possible and review wildcard usage carefully. See Authorization.
When
${clientid},${username}, or${client_attrs.X}is used inside an ACL topic template (see Authorization Placeholders), validate those identity values so they cannot contain MQTT topic wildcards (+,#) or topic separators (/). An unvalidated identity substituted into a template likeclients/${clientid}/datacollapses into a wildcard pattern when the client ID is+(granting access to every other client's subtopics) or escapes its assigned subtree when the value istenantA/+or contains/. Enforce a strict identity format upstream, for example with a Client-Info rule, a JWT claim pattern, or rejection in the HTTP authenticator. Reject the connection rather than relying on the ACL to catch malformed substitutions.When you design outbound requests to external services, including HTTP authentication, HTTP authorization, and data-integration connectors, bridges, and actions, carry each secret in a field or header that EMQX recognizes as sensitive. This allows EMQX to mask the value as
******when the containing data is processed by its redaction logic, including in relevant logs, traces, and configuration API responses. Redaction is driven by the field or header name: for credentials placed in HTTP headers, use the standardAuthorization(orProxy-Authorization) header, which EMQX always redacts; for secrets in other configuration fields, name the field with a recognized sensitive key such aspassword,token,secret,secret_key, orjwt. A non-standard custom header such asx-custom-secret, or an unconventional field name, is not recognized, and its value can appear in clear text indebug-level logs and error messages.Remove or adjust permissive default rules before relying on authorization in production.
For file-based ACLs, use a deny-by-default posture where appropriate, such as ending rules with
{deny, all}and settingauthorization.no_match = deny. See Use ACL File.For brokers exposed to untrusted or public networks, consider setting
authorization.deny_action = disconnect(defaultignore). If a client tries to publish or subscribe to an unauthorized topic, EMQX disconnects the client instead of keeping the connection open. Combined with flapping detection, clients that repeatedly reconnect and trigger authorization denials are banned automatically. Thedeny_actionsetting is global, so it also disconnects legitimate clients that attempt a denied operation. Apply it when clients normally publish and subscribe only to authorized topics. Tune flapping detection thresholds to avoid banning clients during normal reconnection storms. See Authorization.Review authorization cache settings and authorizer order so that policy changes take effect as expected.
Constrain MQTT resource usage to reduce the impact of malformed or abusive clients. Review limits such as packet size, topic levels, subscriptions, inflight windows, and queued messages. See MQTT Configuration.
Apply listener-level rate controls where needed to limit connection and publish bursts. See Rate Limiter Configuration.
Use Banned Clients and Flapping Detect to contain abusive or unstable clients when needed.
If Cluster Linking is enabled, enforce authentication on the listener that accepts peer connections, restrict the
$LINK/control namespace to the dedicated Cluster Linking ClientIDs, and deny it for everyone else. See Secure Cluster Linking.
Phase 5: Administration and Maintenance
- Change the default Dashboard password before production use, and review who has administrative access. See System.
- Keep the Dashboard on trusted networks only. Prefer HTTPS for administrator access, and bind Dashboard listeners to localhost, a private interface, or a protected management network where possible. See Dashboard Configuration.
- Enable SSRF protection under Management -> Cluster Settings -> Rule Engine Security to validate HTTP and MQTT connector targets when a connector configuration is tested, created, or updated. Starting from EMQX 6.0.4, the policy does not cover other connector types or runtime connections. Add host-level egress controls when delegated administrators can create or modify rule-engine resources or when you need a complete outbound network boundary. See Rule Engine Security and Mitigate SSRF with Rule Engine Policy and Firewall Rules.
- If you expose the management API, use API keys instead of Dashboard credentials, grant only the minimum role required, and set expiration dates where possible. See REST API and System.
- If you use EMQX Enterprise, consider Single Sign-On (SSO) for administrative users, and enforce MFA in your identity provider when available.
- Schedule regular backups and rehearse restore procedures. Note that certificates or ACL files stored outside the EMQX data directory require separate backup. See Backup and Restore.
- Enable audit trails where available, and centralize logs and metrics in your observability stack for anomaly detection and incident response. See Audit Log, Logs Configuration, and Logs and Observability.
Revalidate After Change
- Re-run this checklist after certificate rotation, listener changes, load balancer updates, cluster expansion, backup policy changes, or any change to the authentication and authorization chain.
- Validate the expected failure modes before production cutover, such as rejected anonymous clients, failed TLS handshakes for invalid certificates, and denied publish or subscribe operations outside allowed topics.