Demigod
Demigod

Reputation: 116

ldap_connect() with domain name instead of dcs hostname using ldaps

I'm switching from ldap:// to ldaps://

After I've figured out how to connect using ldaps and that I can't use ldaps with the domainname instead of an hostname, I'm wondering how to solve this.

So what's working:

ldap_connect('ldaps://dc1.example.com:636');

What's not working:

ldap_connect('ldaps://example.com:636');

While dc1.example.com is the hostname of my first dc, example.com is a DNS entry which resolves to multiple IPs of my domain controllers.

What did I do next? Using openssl I've figured out that the domain controller chosen by the answer of the DNS-Server using example.com will result in an ldap connection error. is it that the chosen domain controller answers with its hostname certificate (dc1.example.com) instead of the "domain" certificate (example.com)? Can I disable that check with an ldap option on the connection? Or any other suggestions? I don't want to list all those domain controllers in the connection string, cause it will hang for several seconds, if one of them is not available. Using the domain name will "remove" the failing dc.

Upvotes: 0

Views: 1093

Answers (1)

grawity_u1686
grawity_u1686

Reputation: 16282

Can I disable that check with an ldap option on the connection? Or any other suggestions?

There's no option to disable just the hostname verification while keeping the CA checks. You can disable all certificate checking – including hostname checking, but also CA verification – by setting the option X_TLS_REQUIRE_CERT to 0, but this kind of defeats the point of using LDAPS, so please do not do that.

I don't want to list all those domain controllers in the connection string, cause it will hang for several seconds, if one of them is not available. Using the domain name will "remove" the failing dc.

With just standard AD – no, it won't. The IP address records at example.com are not generated on the fly by something like a load balancer; they're still static, registered by DCs whenever they start up, but not instantly removed whenever a DC goes down. It could take quite a while for the DNS server to garbage-collect the DNS records that aren't being refreshed (I believe the expiry is 7 days unless an admin does it first?).

So it can still happen that the first A or AAAA record you take from "example.com" belongs to a DC that's currently down and you will be waiting for a timeout anyway.

But DCs register more DNS records than just the A/AAAA records at "example.com" – they also register SRV records for the LDAP service, and SRV records point at the domain names of each DC instead of just the IP addresses alone – this is what Windows itself uses to find domain controllers, as knowing the exact hostname is required not only for TLS but also for Kerberos (GSSAPI) authentication.

$rrset = dns_get_record("_ldap._tcp.example.com", DNS_SRV);

As far as I know, Active Directory does not put anything useful in the weight parameter in SRV, so you can probably treat it like a flat list of servers:

usort($rrset, fn($a, $b) => $a["pri"] - $b["pri"]);

foreach ($rrset as $rr) {
    try {
        $conn = ldap_connect("ldaps://" . $rr["target"]);
        ldap_set_option, ldap_bind, etc.
        return $conn;
    }
}

(AD only creates SRV entries for "_ldap" but not "_ldaps", so you have to ignore the port that's included in the records as well.)

Upvotes: 0

Related Questions