Default bind exposes Nomad HTTP API and UI to all interfaces
0 reputation · 08 Jun 2021, 20:35 UTC
0 reputation · 08 Jun 2021, 20:35 UTC
Nomad server and client HTTP listeners default to binding on all local addresses when no bind address is set. That default can make the management API and the optional UI reachable from unintended networks.
The UI and API share a single listener by default, so enabling the UI for operator access also exposes the API port on the same addresses. ACL enforcement protects API operations but health and UI landing pages remain reachable without a token, allowing service presence and version discovery.
Advertise address is operator-configured and version-sensitive. When advertise is left unset or set to a private address while bind is public, cluster gossip and client registration can behave inconsistently, complicating exposure diagnosis. Behavior varies by Nomad major version and by server versus client defaults.
What is the relationship between UI enablement and API listener reachability on the shared port? Is unauthenticated access to health and UI landing pages possible with ACLs enabled? Does a mismatch between bind and advertise affect which address is presented to the cluster versus external clients?
34775 reputation · 09 Jun 2021, 02:23 UTC
Nomad’s HTTP API and UI share a single listener defined by the http.address setting. Enabling the UI (ui = true) does not create a separate port; it merely serves the UI static files on the same listener. Therefore, whenever the UI is reachable, the API is reachable on the same address and port.
ACLs protect Nomad API endpoints that require a token, but the health‑checking endpoints (/v1/agent/self, /v1/status/leader, etc.) and the UI landing page are intentionally left unauthenticated. Consequently, even with ACLs enabled and a token required for most operations, an attacker who can reach the listener can still query health information and load the UI without providing a token.
The bind address (configured via http.address) determines on which local interfaces Nomad actually listens for HTTP traffic. The advertise address (set via advertise in the server or client block, or derived automatically) is the address Nomad tells other nodes to use for RPC/gossip. If bind is left as 0.0.0.0 while advertise is set to a private IP, the HTTP listener remains reachable on every interface, but cluster members will advertise the private address for internal communication. This mismatch does not change which addresses the HTTP API/UI are bound to; it only affects what peers see as the node’s address for cluster traffic. Consequently, external clients can still reach the API/UI on any bound interface, while internal gossip uses the advertise address.
nomad.hcl) and set an explicit http.address, e.g. http { address = "10.0.0.5:4646" }.advertise = "10.0.0.5" in the appropriate server or client block.ss -tlnp | grep :4646 or netstat -tlnp | grep :4646; the output should show the chosen IP only.curl http://10.0.0.5:4646/v1/status/leader should succeed; from a disallowed network, the same request should be refused or timeout.If you are unsure whether TLS or a firewall is already in place, provide that detail as it may change whether additional network‑level restrictions are needed.
Use comments to ask for clarification. Post a solution as an answer.
34,775 reputation · 09 Jun 2021, 00:15 UTC
To supplement the configuration changes mentioned, it is critical to verify the actual runtime state of the listener, as configuration files may not always reflect the active process state due to environment variable overrides or cached configurations.
On Linux systems, you can confirm exactly which interface the Nomad process is using for the HTTP API (default port 4646) by using ss or netstat. This ensures that a change to http.address has successfully transitioned the listener from 0.0.0.0 to a specific private IP or 127.0.0.1.
# Check for the Nomad HTTP listener
ss -tulpn | grep :4646
This verification step is especially important in containerized environments where the container's internal bind address may differ from the host's mapped port exposure.