Active-Directory

嘗試使用 JNDI 和 GSSAPI 執行 LDAP 搜尋時出現 javax.naming.CommunicationException:連接重置和 AD“事件 ID 1216”

  • February 10, 2021

我正在嘗試分析 Ldap 搜尋期間異常/失敗的原因。我在 Active Directory 域控制器上使用 JNDI 執行操作。

這是我正在嘗試做的事情的背景:

  1. 使用 SASL( Kerberos authentication) 使用 JAAS( KRB5LoginModule) 生成一個LoginContext.
  2. 登錄成功後,LoginContext實例具有經過身份驗證的主題,其中TGT填充了 kerberos 票證 ()PrivateCredentials
  3. 之後,我使用 GSSAPI 使用上面的 authenticated 生成 LdapContext Subject
  4. LdapContext生成後,我用它來執行 JNDI 操作(主要使用分頁搜尋)

  1. 到現在一切都很好,並且 LdapContext 已正確生成
  2. Active Directory 域控制器設置的一些詳細資訊:
  3. TGT 的生命週期設置為1 hour
  4. 服務票證( )的生命週期TGS設置為 10 分鐘(由於某些限製而需要,但實際上是這樣的)

現在的場景:

  • 使用LdapContext上面創建的,它開始使用 查詢域控制器,pagingcontrol並且事情在一定時間或一定數量的搜尋中工作順利(讓我們這樣說,以便我不希望你們都誤導這可能實際上涉及時間,只需考慮這發生在(大約)定期間隔之後 - 這些間隔可能是時間或搜尋
  • 當它在一定間隔後獲取下一頁時,搜尋失敗並顯示:
  Caused by: javax.naming.CommunicationException: Connection reset
     at com.sun.jndi.ldap.LdapCtx.getSearchReply(LdapCtx.java:1920) ~[?:1.8.0_73]
     at com.sun.jndi.ldap.AbstractLdapNamingEnumeration.getNextBatch(AbstractLdapNamingEnumeration.java:130) ~[?:1.8.0_73]
     at com.sun.jndi.ldap.AbstractLdapNamingEnumeration.hasMoreImpl(AbstractLdapNamingEnumeration.java:217) ~[?:1.8.0_73]
     at com.sun.jndi.ldap.AbstractLdapNamingEnumeration.hasMore(AbstractLdapNamingEnumeration.java:189) ~[?:1.8.0_73]

     ... 10 more

  Caused by: java.net.SocketException: Connection reset
     at java.net.SocketInputStream.read(SocketInputStream.java:209) ~[?:1.8.0_73]
     at java.net.SocketInputStream.read(SocketInputStream.java:141) ~[?:1.8.0_73]
     at java.io.BufferedInputStream.fill(BufferedInputStream.java:246) ~[?:1.8.0_73]
     at java.io.BufferedInputStream.read1(BufferedInputStream.java:286) ~[?:1.8.0_73]
     at java.io.BufferedInputStream.read(BufferedInputStream.java:345) ~[?:1.8.0_73]
     at com.sun.jndi.ldap.sasl.SaslInputStream.readFully(SaslInputStream.java:166) ~[?:1.8.0_73]
     at com.sun.jndi.ldap.sasl.SaslInputStream.fill(SaslInputStream.java:123) ~[?:1.8.0_73]
     at com.sun.jndi.ldap.sasl.SaslInputStream.read(SaslInputStream.java:90) ~[?:1.8.0_73]
     at com.sun.jndi.ldap.Connection.run(Connection.java:860) ~[?:1.8.0_73]
     at java.lang.Thread.run(Thread.java:745) ~[?:1.8.0_73]

同時,我在 Active Directory 域控制器上看到以下事件日誌:EventId:2889

Log Name:      Directory Service
Source:        Microsoft-Windows-ActiveDirectory_DomainService
Event ID:      2889
Task Category: LDAP Interface
Level:         Information
Keywords:      Classic
User:          ANONYMOUS LOGON
Computer:      myad01.example.lab
Description:The following client performed a SASL (Negotiate/Kerberos/NTLM/Digest) LDAP bind without
requesting signing (integrity verification), or performed a simple bind over a clear text (non-
SSL/TLS-encrypted) LDAP connection. 

Client IP address: X.X.X.X:56260 
Identity the client attempted to authenticate as:EXAMPLE\Administrator 
Binding Type:0

我還看到了一個EventID為1216的日誌。詳細資訊如下:

Log Name:      Directory Service
Source:        Microsoft-Windows-ActiveDirectory_DomainService
Event ID:      1216
Task Category: LDAP Interface
Level:         Warning
Keywords:      Classic
User:          N/A
Computer:      myad01.example.lab
Description:Internal event: An LDAP client connection was closed because of an error. 

Client IP:X.X.X.X:56244 

Additional Data 
Error value: 1236 The network connection was aborted by the local system. 
Internal ID: c060420

我的理解:每當(在一段時間後)它去獲取下一頁時ldap connection,伺服器(如事件 id 所建議的**1216**)將其無效,因此我得到了CommunicationException. 我的問題是為什麼我會在一段時間後而不是立即得到這個?是因為 kerberos 和服務票證的有效期已經結束了嗎? 如果是這種情況,那麼我應該如何設計來克服分頁問題?因為,在收到通信異常後,如果我創建一個新的 LdapContext 並設置分頁控制項,我會按預期得到以下異常:

 javax.naming.OperationNotSupportedException: [LDAP: error code 12 - 00000057: LdapErr: DSID-0C090B0B, comment: Error processing control, data 0, v3839 ]
    at com.sun.jndi.ldap.LdapCtx.mapErrorCode(Unknown Source) ~[?:1.8.0_201]
    at com.sun.jndi.ldap.LdapCtx.processReturnCode(Unknown Source) ~[?:1.8.0_201]
    at com.sun.jndi.ldap.LdapCtx.processReturnCode(Unknown Source) ~[?:1.8.0_201]
    at com.sun.jndi.ldap.LdapCtx.searchAux(Unknown Source) ~[?:1.8.0_201]
    at com.sun.jndi.ldap.LdapCtx.c_search(Unknown Source) ~[?:1.8.0_201]
    at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search(Unknown Source) ~[?:1.8.0_201]
    at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(Unknown Source) ~[?:1.8.0_201]
    at javax.naming.directory.InitialDirContext.search(Unknown Source) ~[?:1.8.0_201]

對我來說,同時支持身份驗證的 SASL(kerberos) 和創建 LdapContext 的 GSSAPI 對我來說非常重要。此外,分頁很重要,因為數據量很大,而且我們不能對票證的有效性進行任何限制,因為我無法控制客戶的環境!

請為我提供有關如何進一步調試此問題的指示,並提出正確的方法或解決方法(對此感到抱歉,但無論如何都需要它)來解決此問題。

我的觀察可能會幫助某人分析他們的問題。首先Event ID:1216是在客戶端(在我的問題中,我提到了 JNDI,在這種情況下客戶端只是 LdapContext/DirContext)關閉其底層時在 Active Directory 上生成Socket看看這個連結

LdapContext只不過是在客戶端(例如:JNDI)和 LDAP 伺服器(例如:Active Directory 目錄服務)之間使用某些連接設置形成的連接。當網路上任意兩個實體之間存在連接時,通常由客戶端套接字和伺服器端套接字的形成來支持。在 LdapContext 的情況下,LdapContext 也有一個底層套接字。

GSSAPI用於獲取 LdapContext 的實例時,底層套接字帶有一個超時,該超時等於AD DS 上存在的服務票證生命週期設置的有效性。一旦底層套接字的有效性/超時結束,套接字就會關閉。如果,LdapContext則嘗試查詢 AD DS,則發生上述Caused by: javax.naming.CommunicationException: Connection reset異常並且通信失敗。

由於 TGT 和 TGS 的生命週期/有效性設置位於 AD DS 上,因此無法使用 GSSAPI 繞過它們。如果有需要使用LdapContext更多時間的要求,那麼唯一的出路是增加相應票的有效性。

引用自:https://serverfault.com/questions/1052514