還是跨網域 AD 帳號登入 IIS 網站之 DC 連線需求議題的延伸。

上次實驗我們得到一個結論,使用跨網域帳號登入 IIS 時,不管走 NTLM 或 Kerberos,IIS 主機都不需直接連線跨網域DC。但這僅涵蓋帳號密碼驗證,若涉及更詳細的資料,例如查詢人員所屬群組,是否就必須直接連上跨網域 DC 主機才能完成?

照例寫程式實測,程式碼如下。使用 System.DirectoryEntries.AccountManagement 命令空間的方法連繫 AD DC,查詢 someone 帳號是否存在,並查詢其所屬群組。

void TestAd() 
{
    using (var otherDomain = new PrincipalContext(ContextType.Domain, "child")) 
    {
        var user = UserPrincipal.FindByIdentity(otherDomain, "someone");
        if (user != null)
        {
            foreach (GroupPrincipal p in user.GetAuthorizationGroups())
            {
                Console.WriteLine($"Group: {p.Name}");
            }
        }
    }
}

測試機器 10.0.0.8 屬於 web 網域,直屬 DC 為 10.0.0.7,child 網域 DC 為 10.0.0.6,測試前 10.0.0.8 一律重開機,避免錯過查詢一次可 Cache 沿用的資料查詢。

測試一,未阻擋 10.0.0.8 (以下簡稱 C) 對 10.0.0.6 (以下簡稱 D) 通訊

執行成功,查到 someone 屬於 Users 與 Domain Users 群組。

使用 Wireshark 觀察兩台主機間有以下傳輸:

  1. C ➜ D 389 LDAP
  2. C ➜ D 88 Kerberos
  3. C ➜ D 389 LDAP / bindRequest GSS-SPNNEGO
  4. C ➜ D 389 LDAP / SASL GSS-API
  5. C ➜ D 389 LDAP / searchRequest
  6. C ➜ D 389 LDAP / unbindRequest

測試二,阻擋 10.0.0.8 (C) 對 10.0.0.6 (D) 88 Port

驗證失敗,錯誤訊息為 The user name or password is incorrect. 根本原因是 Kerberos Port 不通,這訊息有點誤導。

Unhandled exception. System.Runtime.InteropServices.COMException (0x8007052E): The user name or password is incorrect.
   at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
   at System.DirectoryServices.DirectoryEntry.Bind()
   at System.DirectoryServices.DirectoryEntry.get_AdsObject()
   at System.DirectoryServices.PropertyValueCollection.PopulateList()
   at System.DirectoryServices.PropertyValueCollection..ctor(DirectoryEntry entry, String propertyName)
   at System.DirectoryServices.PropertyCollection.get_Item(String propertyName)
   at System.DirectoryServices.AccountManagement.PrincipalContext.DoLDAPDirectoryInitNoContainer()
   at System.DirectoryServices.AccountManagement.PrincipalContext.DoDomainInit()
   at System.DirectoryServices.AccountManagement.PrincipalContext.Initialize()
   at System.DirectoryServices.AccountManagement.PrincipalContext.get_QueryCtx()
   at System.DirectoryServices.AccountManagement.Principal.FindByIdentityWithTypeHelper(PrincipalContext context, Type principalType, Nullable`1 identityType, String identityValue, DateTime refDate)
   at System.DirectoryServices.AccountManagement.Principal.FindByIdentityWithType(PrincipalContext context, Type principalType, String identityValue)
   at System.DirectoryServices.AccountManagement.UserPrincipal.FindByIdentity(PrincipalContext context, String identityValue)

有點值得注意,上圖 22, 23 列(淺藍色)的 Protocol 為 CLDAP (Connectionless LDAP),走的是 UDP Port,我一直以為 LDAP 都是走 TCP,但實測也會用到 UDP。

測試三,阻擋 10.0.0.8 (以下簡稱 C) 對 10.0.0.6 (以下簡稱 D) 389 TCP Port

發生錯誤,訊息為找不到 LDAP 伺服器。

Unhandled exception. System.DirectoryServices.AccountManagement.PrincipalServerDownException: The server could not be contacted.
 ---> System.DirectoryServices.Protocols.LdapException: The LDAP server is unavailable.
   at System.DirectoryServices.Protocols.LdapConnection.Connect()
   at System.DirectoryServices.Protocols.LdapConnection.SendRequestHelper(DirectoryRequest request, Int32& messageID)
   at System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request, TimeSpan requestTimeout)
   at System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request)
   at System.DirectoryServices.AccountManagement.PrincipalContext.ReadServerConfig(String serverName, ServerProperties& properties)
   --- End of inner exception stack trace ---
   at System.DirectoryServices.AccountManagement.PrincipalContext.ReadServerConfig(String serverName, ServerProperties& properties)
   at System.DirectoryServices.AccountManagement.PrincipalContext.DoServerVerifyAndPropRetrieval()
   at System.DirectoryServices.AccountManagement.PrincipalContext..ctor(ContextType contextType, String name, String container, ContextOptions options, String userName, String password)
   at System.DirectoryServices.AccountManagement.PrincipalContext..ctor(ContextType contextType, String name)

前後嘗試三次,等待近 30 秒 Timeout 失敗。

結論:使用跨網域帳號登入 IIS 時,若使用 NTLM 方式認證,IIS 可向自身網域 DC 驗證跨網域帳號。但如果 IIS 或 ASP.NET 程式需要查詢群組關係或詳細 AD 屬性,IIS 就需要直接連線跨網域帳號所屬 DC。依實驗結果,至少需開啟 389 UDP/TCP 及 88 Port,完整清單則可參考微軟文件


Comments

Be the first to post a comment

Post a comment