

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 开始使用 AD Connector
<a name="ad_connector_getting_started"></a>

使用 AD Connecto Amazon Directory Service r，您可以连接到现有的企业活动目录。当连接到您的现有目录时，您的所有目录数据仍保留在域控制器上。 Amazon Directory Service 不复制您的任何目录数据。

**Topics**
+ [AD Connector 先决条件](#prereq_connector)
+ [创建 AD Connector](#create_ad_connector)
+ [与 AD Connector 一起创建的内容](create_details_ad_connector.md)

## AD Connector 先决条件
<a name="prereq_connector"></a>

要使用 AD Connector 连接到您的现有目录，您需要：

**Amazon VPC**  
对 VPC 进行如下设置：  
+ 至少两个子网。每个子网必须位于不同的可用区，但网络类型相同。

  您可以将其 IPv6 用于您的 VPC。有关更多信息，请参阅《*Amazon Virtual Private Cloud 用户指南》*[中对您的 VPC 的IPv6 支持](https://docs.amazonaws.cn/vpc/latest/userguide/vpc-migrate-ipv6.html)。
+ 必须通过虚拟专用网络 (VPN) 连接或 Amazon Direct Connect将 VPC 连接到您的现有网络。
+ VPC 必须具有默认硬件租户。
Amazon Directory Service 使用双 VPC 结构。构成您目录的 EC2 实例在您的 Amazon 账户之外运行，由管理 Amazon。其有 `ETH0` 和 `ETH1` 两个网络适配器。`ETH0` 是管理适配器，存在于您的账户之外。`ETH1` 在您的账户内创建。  
目录的 `ETH0` 网络的管理 IP 范围以编程方式选择，以确保其不会与部署目录的 VPC 发生冲突。此 IP 范围可以是以下任一对（因为目录在两个子网中运行）：  
+ 10.0.1.0/24 和 10.0.2.0/24 
+ 169.254.0.0/16
+ 192.168.1.0/24 和 192.168.2.0/24 
我们通过检查 `ETH1` CIDR 的第一个八位字节来避免冲突。如果以 10 开头，那么我们就选择一个 192.168.0.0/16 VPC，其子网为 192.168.1.0/24 和 192.168.2.0/24。如果第一个八位字节不是 10，则我们选择一个 10.0.0.0/16 VPC，其子网为 10.0.1.0/24 和 10.0.2.0/24。  
选择算法不包括您 VPC 上的路由。因此，这种情况可能会导致 IP 路由冲突。  
有关更多信息，请参阅 *Amazon VPC 用户指南* 中的以下主题：  
+ [Amazon VPC 是什么？](https://docs.amazonaws.cn/vpc/latest/userguide/VPC_Introduction.html)
+ [您 VPC 中的子网](https://docs.amazonaws.cn/vpc/latest/userguide/VPC_Subnets.html#VPCSubnet)
+ [在您的 VPC 中添加硬件虚拟专用网关](https://docs.amazonaws.cn/vpc/latest/userguide/VPC_VPN.html)
有关的更多信息 Amazon Direct Connect，请参阅《[Amazon Direct Connect 用户指南》](https://docs.amazonaws.cn/directconnect/latest/UserGuide/)。

**现有 Active Directory**  
您将需要连接到具有 Active Directory 域的现有网络。  
AD Connector 不支持[单个标签域](https://support.microsoft.com/en-us/help/2269810/microsoft-support-for-single-label-domains)。
此 Active Directory 域的功能级别必须是 `Windows Server 2003` 或更高版本。AD Connector 还支持连接到 Amazon EC2 实例上托管的域。  
与 Amazon EC2 域加入功能结合使用时，AD Connector 不支持只读域控制器（RODC）。

**服务账户**  
您必须拥有现有目录中被委派了以下权限的服务账户的凭证：  
+ 读取用户和组 – 必需
+ 将计算机加入域-仅在使用无缝域加入时才需要 WorkSpaces
+ 创建计算机对象-仅在使用无缝域加入时才需要 WorkSpaces
+ 服务账号密码应符合 Amazon 密码要求。 Amazon 密码应为：
  + 长度介于 8 到 128 个字符之间（包含边界值）。
  + 至少包含下列四种类别中三种类别的一个字符：
    + 小写字母 (a-z)
    + 大写字母 (A-Z)
    + 数字 (0-9)
    + 非字母数字字符 (\$1\$1@\$1\$1%^&\$1\$1-\$1=`\$1\$1()\$1\$1[]:;"'<>,.?/)
有关更多信息，请参阅 [向您的服务账户委派权限](#connect_delegate_privileges)。  
AD Connector 使用 Kerberos 对 Amazon 应用程序进行身份验证和授权。LDAP 仅用于用户和组对象查找（读取操作）。对于 LDAP 事务，所有都不可变，凭证也不以明文形式传递。身份验证由 Amazon 内部服务处理，该服务使用 Kerberos 票证以用户身份执行 LDAP 操作。

**用户权限**  
所有 Active Directory 用户必须有权读取自己的属性。具体而言，包括以下属性：  
+ GivenName
+ SurName
+ Mail
+ SamAccountName
+ UserPrincipalName
+ UserAccountControl
+ MemberOf
默认情况下，Active Directory 用户确实有权读取这些属性。但是，管理员可以随时修改这些权限，因此，您可能希望在首次设置 AD Connector 之前，验证用户是否具有这些读取权限。

**IP 地址**  
获取您现有目录域中两个 DNS 服务器或域控制器的 IP 地址。  
AD Connector 在连接到您的目录时将从这些服务器获取 `_ldap._tcp.<DnsDomainName>` 和 `_kerberos._tcp.<DnsDomainName>` SRV 记录，因此这些服务器必须包含这些 SRV 记录。AD Connector 尝试查找将同时提供 LDAP 和 Kerberos 服务的公用域控制器，因此这些 SRV 记录必须至少包含一个公用域控制器。有关 SRV 记录的更多信息，请访问 Microsoft 上的 [SRV 资源记录](http://technet.microsoft.com/en-us/library/cc961719.aspx)。 TechNet

**子网的端口**  
为了让 AD Connector 将目录请求重定向到您的现有 Active Directory 域控制器，您现有网络的防火墙必须 CIDRs 为 Amazon VPC 中的两个子网开放以下端口。  
+ TCP/UDP 53 - DNS
+ TCP/UDP 88 - Kerberos 身份验证
+ TCP/UDP 389 - LDAP
这些是 AD Connector 能够连接到目录之前所需的最少端口。根据您的特定配置，您可能需要打开其他端口。  
如果您想使用 AD Connector 和 Amazon WorkSpaces，则需要将域控制器的 “禁用 VLVSupport LDAP” 属性设置为 0。这是域控制器的默认设置。如果启用了 “禁用 VLVSupport LDAP” 属性，AD Connector 将无法查询目录中的用户。这样会导致 AD Connector 无法与 Amazon WorkSpaces配合使用。  
如果您现有 Active Directory 域的 DNS 服务器或域控制器服务器位于 VPC 内，则与这些服务器关联的安全组必须 CIDRs 为 VPC 中的两个子网开放上述端口。
有关其他端口要求，请参阅 Microsoft 文档中的 [AD 和 AD DS 端口要求](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/dd772723(v=ws.10))。

**Kerberos 预身份验证**  
用户账户必须启用 Kerberos 预身份验证。有关如何启用此设置的详细说明，请参阅[确保已启用 Kerberos 预身份验证](ms_ad_tutorial_setup_trust_prepare_onprem.md#tutorial_setup_trust_enable_kerberos)。有关此设置的一般信息，请转到开启的[预身份验证](http://technet.microsoft.com/en-us/library/cc961961.aspx)。Microsoft TechNet

**加密类型**  
当通过 Kerberos 对您的 Active Directory 域控制器进行身份验证时，AD Connector 支持以下加密类型：  
+ AES-256-HMAC
+ AES-128-HMAC
+ RC4-HMAC

### Amazon IAM Identity Center 先决条件
<a name="prereq_aws_sso_ad_connector"></a>

如果计划将 IAM Identity Center 与 AD Connector 结合使用，则需要确保满足以下条件：
+ 您的 AD Connector 是在您 Amazon 组织的管理账户中设置的。
+ 您的 IAM Identity Center 实例位于您在其中设置 AD Connector 的同一区域中。

有关更多信息，请参阅 Amazon IAM Identity Center 用户指南[中的 IAM 身份中心先决条件](https://docs.amazonaws.cn/singlesignon/latest/userguide/prereqs.html)。

### 多重身份验证先决条件
<a name="mfa_prereqs"></a>

为了使用您的 AD Connector 目录支持多重身份验证，您需要以下内容：
+ 现有网络中具有两个客户端终端节点的[远程身份验证拨入用户服务](https://en.wikipedia.org/wiki/RADIUS) (RADIUS) 服务器。RADIUS 客户端终端节点具有以下要求：
  + 要创建终端节点，您需要 Amazon Directory Service 服务器的 IP 地址。这些 IP 地址可以从目录详细信息的 **Directory IP Address** 字段中获取。
  + 两个 RADIUS 终端节点必须使用相同的共享密码。
+ 您的现有网络必须允许服务器通过默认 RADIUS 服务器端口 (1812) 的 Amazon Directory Service 入站流量。
+ 您的 RADIUS 服务器与您的现有目录的用户名必须相同。

有关通过 MFA 使用 AD Connector 的更多信息，请参阅 [为 AD Connector 启用多重身份验证](ad_connector_mfa.md)。

### 向您的服务账户委派权限
<a name="connect_delegate_privileges"></a>

要连接到您的现有目录，必须在现有目录中拥有被委托了某些权限的 AD Connector 服务账户的凭证。尽管 **Domain Admins** 组的成员有足够的权限连接到目录，但是作为最佳实践，您应使用仅具有连接到目录所需的最小权限的服务账户。以下过程演示如何创建名为的新组`Connectors`，委派连接到该组所需的必要权限，然后 Amazon Directory Service 向该组添加新的服务帐户。

必须在已加入到目录且已安装 **Active Directory User and Computers** MMC 管理单元的计算机上执行此过程。您还必须以域管理员身份登录。

**向您的服务账户委派权限**

1. 打开 **Active Directory User and Computers** 并在导航树中选择您的域根。

1. 在左侧窗格的列表中，右键单击 **Users**，选择 **New**，然后选择 **Group**。

1. 在 **New Object - Group** 对话框中，输入以下内容，然后单击 **OK**。  
****    
[\[See the AWS documentation website for more details\]](http://docs.amazonaws.cn/directoryservice/latest/admin-guide/ad_connector_getting_started.html)

1. 在 **Active Directory 用户和计算机**导航树中，选择确定将在其中创建计算机账户的组织单位（OU）。在菜单中，选择 **Action**，然后选择 **Delegate Control**。当权限传播到子域时，您可以选择该域的父 OU。 OUs如果您的 AD Connector 已连接到 Amazon 托管 Microsoft AD，则您将无法访问域根级别的委托控制。在这种情况下，要委托控制权，请在您的目录 OU 下选择将在其中创建计算机对象的 OU。

1. 在 **Delegation of Control Wizard** 页面上，单击 **Next**，然后单击 **Add**。

1. 在 **Select Users, Computers, or Groups** 对话框中，输入 `Connectors`，然后单击 **OK**。如果找到多个对象，请选择上面创建的 `Connectors` 组。单击**下一步**。

1. 在 **Tasks to Delegate** 页面上，选择 **Create a custom task to delegate**，然后选择 **Next**。

1. 选择 **Only the following objects in the folder**，然后选择 **Computer objects** 和 **User objects**。

1. 选择 **Create selected objects in this folder**，然后选择 **Delete selected objects in this folder**。然后选择**下一步**。  
![\[委派控制向导：仅选择文件夹中的以下对象、用户对象、在此文件夹中创建选定对象以及删除此文件夹中的选定对象选项。\]](http://docs.amazonaws.cn/directoryservice/latest/admin-guide/images/aduc_delegate_join_linux.png)

1. 选择 **Read**，然后选择 **Next**。
**注意**  
如果您要使用无缝域加入或 WorkSpaces，则还必须启用**写入**权限，这样 Active Directory 才能创建计算机对象。  
![\[委派控制向导：在“显示这些权限”下，选择“常规”、“特定于属性”和“读取”。\]](http://docs.amazonaws.cn/directoryservice/latest/admin-guide/images/aduc_delegate_join_permissions.png)

1. 在 **Completing the Delegation of Control Wizard** 页面上验证信息，然后单击 **Finish**。

1. 使用强密码创建一个用户账户，并将该用户添加到 `Connectors` 组。此用户将被称为您的 AD Connector 服务帐户，由于它现在是该`Connectors`组的成员，因此现在它具有足够的权限 Amazon Directory Service 来连接到该目录。

### 测试 AD Connector
<a name="connect_verification"></a>

为了让 AD Connector 连接到您的现有目录，您现有网络的防火墙必须为 VPC 中的两个子网开放某些端口。 CIDRs 要测试是否满足这些条件，请执行以下步骤：

**测试 连接**

1. 在 VPC 中启动一个 Windows 实例并通过 RDP 连接它。实例必须是您现有域的成员。在该 VPC 实例上执行剩余步骤。

1. 下载并解压缩[DirectoryServicePortTest](samples/DirectoryServicePortTest.zip)测试应用程序。其中包含源代码及 Visual Studio 项目文件，您可以根据需要修改该测试应用程序。
**注意**  
Windows Server 2003 及更低版本的操作系统不支持此脚本。

1. 在 Windows 命令提示符下，使用以下选项运行 **DirectoryServicePortTest** 测试应用程序：
**注意**  
只有将域和林功能级别设置为 Windows Server 2012 R2 及更低版本时，才能使用 DirectoryServicePortTest 测试应用程序。

   ```
   DirectoryServicePortTest.exe -d <domain_name> -ip <server_IP_address> -tcp "53,88,389" -udp "53,88,389"
   ```  
*<domain\$1name>*  
完全限定域名。这可用于测试林和域功能级别。如果不指定域名，则不测试功能级别。  
*<server\$1IP\$1address>*  
现有域中域控制器的 IP 地址。将针对该 IP 地址来测试端口。如果不指定 IP 地址，则不测试端口。

   此测试应用程序确定是否打开了从 VPC 到域的必要端口，并验证最低的林和域功能级别。

   该输出值将类似于以下内容：

   ```
   Testing forest functional level.
   Forest Functional Level = Windows2008R2Forest : PASSED
   
   Testing domain functional level.
   Domain Functional Level = Windows2008R2Domain : PASSED
   
   Testing required TCP ports to <server_IP_address>:
   Checking TCP port 53: PASSED
   Checking TCP port 88: PASSED
   Checking TCP port 389: PASSED
   
   Testing required UDP ports to <server_IP_address>:
   Checking UDP port 53: PASSED
   Checking UDP port 88: PASSED
   Checking UDP port 389: PASSED
   ```

以下是 **DirectoryServicePortTest** 应用程序的源代码。

```
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.DirectoryServices.ActiveDirectory;
using System.Threading;
using System.DirectoryServices.AccountManagement;
using System.DirectoryServices;
using System.Security.Authentication;
using System.Security.AccessControl;
using System.Security.Principal;

namespace DirectoryServicePortTest
{
    class Program
    {
        private static List<int> _tcpPorts;
        private static List<int> _udpPorts;

        private static string _domain = "";
        private static IPAddress _ipAddr = null;

        static void Main(string[] args)
        {
            if (ParseArgs(args))
            {
                try
                {
                    if (_domain.Length > 0)
                    {
                        try
                        {
                            TestForestFunctionalLevel();

                            TestDomainFunctionalLevel();
                        }
                        catch (ActiveDirectoryObjectNotFoundException)
                        {
                            Console.WriteLine("The domain {0} could not be found.\n", _domain);
                        }
                    }

                    if (null != _ipAddr)
                    {
                        if (_tcpPorts.Count > 0)
                        {
                            TestTcpPorts(_tcpPorts);
                        }

                        if (_udpPorts.Count > 0)
                        {
                            TestUdpPorts(_udpPorts);
                        }
                    }
                }
                catch (AuthenticationException ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
            else
            {
                PrintUsage();
            }

            Console.Write("Press <enter> to continue.");
            Console.ReadLine();
        }

        static void PrintUsage()
        {
            string currentApp = Path.GetFileName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            Console.WriteLine("Usage: {0} \n-d <domain> \n-ip \"<server IP address>\" \n[-tcp \"<tcp_port1>,<tcp_port2>,etc\"] \n[-udp \"<udp_port1>,<udp_port2>,etc\"]", currentApp);
        }

        static bool ParseArgs(string[] args)
        {
            bool fReturn = false;
            string ipAddress = "";

            try
            {
                _tcpPorts = new List<int>();
                _udpPorts = new List<int>();

                for (int i = 0; i < args.Length; i++)
                {
                    string arg = args[i];

                    if ("-tcp" == arg | "/tcp" == arg)
                    {
                        i++;
                        string portList = args[i];
                        _tcpPorts = ParsePortList(portList);
                    }

                    if ("-udp" == arg | "/udp" == arg)
                    {
                        i++;
                        string portList = args[i];
                        _udpPorts = ParsePortList(portList);
                    }

                    if ("-d" == arg | "/d" == arg)
                    {
                        i++;
                        _domain = args[i];
                    }

                    if ("-ip" == arg | "/ip" == arg)
                    {
                        i++;
                        ipAddress = args[i];
                    }
                }
            }
            catch (ArgumentOutOfRangeException)
            {
                return false;
            }

            if (_domain.Length > 0 || ipAddress.Length > 0)
            {
                fReturn = true;
            }

            if (ipAddress.Length > 0)
            { 
                _ipAddr = IPAddress.Parse(ipAddress); 
            }
            
            return fReturn;
        }

        static List<int> ParsePortList(string portList)
        {
            List<int> ports = new List<int>();

            char[] separators = {',', ';', ':'};

            string[] portStrings = portList.Split(separators);
            foreach (string portString in portStrings)
            {
                try
                {
                    ports.Add(Convert.ToInt32(portString));
                }
                catch (FormatException)
                {
                }
            }

            return ports;
        }

        static void TestForestFunctionalLevel()
        {
            Console.WriteLine("Testing forest functional level.");

            DirectoryContext dirContext = new DirectoryContext(DirectoryContextType.Forest, _domain, null, null);
            Forest forestContext = Forest.GetForest(dirContext);

            Console.Write("Forest Functional Level = {0} : ", forestContext.ForestMode);

            if (forestContext.ForestMode >= ForestMode.Windows2003Forest)
            {
                Console.WriteLine("PASSED");
            }
            else
            {
                Console.WriteLine("FAILED");
            }

            Console.WriteLine();
        }

        static void TestDomainFunctionalLevel()
        {
            Console.WriteLine("Testing domain functional level.");

            DirectoryContext dirContext = new DirectoryContext(DirectoryContextType.Domain, _domain, null, null);
            Domain domainObject = Domain.GetDomain(dirContext);

            Console.Write("Domain Functional Level = {0} : ", domainObject.DomainMode);

            if (domainObject.DomainMode >= DomainMode.Windows2003Domain)
            {
                Console.WriteLine("PASSED");
            }
            else
            {
                Console.WriteLine("FAILED");
            }

            Console.WriteLine();
        }

        static List<int> TestTcpPorts(List<int> portList)
        {
            Console.WriteLine("Testing TCP ports to {0}:", _ipAddr.ToString());

            List<int> failedPorts = new List<int>();

            foreach (int port in portList)
            {
                Console.Write("Checking TCP port {0}: ", port);

                TcpClient tcpClient = new TcpClient();

                try
                {
                    tcpClient.Connect(_ipAddr, port);

                    tcpClient.Close();
                    Console.WriteLine("PASSED");
                }
                catch (SocketException)
                {
                    failedPorts.Add(port);
                    Console.WriteLine("FAILED");
                }
            }

            Console.WriteLine();

            return failedPorts;
        }

        static List<int> TestUdpPorts(List<int> portList)
        {
            Console.WriteLine("Testing UDP ports to {0}:", _ipAddr.ToString());

            List<int> failedPorts = new List<int>();

            foreach (int port in portList)
            {
                Console.Write("Checking UDP port {0}: ", port);

                UdpClient udpClient = new UdpClient();

                try
                {
                    udpClient.Connect(_ipAddr, port);
                    udpClient.Close();
                    Console.WriteLine("PASSED");
                }
                catch (SocketException)
                {
                    failedPorts.Add(port);
                    Console.WriteLine("FAILED");
                }
            }

            Console.WriteLine();

            return failedPorts;
        }
    }
}
```

## 创建 AD Connector
<a name="create_ad_connector"></a>

要使用 AD Connector 连接到现有目录，请执行以下步骤。在开始此过程之前，请确保您已满足了[AD Connector 先决条件](#prereq_connector)中确定的先决条件。

**注意**  
您无法使用 Cloud Formation 模板创建 AD Connector。

**使用 AD Connector 连接**

1. 在 [Amazon Directory Service 控制台](https://console.amazonaws.cn/directoryservicev2/)导航窗格中，选择**目录**，然后选择**设置目录**。

1. 在**选择目录类型**页面上，选择 **AD Connector**，然后选择**下一步**。

1. 在 **Enter AD Connector information (输入 AD Connector 信息)** 页面上，提供以下信息：  
**目录大小**  
从**小型**或**大型**大小选项中进行选择。有关大小的更多信息，请参阅[AD Connector](directory_ad_connector.md)。  
**目录描述**  
目录的可选描述。

1. 在 **Choose VPC and subnets (选择 VPC 和子网)** 页面上，提供以下信息，然后选择 **Next (下一步)**。  
**VPC**  
目录的 VPC。  
**子网**  
为域控制器选择子网。两个子网必须位于不同的可用区。

1. 在 **Connect to AD (连接到 AD)** 页面上，提供以下信息：  
**目录 DNS 名称**  
现有目录的完全限定名称，例如 `corp.example.com`。  
**目录 NetBIOS 名称**  
现有目录的短名称，例如 `CORP`。  
**DNS IP 地址**  
现有目录中至少一个 DNS 服务器的 IP 地址。这些服务器必须可从步骤 4 中指定的每个子网访问。只要指定的子网和 DNS 服务器 IP 地址之间存在网络连接，这些服务器就可以位于外部。 Amazon  
**服务账户用户名**  
现有目录中用户的用户名称。有关该账户的更多信息，请参阅[AD Connector 先决条件](#prereq_connector)。  
**服务账户密码**  
现有用户账户的密码。此密码区分大小写，且长度必须介于 8 到 128 个字符之间。至少，它还必须包含下列四种类别中三种类别的一个字符：  
   + 小写字母 (a-z)
   + 大写字母 (A-Z)
   + 数字 (0-9)
   + 非字母数字字符 (\$1\$1@\$1\$1%^&\$1\$1-\$1=`\$1\$1()\$1\$1[]:;"'<>,.?/)  
**确认密码**  
重新键入现有用户账户的密码。

1. 在 **Review & create (检查并创建)** 页面上，检查目录信息并进行任何必要的更改。如果信息正确，请选择 **Create directory (创建目录)**。目录创建需要几分钟时间。创建后，**Status** 值将更改为 **Active**。

有关随 AD Connector 创建的内容的更多信息，请参阅[与 AD Connector 一起创建的内容](create_details_ad_connector.md)。