嘗試使用 JNDI 和 GSSAPI 執行 LDAP 搜尋時出現 javax.naming.CommunicationException:連接重置和 AD“事件 ID 1216”
我正在嘗試分析 Ldap 搜尋期間異常/失敗的原因。我在 Active Directory 域控制器上使用 JNDI 執行操作。
這是我正在嘗試做的事情的背景:
- 使用 SASL(
Kerberos authentication
) 使用 JAAS(KRB5LoginModule
) 生成一個LoginContext
.- 登錄成功後,
LoginContext
實例具有經過身份驗證的主題,其中TGT
填充了 kerberos 票證 ()PrivateCredentials
- 之後,我使用 GSSAPI 使用上面的 authenticated 生成 LdapContext
Subject
。LdapContext
生成後,我用它來執行 JNDI 操作(主要使用分頁搜尋)
- 到現在一切都很好,並且 LdapContext 已正確生成
- Active Directory 域控制器設置的一些詳細資訊:
- TGT 的生命週期設置為
1 hour
- 服務票證( )的生命週期
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
更多時間的要求,那麼唯一的出路是增加相應票的有效性。