企業導入 Zimbra 時,很多都會把帳號認證交給 AD(Active Directory),使用者只要記一組網域密碼。方便是方便,但只要有人反應「信箱登不進去」,問題可能出在 Zimbra、出在網路,也可能出在 AD 本身,沒有把記錄查清楚,就只能靠猜。
這篇把我平常處理這類問題時會看的記錄整理起來,從 Zimbra 端一路查到 AD/DC 端,最後附上我實際使用的問題排除順序。除了查登入問題,要稽核「誰在什麼時候登入過」也可以使用。
認證流程與記錄位置
先講一下流程:使用者在 Webmail、IMAP、ActiveSync 等任何一個入口輸入帳密,Zimbra 會依網域的設定(zimbraAuthMech 設為 ad 或 ldap),用 LDAP Bind 把帳密送到 DC 驗證,再把結果回給使用者。
所以一次登入會在兩邊各留下記錄:
- Zimbra 端
登入嘗試、協定、來源 IP、成功或失敗,以及 Bind 的細節 - DC 端
Security 事件記錄裡的驗證結果,帳號是不是被鎖、被停用都在這裡
查問題前,可以先確認網域的外部認證設定,後面比對記錄時會用到:
su - zimbra
zmprov gd example.com zimbraAuthMech zimbraAuthLdapURL zimbraAuthLdapSearchBase \
zimbraAuthLdapSearchFilter zimbraAuthLdapSearchBindDn zimbraAuthLdapBindDn
Zimbra 端的記錄
記錄檔一覽
| 記錄檔 | 內容 | 重要度 |
|---|---|---|
/opt/zimbra/log/audit.log | 登入稽核記錄,只記錄認證結果 | 高 |
/opt/zimbra/log/mailbox.log | 主要服務記錄,Web、SOAP、ActiveSync 的認證過程與錯誤 | 高 |
/var/log/zimbra.log | syslog,含 Postfix 的 SMTP AUTH | 中 |
/opt/zimbra/log/nginx.access.log | Proxy 的連線記錄,看使用者到底有沒有連進來 | 中 |
/opt/zimbra/log/zmmailboxd.out | mailboxd 啟動與 JVM 錯誤 | 低 |
audit.log:建議優先看
audit.log 是專門給稽核用的,只記錄認證結果,不會混雜其他服務訊息,格式也比較乾淨,查登入問題我都先看這個。
# 特定使用者最近的登入記錄
grep "user@example.com" /opt/zimbra/log/audit.log | tail -20
# 所有認證失敗
grep "cmd=Auth" /opt/zimbra/log/audit.log | grep "error="
# 統計今天各帳號的失敗次數,找出可能被暴力嘗試的帳號
grep "$(date +%Y-%m-%d)" /opt/zimbra/log/audit.log | grep "cmd=Auth" | grep "error=" | \
grep -o 'account=[^;]*' | sort | uniq -c | sort -rn | head -20
每一筆會帶帳號、協定(protocol=soap、imap…)以及來源 IP(oip=),從這裡就能判斷是不是只有某個用戶端有問題,例如 Webmail 正常、手機 ActiveSync 失敗,那多半是手機上存的舊密碼。
mailbox.log:看錯誤原因
audit.log 告訴你「失敗了」,mailbox.log 才看得到「為什麼失敗」:
# 特定使用者的認證相關訊息
grep "user@example.com" /opt/zimbra/log/mailbox.log | grep -i "auth" | tail -50
# 所有認證失敗
grep -i "authentication failed" /opt/zimbra/log/mailbox.log | tail -50
# 最近一小時的認證活動
grep "$(date +'%Y-%m-%d %H')" /opt/zimbra/log/mailbox.log | grep -i "auth"
mailbox.log 的量很大,務必先用帳號篩選再看,不然會被其他訊息淹沒。
開啟 DEBUG 看 LDAP Bind 細節
預設的記錄等級不會寫出 LDAP Bind 的過程,要看 Zimbra 實際送了什麼到 AD,可以只針對那個帳號開 DEBUG,不用重新啟動服務,也不會讓整台的記錄量暴增:
su - zimbra
# 只對這個帳號開 DEBUG
zmprov addAccountLogger user@example.com zimbra.account debug
zmprov addAccountLogger user@example.com zimbra.ldap debug
# 確認目前開了哪些
zmprov getAccountLoggers user@example.com
開好之後請使用者再登入一次,mailbox.log 就會出現像這樣的訊息:
DEBUG [qtp...] [name=...] account - LDAP search base=DC=example,DC=com
filter=(samAccountName=user) bindDN=zimbra-svc@example.com
DEBUG [qtp...] [name=...] account - LDAP bind successful for
CN=User Name,OU=Users,DC=example,DC=com
從這兩行就能確認搜尋基底、篩選條件、用哪個帳號查詢,以及最後 Bind 的是哪一筆 DN。常見的問題像是使用者被搬到其他 OU 而不在搜尋基底底下、篩選條件寫錯,在這裡一眼就看得出來。
查完記得關掉:
zmprov removeAccountLogger user@example.com zimbra.account
zmprov removeAccountLogger user@example.com zimbra.ldap
注意:DEBUG 記錄會帶出 DN、搜尋條件等內部資訊,查完務必關閉,記錄檔要分享給別人看之前也要先遮蔽。
AD/DC 端的記錄
Zimbra 把帳密送到 DC 之後,DC 自己也會記錄這次驗證。要確認 Zimbra 真的有打到 AD、AD 回了什麼,就要到 DC 上看。
Security 事件記錄
打開 事件檢視器 → Windows 記錄 → 安全性,篩選以下事件識別碼:
| 事件識別碼 | 意義 | 說明 |
|---|---|---|
| 4624 | 登入成功 | Zimbra 的 LDAP Bind 成功會出現在這裡,來源位址是 Zimbra 主機 |
| 4625 | 登入失敗 | 看 Status/Sub Status 判斷原因 |
| 4776 | 認證資料驗證 | NTLM 驗證,失敗時也有錯誤碼 |
| 4740 | 帳號被鎖定 | 密碼錯太多次 |
| 4768 / 4771 | Kerberos TGT 申請/預先驗證失敗 | 使用者在 Windows 登入時產生,可用來判斷帳號本身是否正常 |
4625 常見的錯誤碼:
| 錯誤碼 | 意義 |
|---|---|
0xC000006A | 密碼錯誤 |
0xC0000064 | 帳號不存在 |
0xC0000234 | 帳號已鎖定 |
0xC0000072 | 帳號已停用 |
0xC0000071 | 密碼已過期 |
0xC0000224 | 下次登入必須變更密碼 |
最後兩個很常見:AD 設了密碼期限,使用者在 Windows 上會被提示改密碼,但從 Webmail 登入就只會看到密碼錯誤。
注意:要看到這些事件,DC 的稽核原則要開啟「稽核登入」與「稽核認證資料驗證」。有多台 DC 時,Zimbra 連的是哪一台就要去哪一台看,或是把記錄集中到 Graylog 這類記錄平台一起查。
用 PowerShell 篩出 Zimbra 來源的驗證
事件檢視器一筆一筆點很慢,我習慣直接在 DC 上用 PowerShell,依來源 IP 篩出 Zimbra 主機的驗證記錄:
# 在 DC 上執行:列出最近一小時、來自 Zimbra 主機的登入成功與失敗
$zimbraIP = '192.168.1.20'
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = 4624, 4625
StartTime = (Get-Date).AddHours(-1)
} | ForEach-Object {
$d = @{}
([xml]$_.ToXml()).Event.EventData.Data | ForEach-Object { $d[$_.Name] = $_.'#text' }
if ($d.IpAddress -eq $zimbraIP) {
[pscustomobject]@{
Time = $_.TimeCreated
Id = $_.Id
Account = $d.TargetUserName
LogonType = $d.LogonType
Status = $d.Status
SubStatus = $d.SubStatus
}
}
} | Format-Table -AutoSize
把 192.168.1.20 換成你的 Zimbra 主機 IP。用事件的 XML 欄位比對,比直接搜尋 Message 文字準確,也不受系統語系影響。
在 Zimbra 主機上模擬 Bind
前面都是「事後看記錄」,也可以直接在 Zimbra 主機上用 ldapsearch 模擬 Zimbra 的動作,Zimbra 本身就有附:
# 用服務帳號查詢使用者,確認搜尋基底與篩選條件
/opt/zimbra/common/bin/ldapsearch -x -H ldaps://dc01.example.com:636 \
-D "zimbra-svc@example.com" -W \
-b "DC=example,DC=com" \
"(sAMAccountName=user)" sAMAccountName mail userPrincipalName
# 用使用者自己的帳密 Bind,確認密碼與帳號狀態
/opt/zimbra/common/bin/ldapwhoami -x -H ldaps://dc01.example.com:636 \
-D "user@example.com" -W
這兩個都成功,代表 Zimbra 主機到 DC 的網路、憑證、帳號都沒問題,問題就要往 Zimbra 的設定或用戶端去找。要看 TLS 協商的細節,可以加上 -d 1。
更多 ldapsearch 的用法可以參考我之前整理的〈LDAPSearch 常用 CLI 指令整理〉。
問題排除流程
使用者反應登不進去時,我會照這個順序查:
- audit.log
grep "user@example.com" /opt/zimbra/log/audit.log | tail -20
先確認是認證失敗,還是根本沒有進到 Zimbra - mailbox.log
grep "user@example.com" /opt/zimbra/log/mailbox.log | tail -50
看失敗原因:密碼錯誤、Bind 失敗、還是連不到 DC - 開 DEBUG(必要時)
zmprov addAccountLogger user@example.com zimbra.account debug
請使用者再試一次,取得完整的 Bind 過程,查完就關掉 - 模擬 Bind
ldapsearch/ldapwhoami
確認網路、憑證、服務帳號與使用者帳密都正常 - DC 事件記錄
4625 的錯誤碼、4740 帳號鎖定
確認是不是密碼真的錯、帳號被鎖定,或密碼已過期 - 連線層
nc -vz dc01.example.com 636openssl s_client -connect dc01.example.com:636 -showcerts
排除防火牆封鎖、LDAPS 憑證過期
結論
Zimbra 整合 AD 之後,帳號問題就變成「兩套系統一起看」,只看任何一邊都很容易誤判。我自己的習慣是:先看 Zimbra 的 audit.log 確認有沒有進來,再看 DC 的事件記錄確認 AD 怎麼回,大部分的問題到這一步就很清楚了。
另外,這些記錄平常最好就集中到記錄平台保存,真的要稽核或追查時,才不會遇到記錄已經被輪替掉的狀況。
參考資料
- Zimbra Wiki:Log Files
https://wiki.zimbra.com/wiki/Log_Files - Microsoft Learn:4625(F) An account failed to log on
https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/event-4625 - Microsoft Learn:4776(S, F) The computer attempted to validate the credentials for an account
https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/event-4776 - LDAPSearch 常用 CLI 指令整理
https://blog.jason.tools/2022/02/ldapsearch-cli.html - Zimbra 常用 CLI 指令整理
https://blog.jason.tools/2021/05/zimbra-cli.html



