如何动态获取特定Active Directory域的所有服务器主机名?
获取Active Directory域控制器列表的实现方案
核心原理:DNS SRV记录查询
Active Directory确实通过DNS的SRV记录发布域控制器信息,这是标准机制。针对目标域SOME.AD.DOMAIN,需查询两类关键SRV记录:
_ldap._tcp.dc._msdcs.SOME.AD.DOMAIN:所有域控制器的LDAP服务记录_ldap._tcp.pdc._msdcs.SOME.AD.DOMAIN:主域控制器(PDC)的专属记录
类UNIX系统下的实现步骤
1. 编程获取DC列表
在类UNIX环境中,有两种主流方式获取DC列表:
- 调用系统DNS解析API(如
res_query、dns_query)直接查询SRV记录 - 调用系统命令(
dig或nslookup)并解析输出:# 查询所有DC的LDAP SRV记录 dig _ldap._tcp.dc._msdcs.SOME.AD.DOMAIN SRV +short # 查询PDC的LDAP SRV记录 dig _ldap._tcp.pdc._msdcs.SOME.AD.DOMAIN SRV +short
SRV记录会返回优先级、权重、端口和主机名:优先级值越低的服务器越优先,同优先级按权重分配流量。
2. 排序DC列表
按照SRV规则排序:
- 优先放置PDC(单独查询PDC记录,放在列表最前端)
- 其他DC按SRV记录的优先级升序排列,同优先级按权重降序排列(权重高的优先)
3. 连接与验证流程
结合你的伪代码逻辑,给出Python示例实现:
import dns.resolver import ldap3 def get_ad_dcs(domain): dcs = [] # 查询PDC并加入列表 try: answers = dns.resolver.resolve(f'_ldap._tcp.pdc._msdcs.{domain}', 'SRV') for rdata in answers: dcs.append((0, str(rdata.target).rstrip('.'))) except dns.resolver.NXDOMAIN: pass # 查询所有DC并去重 try: answers = dns.resolver.resolve(f'_ldap._tcp.dc._msdcs.{domain}', 'SRV') existing_dcs = [dc[1] for dc in dcs] for rdata in answers: dc_host = str(rdata.target).rstrip('.') if dc_host not in existing_dcs: dcs.append((rdata.priority, dc_host)) except dns.resolver.NXDOMAIN: return [] # 按优先级排序 dcs.sort(key=lambda x: x[0]) return [dc[1] for dc in dcs] connection_successful = False domain = "SOME.AD.DOMAIN" dc_list = get_ad_dcs(domain) for hostname in dc_list: try: server = ldap3.Server(hostname, get_info=ldap3.ALL) conn = ldap3.Connection(server, user='USERNAME', password='PASSWORD', auto_bind=True) connection_successful = True print(f"成功连接到域控制器: {hostname}") # 执行身份验证、授权等业务逻辑 break except ldap3.core.exceptions.LDAPException: print(f"连接域控制器 {hostname} 失败") if not connection_successful: print("无法连接到任何可用的域控制器")
注意事项
- 确保主机DNS配置能正确解析AD域的SRV记录(主机需在AD域网络内,或DNS服务器可访问AD的DNS区域)
- 添加DNS查询失败、连接超时的异常处理,避免程序崩溃
- 可根据实际需求调整排序规则(如结合网络延迟检测优化优先级)
内容的提问来源于stack exchange,提问作者yha
相关产品推荐
相关产品推荐

