LDAP, the Lightweight Directory Access Protocol, is how applications ask a directory questions: does this user exist, which groups is this account in, is this password right. Microsoft Active Directory speaks it, and so do OpenLDAP and most identity appliances. Almost every guide to it opens with the same two numbers, port 389 and port 636, and the same neat summary: one is cleartext, the other is encrypted.
The summary is tidy, and it causes real mistakes. People open 636 on a firewall and assume every directory connection is now protected, or they close 389 because "that is the insecure one" and break applications that were encrypting on it all along. The split is not really between two ports. It is between two ways of starting encryption.
The short answer#
- Port 389 is LDAP. A connection starts in cleartext. The client may upgrade it to TLS partway through with a command called StartTLS, or it may never do so.
- Port 636 is LDAPS. The TLS handshake happens the moment the connection opens, before a single LDAP message is sent. There is no unencrypted phase at all.
Both carry exactly the same protocol once they are running. Searches, binds (LDAP's word for logging in) and modifications look identical. The only difference is when, and whether, the encryption starts.
What runs on port 389#
IANA registers port 389 as ldap, "Lightweight Directory Access Protocol", on both TCP and UDP. The protocol itself is LDAP version 3, defined in RFC 4511, with authentication and StartTLS covered in RFC 4513.
A plain connection on 389 is readable by anyone who can see the traffic. That matters most for the simple bind, where the client sends a username and password. Without TLS, that password crosses the network as it was typed. RFC 4513 is blunt about it: implementations should not, by default, accept cleartext password authentication unless the session is protected by TLS. Plenty of older software ignores that advice, which is why "LDAP password captured on the wire" is still a routine penetration-test finding.
RFC 4513 also names a quieter trap, the unauthenticated bind: a simple bind with a username and an empty password. Some applications treat "the directory accepted the bind" as "the password was correct", so an empty password becomes a way in. The RFC says servers should reject these by default. It is worth confirming yours does.
UDP 389 is a different beast. Connectionless LDAP (CLDAP) answers small queries with much larger responses, which made it a favourite for reflection attacks. US-CERT's advisory on UDP amplification lists CLDAP with a bandwidth amplification factor of 56 to 70. Active Directory uses UDP 389 internally to locate domain controllers, so the fix is to keep it off the public internet, not to disable it. Our guide to how DDoS attacks work explains why that amplification matters.
What runs on port 636#
IANA registers port 636 as ldaps, with the description "ldap protocol over TLS/SSL (was sldap)". This is implicit TLS: the client connects, the two sides complete a TLS handshake, and only then does LDAP begin. If the handshake fails, there is no fallback to cleartext. The connection simply does not happen.
Here is the odd part of its history. LDAPS was never standardised the way StartTLS was. The LDAP RFCs define StartTLS as the way to encrypt a session, and the LDAP URL format in RFC 4516 defines only the ldap:// scheme. The ldaps:// form grew out of implementation practice rather than an RFC, and IANA's entry for 636 cites no reference document. Despite that, practically every directory server and client library supports it, and in many shops it is the default.
Encryption solves one problem and no others. A client connected to 636 can still guess passwords, and once it has bound successfully it can read whatever its account is allowed to read. LDAPS protects the conversation, not the directory.
How StartTLS muddies the split#
StartTLS is an LDAP extended operation (its identifier is 1.3.6.1.4.1.1466.20037). The client connects to 389 in cleartext, sends the StartTLS request, and if the server agrees, both sides run a TLS handshake over the same connection. Everything after that point is encrypted, just as it would be on 636.
So a StartTLS session on 389 and an LDAPS session on 636 end up equally protected. The difference lies in what happens when something goes wrong, and that is where the muddle comes from:
- The upgrade is optional. Nothing about port 389 forces a client to ask for TLS. An application configured for "LDAP on 389" may be encrypting or may not, and you cannot tell from the port number or the firewall rule.
- A failed upgrade can be silent. If the server refuses StartTLS, or an attacker in the path strips the request, a lenient client carries on in cleartext and sends the password anyway. With OpenLDAP's
ldapsearch, for example,-Zasks for StartTLS while-ZZrequires it to succeed. Only the second one refuses to continue unencrypted. - Certificate checks still apply. RFC 4513 requires the client to verify the server's identity from its certificate after the handshake. A client that skips that check is encrypted but not authenticated, on either port.
The same pattern shows up across the internet. Mail has submission on port 587 with STARTTLS and implicit TLS on 465, and the web settled on a separate port for HTTPS, as our explainer on port 80 versus port 443 describes. Implicit TLS fails closed. An in-band upgrade fails open unless the client insists.
Which one should you use#
Either is fine if it is configured strictly. In practice the choice usually comes down to what your client software handles well:
- Choose 636 when you want a rule that is easy to audit. If the firewall only allows 636, every connection that gets through is encrypted, and a misconfigured client fails loudly instead of leaking a password.
- Choose 389 with required StartTLS when your software expects the standard LDAPv3 approach, or when you need to keep one port for mixed traffic. Set the client to require StartTLS, and set the server to reject cleartext binds, so a failed upgrade stops the connection instead of degrading it.
- Avoid 389 without TLS for anything that sends a password, unless the traffic never leaves a network segment you fully trust. Even then, prefer encryption.
Active Directory adds its own settings on top. LDAP signing, when a domain controller is set to require it, rejects unsigned SASL binds and any simple bind made over a connection without SSL or TLS. Microsoft's documentation shows the resulting client error as Strong Authentication Required. Channel binding applies to LDAP over TLS and ties the authentication to that specific TLS session, which defends against man-in-the-middle relay. Microsoft's guidance (advisory ADV190023) is to enable both. Its 2020 updates added the controls without changing the defaults, so check what your domain controllers are actually enforcing rather than assuming.
The Active Directory extras: 3268 and 3269#
If you work with Active Directory you will meet two more numbers. Port 3268 is the Global Catalog over LDAP, and 3269 is the Global Catalog over LDAP with SSL. The Global Catalog holds a partial copy of every object in the forest, so a query on 3268 can find a user in any domain, while a query on 389 normally sees only the server's own domain.
The same split applies: 3268 is the cleartext-or-StartTLS port and 3269 is implicit TLS. Microsoft's firewall guidance for domain controllers lists all four TCP ports (389, 636, 3268 and 3269), plus UDP 389, alongside Kerberos on port 88 and SMB on 445. It also notes that if no clients use LDAP over SSL/TLS, you do not need to open 636 and 3269. That tells you the encrypted ports are opt-in, not a baseline.
Testing what a server actually does#
You can check both behaviours with standard tools, run from a machine that can reach the directory:
openssl s_client -connect dc.example.com:636tests implicit TLS. You should see a certificate chain and a completed handshake immediately.openssl s_client -connect dc.example.com:389 -starttls ldaptests StartTLS. OpenSSL speaks just enough LDAP to request the upgrade, then shows the certificate the same way.ldapsearch -x -ZZ -H ldap://dc.example.com -b "" -s baseasks for the server's root entry over 389 and fails outright if StartTLS does not succeed.ldapsearch -x -H ldaps://dc.example.com -b "" -s basedoes the same over 636.
In the openssl output, read the certificate's subject and expiry date, and confirm the name matches the host your applications connect to. A certificate issued for a different name is a common reason LDAPS "works in testing" and then fails in an application that validates properly. If you are unsure what the TLS version line means, our comparison of TLS 1.2 and TLS 1.3 covers it.
On a domain controller, Event ID 2887 in the Directory Service log counts, once every 24 hours, the binds that would be rejected if signing were required. Watching it for a while before you tighten anything tells you which applications still bind in cleartext.
What an open 389 or 636 tells you#
From the outside, 389 and 636 open together, especially next to 88 and 445, is a strong hint that the machine is an Active Directory domain controller. That is information you would rather not publish. Directory ports belong on internal networks or behind a VPN, and an internet-facing 389 is worth fixing even if every client uses StartTLS, because of the UDP reflection risk and the reconnaissance value of an anonymous query.
Our port lookup has researched pages for the ports you are most likely to meet, including 389 and 636, each with its IANA registration, security notes and related ports. For the wider picture of which numbers matter, the common ports cheat sheet puts LDAP next to the other services you are likely to meet.
The takeaway is simple. Do not judge a directory connection by its port number. Judge it by whether encryption is required before the password is sent. On 636 that is built in. On 389 it is a setting, and it is worth checking that someone turned it on.
Look up what a port is for
Researched pages for the ports you are most likely to meet: the IANA assignment, what it means when you find one open, and the ports it usually travels with.
Open the port lookup →