Jaa


如何拆分子域 DNS 记录并将子域 DNS 记录迁移到专用 DNS 区域

大家好,我叫 Pierre Ricca,是一名专注研究 Active Directory 和 PowerShell 脚本的高级现场工程师。自 2010 年 11 月开始在微软法国分部担任 PFE。我工作的一个重要部分是实施运行状况检查、风险评估并向我们在法国地区的主要客户传播相关技术知识。

简介

我们的客户曾在现场多次要求我提供有关优化 DNS 解析的建议和最佳实践。尽管每位客户的 DNS 拓扑结构各不相同,但还是可以提供一些通用建议。

您可能注意到,若在域控制器上安装 DNS 服务器,即可在 Active Directory 实例上托管 DNS 区域。在 Active Directory 中托管 DNS 区域具有若干优点:不仅可以充分利用 Active Directory 复制的优势,还能为同一 DNS 区域设置多个“主”DNS 服务器 (SOA)。

我发现在一些客户环境中,客户仅通过一个 DNS 区域托管整个林的所有 DNS 记录。客户环境由一个根域 (“contoso.com”) 和几个子域(“child1.contoso.com”、“child2.contoso.com”、“child3.contoso.com” 和 “child4.contoso.com”)构成。

下方的屏幕截图显示其在 DNS 服务器管理控制台中的外观。

 image

在本示例中,大家可以看出这里仅包含一个正向查找区域 (“contoso.com”),其中每个子域都是该区域的子命名空间。如果在运行 DCPROMO 创建新子域之前未安装“DNS 服务器”角色,通常会显示这种配置。您会发现,父 DNS 区域中也托管该 “_MSDCS” 子命名空间。

此配置有一个主要弱点:如果您在子域中安装 DNS 服务器,将无法选择托管特定于该子域的 DNS 记录,只能托管整个 “contoso.com” 区域,因而会影响 Active Directory 复制性能及 Active Directory 实例大小。

很多时候,在这种环境中,我们建议将各子域 DNS 记录拆分为单独的 DNS 域,并从根 DNS 域委派各子区域。下方的屏幕截图展示了一个“推荐”配置示例。

image

本文将展示一项拆分解决方案,说明如何将大 “contoso.com” DNS 域拆分为各子域的特定 DNS 子域。

DNS 区域拆分技术发展史

自 Windows Server 2003 起,当您开始安装新的 Active Directory 林时,DCPROMO 将会创建两个独立的 DNS 区域,也就是 “_MSDCS.yourDomain.com” 和 “yourDomain.com”。下面是一个 “dom2k3.com” 域示例:

image

此行为允许这些不同的 DNS 区域具有不同的复制范围。默认情况下,将根域的 “_MSDCS” 区域复制到“All DNS servers in the Active Directory forest”,但仅将域 DNS 域复制到“All DNS servers in the Active Directory domain”。您可以在区域属性的“General”选项卡中查看并更改这些设置:

image

image

在通过 Windows 2000 Server 创建林的情况下,DCPROMO 无法区分 “_MSDCS” 区域与根域区域,此区域直接在根域区域托管。如果要拆分 “_MSDCS” 区域并使其符合 “Windows Server 2003” 的默认行为,则必须手动拆分这些区域。这篇技术文章详细介绍了该项流程:“当从Windows 2000 升级到 Windows Server 2003 后,如何为全林性 DNS 应用程序目录分区重新配置 _MSDCS 子域”https://support.microsoft.com/kb/817470/en-us

子域 DNS 记录迁移

下面提到的技术文章 (KB 817470) 允许拆分 “_MSDCS”,方法是新建一个空的 “_MSDCS” DNS 区域,然后强制各域控制器将其 DNS 记录注册到新的 DNS 区域中。

遗憾的是,我们不能针对当前的客户场景使用相同的方法,因为我们需要将现有的全部子域记录(包括静态记录)迁移到新的专用子域区域。在我们的场景中,每个子域均已投入运行数年,并针对每个子域呈现了数千个 DNS 记录。手动重新创建这些 DNS 记录太过复杂耗时。我们的唯一解决方案是编写脚本!

下面是我们采用的方法。

请注意,本文展示的脚本均作为示例提供,微软不支持这些脚本。在应用本解决方案之前,请务必备份您的 DNS 区域,并保证能够在发生意外时进行恢复。 根据我的经验,本解决方案从开始到完成可能需要几个小时的时间。强烈建议在下班时间应用此解决方案。迁移期间无法使用 DNS 动态注册。

步骤 1:导出 DNS 区域。

首先,我们需要将当前的 DNS 区域导出到文件中。幸运的是,“DNSCMD” 命令允许将 DNS 区域导出到文件中。下面是一个使用示例:

Dnscmd /zoneexport contoso.com export.dns

此命令将在 “%SYSTEMROOT%\DNS\” 文件夹中创建一个名为 “export.dns” 的文件(例如:“C:\Windows\system32\dns\export.dns”)。

步骤 2:为每个子域创建一个特定的 DNS 文件。

现在,我们需要将平面 “export.dns” 文件拆分为特定于各子域的文件,然后需要将子域的 DNS 记录导出到对应的文件。

下面是一个 “export.dns” 内容示例:

MyComputer1234.child1 [AGE:3606209] 1200 A 172.2.3.4

MyComputer5678 [AGE:1782367] 1200 A 172.5.6.7

MyComputer90AB.child2 [AGE:2457912] 1200 A 172.9.0.1

MyComputerCDEF.child2 [AGE:1982627] 1200 A 172.10.11.12

我们应当分析 “export.dns” 根据子域筛选 DNS 记录,然后为每个子域创建一个特定的新 dns 文件。

从上面的示例中,我们应该提取 “child1.dns” 的以下信息:

MyComputer1234 [AGE:3606209] 1200 A 172.2.3.4

我们应该提取 “child2.dns” 的以下信息:

MyComputer90AB [AGE:2457912] 1200 A 172.9.0.1

MyComputerCDEF [AGE:1982627] 1200 A 172.10.11.12

注意,当提取到 “child1.dns” 时,“export.dns” 中的 “MyComputer1234.child1” 将被转换为 “MyComputer”(不含 “.child1”,child2 的记录标志完全相同)。另外注意,“export.dns” 的 “MyComputer5678” 记录直接呈现到 “contoso.com” 的根目录,不会被提取到任何子域 DNS 文件。

 

我已经创建了一个示例脚本,该脚本可以自动提取并转换这些 DNS 记录,然后将结果导出到 “child.dns” 文件。请注意,此脚本作为示例提供,微软不支持该脚本。下面是使用方法示例:

.\Extract-DNSZone.PS1 -inputFile “C:\Scripts\export.dns” -outputFile “C:\Scripts\child1.contoso.com.ns” -extractZoneName "child1"

image

您可以针对每个子域重复此操作。

步骤 3:导入子 DNS 域

现在,我们将具有针对每个子区域的特定 DNS 文件(在上一步中生成)。

image

我们需要将这些“子”文件导入 DNS 服务器。首先将这些文件复制到 “%SYSTEMROOT%\DNS\” 文件夹(例如:“C:\Windows\system32\dns\”)。

接着,打开 DNS 服务器管理控制台。右键单击“Forward Lookup Zones”,然后选择“New Zone…”。

image

单击“Next”,选择“Primary zone”,确保取消选中“Store the zone in Active Directory”(因为我们希望从文件加载该区域),然后单击“Next”。

image

输入要导入的子区域名称(例如:child1.contoso.com),然后单击“Next”。

image

选择“Use this existing file”,验证该名称是否与要导入的子 DNS 文件的名称相符,然后单击“Next”。

image

选择“Do not allow dynamic updates”(我们不希望在未完成迁移流程时允许动态更新),然后单击“Next”和“Finish”。您可以在 DNS 迁移结束后重新启用动态更新。

image

针对每个子域重复此操作。现在,您将会在 DNS 服务器管理控制台中看到您的根域和子域具有单独的区域。

image

步骤 4:将子 DNS 区域复制到林中的所有 DNS 服务器

在此步骤中,我们将对林中的所有 DNS 服务器启用子区域复制。您可以在迁移结束后,将复制范围切换为“全域性”。

从 DNS 管理控制台中,右键单击子 DNS 区域,然后打开区域属性。

单击“Type: Primary”文本旁边的 Change。选中“Store the zone in Active Directory”框,然后单击“OK”。当显示提问时,单击“Yes”以确认 Active Directory 集成。

image

接着,单击“Replication: All DNS servers in this domain”文本旁边的“Change”。选中“To all DNS servers running on domain controllers in the forest”,然后单击“OK”。

image

最后的配置如下:

image

单击“OK”,针对每个子域重复此操作。

步骤 5:还原 DNS 记录 ACL

现在,我们需要还原 DNS 记录 ACL。如果要保护动态 DNS 更新的安全,那么这个步骤显得尤其重要。当将动态 DNS 更新设置为“Secure”时,DNS 服务器将检查 DNS 记录 ACL,以便验证成员服务器是否有权修改该 DNS 记录。

遗憾的是,“DNSCMD /zoneexport” 并未导出 ACL 信息。我们需要将各 DNS 记录 ACL 从“旧”父区域复制到新子区域中对应的 DNS 记录。同样,我也为它创建了一个示例脚本。此脚本需要“PowerShell Active Directory 模块”,我们可将其安装为 Windows Server 的一项可选功能,或者也可以作为“远程服务器管理工具”的一部分安装到 Windows 客户端。请注意,此脚本作为示例提供,Microsoft 不支持该脚本。下面是使用方法示例:

.\Copy-DNSACL.ps1 -SourceZoneDN "DC=contoso.com,CN=MicrosoftDNS,DC=ForestDnsZones,DC=contoso,DC=com" -TargetZoneDN "DC=child1.contoso.com,CN=MicrosoftDNS,DC=ForestDnsZones,DC=contoso,DC=com" -TargetDNSZoneShortName "child1"

下面是脚本结果示例:

image

您需要针对每个子域重复此步骤。现在,如果转到 DNS 记录的 Security 选项卡,会发现这些成员服务器对其记录具有完全访问权限。

image

步骤 6:重新启用动态更新

如果您的环境使用动态 DNS 更新,那么需要进行重新启用。转到子 DNS 区域属性,然后在“Dynamic updates:”字段中选择“Secure only”或“Nonsecure and secure”(如果不确定,请重新使用与根 DNS 区域相同的设置)。

image

步骤 7:清除旧 DNS 记录并委派子域区域。

在清除旧 DNS 记录前,请务必确保:

- 具有“旧”根 DNS 区域备份并能对其进行还原。

- DNS 解析可以妥善处理根 DNS 记录和子 DNS 记录。

- 动态更新运行正常。

- 目前未发现任何问题。

要清除旧 DNS 记录,请打开 DNS 服务器平台,浏览“旧”根 DNS 区域。务必确保要委派新子区域!右键单击根 DNS 区域中的 “child1” 子区域,然后选择“Delete”。

image

现在,“Child1” 已经从 “contoso.com” 的“子区域”中消失,但 “child1.contoso.com” 仍然显示为自治 DNS 区域。

为了能够在托管 “contoso.com”(而非托管 “child1.contoso.com”)的 DNS 服务器上解析 “child1.contoso.com”,我们需要从 “contoso.com” 区域为 “child1” 创建一个委派。右键单击 “contoso.com” 区域,然后选择“New delegation…”。

image

单击“Next”,键入子域的名称(例如:child1),然后单击“Next”。

image

从此列表中,添加托管 “child1.contoso.com” 区域的所有服务器(该列表可能较长,具体取决于环境大小),然后依次单击“Next”和“Finish”。

image

现在,在 DNS 服务器控制台中,您将会发现 “child1” 成为 “contoso.com” 的委派。

image

针对每个子域重复此操作。最终,您的 DNS 将如下所示:

image

现在迁移就完成了!如果愿意,您可以更改子 DNS 区域的复制范围。检查是否所有 DNS 区域的 DNS 记录均保持一致。另外,如果愿意,还可以考虑为您的新子区域重新启用帐龄和清理功能。

12-6-13- 脚本已上载到 TechNet 资料库。

https://gallery.technet.microsoft.com/scriptcenter/Copy-ACL-of-DNS-records-97837128

https://gallery.technet.microsoft.com/scriptcenter/Extract-a-specific-DNS-dc633d77