證實(shí)戰(zhàn):Google Authenticator配置全解)
給 Rocky 9.6 服務(wù)器加裝 Google Authenticator 做雙因子認(rèn)證是我最近處理過的一件高頻需求。服務(wù)器剛交付使用時(shí)被公網(wǎng)掃描和弱口令爆破騷擾是家常便飯單純靠密碼甚至密鑰都免不了擔(dān)心。把 TOTP 動(dòng)態(tài)驗(yàn)證碼接入 SSH 登錄流程等于給安全加了第二道閘門。這篇文章我直接按生產(chǎn)環(huán)境實(shí)操從頭講EPEL 源安裝、google-authenticator 客戶端與 PAM 模塊、sshd 配置的關(guān)鍵參數(shù)再到手機(jī)端綁定驗(yàn)證碼、常見坑的排查辦法。適合手里管著 Rocky/RHEL 系服務(wù)器、想給登錄增加一道保險(xiǎn)的運(yùn)維和開發(fā)同學(xué)參考。1. 為什么要在 SSH 登錄上加第二道鎖1.1 密碼認(rèn)證的天然短板很多人在剛接觸服務(wù)器的時(shí)候第一反應(yīng)就是設(shè)個(gè)復(fù)雜的密碼。復(fù)雜密碼確實(shí)能擋住一部分腳本但擋不住有針對性的爆破。公網(wǎng)上的服務(wù)器每天被掃描端口、嘗試弱口令幾乎是地方產(chǎn)業(yè)尤其 22 端口一天下來 /var/log/secure 里能堆上百條 Failed password 記錄。我也見過不少把密碼設(shè)成大小寫加數(shù)字加符號還帶特殊字符的照樣被撞庫撞出來的案例。原因很簡單很多人喜歡在多個(gè)環(huán)境復(fù)用同一套密碼只要其中一個(gè)平臺(tái)的密碼泄露攻擊者拿過來就是數(shù)據(jù)庫式的輪番嘗試。密鑰認(rèn)證比密碼安全不少幾百位的非對稱密鑰理論上無法暴力枚舉。但密鑰文件本身存在丟失和泄露的風(fēng)險(xiǎn)如果你把私鑰放在筆記本里筆記本丟了或者被同事拷走了那對方就直接拿到了你服務(wù)器的入場券。就算給私鑰加了 passphrase這依然屬于你知道的東西這一因子本質(zhì)還是單因子認(rèn)證只是把攻擊面從服務(wù)器轉(zhuǎn)移到了你的客戶端和私鑰文件上。我個(gè)人的判斷標(biāo)準(zhǔn)很簡單只要服務(wù)器暴露在公網(wǎng)或者多人共用賬號管理就必須把其中一層認(rèn)證做成只有用戶手里才有的東西。雙因子認(rèn)證就是這類方案它的意義不是替代密碼而是即便密碼泄露攻擊者少了第二個(gè)因子照樣進(jìn)不來。1.2 TOTP 動(dòng)態(tài)驗(yàn)證碼是怎么工作的TOTP 的全稱是 Time-based One-Time Password即基于時(shí)間的一次性密碼標(biāo)準(zhǔn)定義在 RFC 6238 里。核心思路是客戶端和服務(wù)器端共享一個(gè)秘密種子secret把這個(gè)種子和當(dāng)前時(shí)間戳切成的時(shí)間窗口一起做 HMAC-SHA1 運(yùn)算再從結(jié)果里截出一段數(shù)字作為驗(yàn)證碼。因?yàn)殡p方用的是同一個(gè)秘密、同一個(gè)算法、同一個(gè)時(shí)間窗口所以在同一時(shí)刻算出來的驗(yàn)證碼是一致的。具體來說服務(wù)端和手機(jī) App 的時(shí)間被切成 30 秒一格每一格對應(yīng)一個(gè)新的 6 位數(shù)字。服務(wù)器收到驗(yàn)證碼后會(huì)用當(dāng)前時(shí)間窗口重算一遍再和你輸入的驗(yàn)證碼比對。匹配就通過超過時(shí)間窗口自動(dòng)作廢。這也是為什么驗(yàn)證碼每 30 秒變一次——不是 App 在隨機(jī)亂跳而是算法在按時(shí)間片推進(jìn)。用生活化的方式理解這就好比保險(xiǎn)柜的密碼鎖每 30 秒自動(dòng)換一組密碼而你和銀行約定好同一本密碼手冊和同一個(gè)對表時(shí)鐘只有你手里那本手冊才能算出當(dāng)前時(shí)刻該輸哪個(gè)密碼。攻擊者就算偷看你輸了一次下一分鐘這個(gè)密碼就過期了偷看毫無意義。這個(gè)機(jī)制天然抗重放攻擊。就算有人在網(wǎng)絡(luò)上抓到了你輸入的驗(yàn)證碼他也沒法在當(dāng)前時(shí)間片之外復(fù)用它而且常見的配置里每個(gè)時(shí)間片內(nèi)的驗(yàn)證碼都會(huì)被限制使用次數(shù)。把 TOTP 接到 SSH 登錄上等于讓每一次登錄都變成一次動(dòng)態(tài)挑戰(zhàn)而不是一個(gè)固定不變的憑證。1.3 為什么選 Google Authenticator而不是其他方案TOTP 是開放標(biāo)準(zhǔn)Google Authenticator 只是其中一種實(shí)現(xiàn)。選它做服務(wù)端的 PAM 模塊原因很現(xiàn)實(shí)一是 google-authenticator 這個(gè)包在社區(qū)里維護(hù)得久RHEL/Rocky 生態(tài)的 EPEL 倉庫直接提供裝上就能用二是它的 pam_google_authenticator.so 模塊和 sshd 的鍵盤交互式認(rèn)證配合得非常順滑不需要額外開端口、跑服務(wù)三是客戶端生態(tài)足夠通用你手機(jī)里隨便一個(gè)支持 RFC 6238 的 AppAuthy、FreeOTP、Microsoft Authenticator甚至密碼管理器內(nèi)置的 TOTP 功能都能掃碼綁定不一定非要裝谷歌家的 App。有些團(tuán)隊(duì)會(huì)考慮硬令牌或者類似 pam_duo 的在線驗(yàn)證服務(wù)它們各有優(yōu)勢但都需要額外的接入成本和外部依賴。對于大多數(shù)單機(jī)或中小規(guī)模集群google-authenticator 加 PAM 是最輕量、最容易維護(hù)的方案。這里我并不是說其他方案不好而是從改造成本最低、后續(xù)最省心的角度它確實(shí)是上手最快的選擇。2. 環(huán)境準(zhǔn)備與安裝EPEL 這一步別漏2.1 先確認(rèn)系統(tǒng)和基礎(chǔ)環(huán)境動(dòng)手之前先把底摸清楚。Rocky 9.6 是基于 RHEL 9 分支的企業(yè)級發(fā)行版默認(rèn)裝的 OpenSSH 版本在 8.7p1 左右PAM 版本也比較新這些都會(huì)影響后面的參數(shù)選擇。用一條命令確認(rèn)系統(tǒng)版本cat /etc/rocky-release接下來檢查 sshd 是否正常運(yùn)行、當(dāng)前能否用現(xiàn)有方式登錄以及時(shí)間同步服務(wù)是否開啟systemctl status sshd systemctl status chronyd timedatectlTOTP 對時(shí)間同步極度敏感客戶端和服務(wù)器的時(shí)間差一旦超過允許窗口驗(yàn)證碼就會(huì)一直顯示錯(cuò)誤。所以開機(jī)自帶的 chronyd 必須保持在運(yùn)行狀態(tài)。如果服務(wù)器沒連外網(wǎng)或者防火墻擋掉了 NTP 端口后面驗(yàn)證碼會(huì)是一道很難排查的暗坑這塊我在第五章會(huì)專門說。還要順手確認(rèn) SELinux 狀態(tài)。Rocky 默認(rèn)是 Enforcing正常配置下它不會(huì)攔 google-authenticator但如果你后面要手工挪文件、改目錄就得注意安全上下文的問題不然又會(huì)出現(xiàn)一個(gè)配置明明對了卻登錄不了的詭異現(xiàn)象。2.2 安裝 EPEL 和 google-authenticatorgoogle-authenticator 并不在 Rocky 的 BaseOS 或 AppStream 倉庫里它在 EPELExtra Packages for Enterprise Linux擴(kuò)展倉庫中。EPEL 是 Fedora 社區(qū)維護(hù)的擴(kuò)展包倉庫對企業(yè)級發(fā)行版幾乎是標(biāo)配。安裝順序應(yīng)該是先裝 epel-release再裝 google-authenticatordnf install -y epel-release dnf install -y google-authenticator如果你之前已經(jīng)裝過 epel-release直接跳過第一步。安裝完成后用 rpm 驗(yàn)證包里的內(nèi)容rpm -ql google-authenticator正常你會(huì)看到 /usr/bin/google-authenticator 這個(gè)命令行工具以及 /usr/lib64/security/pam_google_authenticator.so 這個(gè) PAM 模塊。前者用來給用戶生成秘密種子和二維碼后者在 SSH 認(rèn)證階段被 PAM 調(diào)用負(fù)責(zé)校驗(yàn)驗(yàn)證碼。2.3 安裝后的依賴自檢PAM 模塊本質(zhì)上是動(dòng)態(tài)庫依賴系統(tǒng)的 libpam 等基礎(chǔ)庫。如果哪天發(fā)現(xiàn)模塊加載不了可以用 ldd 查一下依賴是否完整ldd /usr/lib64/security/pam_google_authenticator.so這一步排查在正常安裝下很少出問題但當(dāng)你從別的機(jī)器拷貝文件過來或者系統(tǒng)基礎(chǔ)庫被更新到不兼容版本時(shí)ldd 會(huì)立刻暴露問題。另外建議隨便切到一個(gè)普通用戶目錄下執(zhí)行/usr/bin/google-authenticator -h確認(rèn)命令能跑起來再把下面的步驟繼續(xù)往下做。有一點(diǎn)要提前說清楚這個(gè)包裝好后并不會(huì)自動(dòng)啟用它只是把工具和模塊擺到位了。真正的開關(guān)在 /etc/pam.d/sshd 和 /etc/ssh/sshd_config 里這也是新手最容易卡住的地方。3. 核心改造PAM 棧怎么和 sshd 配合3.1 PAM 配置怎么改才安全PAM 全稱 Pluggable Authentication Modules是 Linux 下的可插拔認(rèn)證框架。SSH 登錄時(shí)sshd 會(huì)調(diào)用 PAM 去做實(shí)際的賬號密碼校驗(yàn)而 PAM 會(huì)按 /etc/pam.d/sshd 文件里聲明的模塊順序一個(gè)接一個(gè)地執(zhí)行認(rèn)證。我們要做的就是把 pam_google_authenticator.so 插進(jìn)這個(gè)鏈條里。用編輯器打開 /etc/pam.d/sshd在文件的 auth 部分加一行auth required pam_google_authenticator.so關(guān)鍵點(diǎn)在于這個(gè)模塊放的位置。我通常放在最前面也就是pam_sepermit.so之前#%PAM-1.0 auth required pam_google_authenticator.so auth required pam_sepermit.so auth substack password-auth這樣做的效果是認(rèn)證時(shí)先要求輸入 Google Authenticator 驗(yàn)證碼然后再走系統(tǒng)的密碼認(rèn)證。兩個(gè)模塊都是 required意味著兩關(guān)都要過任何一關(guān)失敗都登錄失敗。這里有個(gè)容易踩的坑直接在 auth 段加 pam_google_authenticator.so 時(shí)如果用戶目錄下還沒有生成 .google_authenticator 文件模塊會(huì)直接拒絕認(rèn)證導(dǎo)致所有用戶都進(jìn)不去。所以我通常建議先在文件里加上nullok選項(xiàng)auth required pam_google_authenticator.so nulloknullok 的意思是用戶沒有密鑰文件時(shí)允許通過等所有需要 2FA 的用戶都完成初始化綁定后再把這行里的 nullok 去掉強(qiáng)制全員都必須有驗(yàn)證碼才能登錄。生產(chǎn)環(huán)境我強(qiáng)烈建議按這個(gè)順序來做別一上來就強(qiáng)制。3.2 sshd_config 里真正要改的項(xiàng)改完 PAM還要讓 sshd 使用鍵盤交互認(rèn)證把驗(yàn)證碼的輸入提示拋給用戶。這里有一個(gè)版本相關(guān)的老坑很多舊教程會(huì)叫你設(shè)ChallengeResponseAuthentication yes但 OpenSSH 8.7 開始這個(gè)選項(xiàng)已被標(biāo)記為廢棄Rocky 9 里對應(yīng)的正確寫法是KbdInteractiveAuthentication yes在 /etc/ssh/sshd_config 里確認(rèn)或添加以下幾項(xiàng)UsePAM yes KbdInteractiveAuthentication yesUsePAM 默認(rèn)就是 yes但如果之前有人手賤改過一定要改回來否則 PAM 那套 Google Authenticator 校驗(yàn)根本不會(huì)執(zhí)行。PasswordAuthentication 保持 yes 也沒關(guān)系因?yàn)槊艽a已經(jīng)在 PAM 棧里被要求了這里主要是放開鍵盤交互通道。如果你只想用密碼 驗(yàn)證碼這一種組合可以再加一行強(qiáng)制認(rèn)證方式AuthenticationMethods keyboard-interactive加了這行之后sshd 只接受鍵盤交互方式登錄外部用純密碼或者純密鑰直接連會(huì)被拒絕。如果只想對特定用戶組啟用還可以用 Match 塊單獨(dú)控制Match Group sysadmin AuthenticationMethods keyboard-interactive要特別提醒的是改 sshd_config 之前先開一個(gè) second session 或者 screen/tmux防止配置寫錯(cuò)導(dǎo)致所有會(huì)話都斷掉。這個(gè)習(xí)慣我后面還會(huì)再強(qiáng)調(diào)因?yàn)樗呛芏嗳搜獪I換來的教訓(xùn)。3.3 模塊參數(shù)與文件權(quán)限的講究pam_google_authenticator.so 支持的參數(shù)不少常用的是這幾個(gè)參數(shù)作用推薦值window-size允許的時(shí)間窗口偏移量3time-step-size時(shí)間片長度秒30rate-limit限制失敗嘗試次數(shù)3no-concurrent-login禁止同一賬號并發(fā)登錄可選這些參數(shù)既可以寫在 PAM 行里覆蓋全局也可以在每個(gè)用戶各自的 .google_authenticator 文件里設(shè)置。用戶文件里寫的配置通常比全局更靈活比如某個(gè)賬號允許稍大窗口、另一個(gè)賬號啟用并發(fā)限制互不影響。再強(qiáng)調(diào)一下文件權(quán)限。google-authenticator 生成的 .google_authenticator 位于用戶家目錄里面保存著秘密種子和應(yīng)急碼權(quán)限必須收緊chmod 0400 ~/.google_authenticator如果權(quán)限過寬模塊會(huì)直接拒絕讀取并報(bào)錯(cuò)防止密鑰泄露。這一步其實(shí)是在保護(hù)你自己別小看它。4. 完整實(shí)操從手機(jī)綁定到驗(yàn)證登錄4.1 運(yùn)行初始化命令生成秘密種子配置改完之后每個(gè)要使用 2FA 的用戶需要登錄一次服務(wù)器在自己的家目錄下執(zhí)行g(shù)oogle-authenticator這是一段交互式向?qū)讉€(gè)問題我逐個(gè)說清楚。第一個(gè)問題Do you want authentication tokens to be time-based選擇 y也就是基于時(shí)間第二個(gè)問是否更新配置文件選 y 把生成結(jié)果寫進(jìn) ~/.google_authenticator第三個(gè)問是否禁止并發(fā)登錄按需選一般選 y 會(huì)更嚴(yán)格第四個(gè)問是否啟用頻率限制強(qiáng)烈建議選 y這能限制每 30 秒內(nèi)最多嘗試 3 次防止驗(yàn)證碼被暴力枚舉。向?qū)ЫY(jié)束后終端會(huì)顯示一大塊 ASCII 二維碼、一個(gè) Base32 格式的 Secret Key以及 5 個(gè)緊急備用碼。這 5 個(gè)代碼是單次使用的每個(gè) 8 位一定要復(fù)制到密碼管理器里存好最好別存在同一臺(tái)服務(wù)器上。真到了手機(jī)丟失、App 重置的時(shí)候這幾個(gè)代碼是你唯一的救命繩。4.2 手機(jī)端綁定與替代 App拿出手機(jī)打開 Google Authenticator選添加賬戶掃碼即可。如果掃碼不方便也可以手動(dòng)輸入終端里顯示的 Base32 Secret Key。這里要說明一點(diǎn)TOTP 是開放協(xié)議你未必非要用 Google Authenticator 這個(gè) App。我用過 Authy、FreeOTP、Microsoft Authenticator掃同一個(gè)碼都能綁定。有些密碼管理器也內(nèi)置 TOTP可以把驗(yàn)證碼和賬號密碼放一起這種方式有得有失看團(tuán)隊(duì)取舍。綁定成功之后App 里會(huì)顯示一個(gè) 6 位數(shù)字每 30 秒刷新一次。你可以先在本機(jī)對照終端里顯示的驗(yàn)證碼確認(rèn) App 計(jì)算的和服務(wù)器計(jì)算的一致。如果數(shù)值對不上八成是手機(jī)時(shí)間和服務(wù)器時(shí)間差太多先把手機(jī)時(shí)間同步打開再回服務(wù)器上執(zhí)行timedatectl看系統(tǒng)時(shí)間。4.3 重啟 sshd 并驗(yàn)證登錄流程服務(wù)端配置改完需要讓它生效systemctl restart sshd注意這里是 restart 不是 reload。reload 對 sshd_config 的部分改動(dòng)有效但 PAM 模塊和認(rèn)證方式的變更最好用 restart確保新配置完全加載。重啟后千萬別急著關(guān)掉當(dāng)前連接先開一個(gè)新終端測試確認(rèn)能登錄再放手。成功場景下你會(huì)看到這樣的登錄過程輸入 ssh 用戶名和 IP提示輸入驗(yàn)證碼然后提示輸入密碼。兩個(gè)都對了才能登錄進(jìn)去。在 /var/log/secure 里能看到類似 Accepted keyboard-interactive 的記錄證明走的是鍵盤交互認(rèn)證。4.4 進(jìn)階玩法密鑰 驗(yàn)證碼雙保險(xiǎn)如果你的一貫習(xí)慣是密鑰登錄也可以要求密鑰 驗(yàn)證碼組合。方法是在 sshd_config 里寫AuthenticationMethods publickey,keyboard-interactive逗號表示并且意思是客戶端必須先完成公鑰認(rèn)證再完成鍵盤交互也就是 PAM 里的驗(yàn)證碼和密碼缺一不可。這樣即使私鑰泄露別人沒有驗(yàn)證碼也進(jìn)不來。注意這個(gè)配置會(huì)完全替代默認(rèn)的認(rèn)證方式所以在改動(dòng)前務(wù)必保持當(dāng)前會(huì)話存活別有僥幸心理。這種模式下客戶端會(huì)先走密鑰校驗(yàn)通過后再彈驗(yàn)證碼提示。我在實(shí)際使用中覺得這個(gè)組合是當(dāng)前 SSH 登錄里最穩(wěn)的形態(tài)密鑰負(fù)責(zé)你擁有的憑證驗(yàn)證碼負(fù)責(zé)你手上的動(dòng)態(tài)憑證兩邊互補(bǔ)單邊失守都不至于直接淪陷。4.5 多用戶場景與備份注意事項(xiàng)如果是多用戶服務(wù)器每個(gè)用戶都必須單獨(dú)執(zhí)行一次 google-authenticator每個(gè)賬號對應(yīng)不同的秘密種子。從安全角度我不建議把同一個(gè)用戶的 .google_authenticator 文件復(fù)制給其他賬號用一旦有人泄露種子所有共用賬號全部受影響排查起來非常痛苦。對于監(jiān)控腳本、自動(dòng)化任務(wù)這類服務(wù)賬號需要提前想清楚策略。簡單粗暴的排除賬號雖然省事但會(huì)留下一個(gè) 2FA 的缺口。我見過一種做法是把服務(wù)賬號的 TOTP secret 存到內(nèi)部密碼管理系統(tǒng)里讓自動(dòng)化工具每次動(dòng)態(tài)取碼也見過在 PAM 層面用 pam_succeed_if 按用戶名跳過 2FA 的那個(gè)適合內(nèi)網(wǎng)強(qiáng)隔離環(huán)境公網(wǎng)環(huán)境不太推薦。備份方面除了前面說的應(yīng)急碼也可以把 .google_authenticator 文件內(nèi)容加密后存入公司內(nèi)部的密碼庫。這樣即使服務(wù)器重裝、用戶文件丟失也能恢復(fù)出原始秘密重新綁定手機(jī) App而不必讓用戶重新跑一遍初始化流程。5. 常見問題與排查實(shí)錄5.1 登錄提示 Permission denied 但密碼明明是對的這種場景最讓人抓狂。排查思路按順序來先看是不是 PAM 配置沒生效執(zhí)行journalctl -u sshd -f再開一個(gè)終端嘗試登錄觀察日志。如果報(bào)類似 pam_google_authenticator.so: Module is unknown 的錯(cuò)誤說明模塊文件沒被識(shí)別回到 2.2 節(jié)重裝包如果是 Could not open file /home/user/.google_authenticator說明這個(gè)用戶還沒執(zhí)行過初始化或者 nullok 沒加導(dǎo)致直接拒絕。另一個(gè)隱蔽原因是 sshd_config 里把 KbdInteractiveAuthentication 設(shè)成了 no導(dǎo)致鍵盤交互認(rèn)證根本沒被調(diào)用檢查一下那行。5.2 驗(yàn)證碼總是提示無效驗(yàn)證碼不對十有八九是時(shí)間問題。TOTP 的容差窗口默認(rèn)只有 3 個(gè)時(shí)間片也就是前后各 90 秒左右。先看服務(wù)器時(shí)間date timedatectl status再看 chrony 是否同步chronyc tracking如果顯示既沒建立連接又沒同步就需要檢查到 NTP 服務(wù)器的網(wǎng)絡(luò)連通性和防火墻規(guī)則。手機(jī)端也一樣別開省電模式導(dǎo)致 App 的時(shí)間基準(zhǔn)被凍結(jié)。另外如果驗(yàn)證碼在某個(gè)時(shí)間片剛切換時(shí)錄入建議等幾秒再輸避免邊界問題。如果時(shí)間完全同步還是不行可以嘗試在 ~/.google_authenticator 文件里手動(dòng)把窗口調(diào)大一點(diǎn)把 WINDOW_SIZE 3改成 WINDOW_SIZE 5。這只是臨時(shí)排查手段長期不要放大窗口否則暴力破解面會(huì)變大。5.3 SELinux 和文件權(quán)限導(dǎo)致的奇怪拒絕Rocky 默認(rèn) SELinux 是 Enforcing。正常情況下 google-authenticator 讀自己家目錄下的普通文件不會(huì)觸發(fā)攔截但如果你是從備份恢復(fù)、用 root 幫用戶生成了文件、或者文件從別的服務(wù)器拷貝過來就可能出現(xiàn)模塊明明裝了、配置也沒錯(cuò)但認(rèn)證還是失敗的情況。這時(shí)看 SELinux 日志ausearch -m AVC -ts recent如果確實(shí)有類型攔截用 restorecon 修復(fù)一下文件上下文restorecon -Rv /home/user/.google_authenticator同時(shí)確認(rèn)文件屬主是登錄用戶權(quán)限不要超過 0400。這里有一個(gè)小竅門實(shí)際排障時(shí)可以臨時(shí)把 SELinux 切到 Permissive 對比一下確認(rèn)問題后記得切回 Enforcing別為了省事長期關(guān)掉它。5.4 最壞情況把自己鎖在門外在不巧連 restart sshd 都沒能保住當(dāng)前會(huì)話、驗(yàn)證碼又一直不對的情況下只能走帶外通道比如物理顯示器、IPMI/iLO、云廠商的 VNC 控制臺(tái)。進(jìn)入系統(tǒng)后先停掉 sshd把 /etc/pam.d/sshd 里那行 google-authenticator 注釋掉重啟 sshd 恢復(fù)到無驗(yàn)證碼模式然后排查時(shí)間問題或者重新初始化用戶。應(yīng)急碼也是重要保底手段鎖死的情況下用其中一張一次性代碼能直接登錄登錄后再重新審視配置。我自己的習(xí)慣是每次改認(rèn)證配置前都會(huì)先寫好一條恢復(fù)路徑比如準(zhǔn)備一個(gè)還能用的控制臺(tái)會(huì)話或者確認(rèn) IPMI 可以訪問。這不是小題大做是生產(chǎn)環(huán)境的基本素養(yǎng)。下面是常見問題的速查表實(shí)際排障時(shí)可以照著過一遍?,F(xiàn)象大概率原因快速處理Permission denied 但密碼正確模塊未裝或 PAM 未生效確認(rèn) EPEL 與包檢查 PAM 行Permission denied 且日志無模塊記錄KbdInteractiveAuthentication 為 no置為 yes 并 restart sshd驗(yàn)證碼無效時(shí)間不同步chronyc tracking 手機(jī)時(shí)間修正驗(yàn)證碼無效且時(shí)間正常窗口太小或種子不一致臨時(shí)放寬窗口或重新綁定提示無法讀取配置文件權(quán)限或?qū)僦骰?SELinuxchmod 0400 restorecon說實(shí)話這套東西配置起來門檻并不高真正考驗(yàn)人的是對每個(gè)選項(xiàng)的理解。我個(gè)人的習(xí)慣是先在一臺(tái)測試機(jī)上把 PAM 和 sshd 的交互流程徹底跑通再上生產(chǎn)。google-authenticator 這種方案一旦用順手會(huì)變成你服務(wù)器安全配置里最不起眼但最可靠的一環(huán)。最后分享一個(gè)小技巧如果你有多臺(tái)服務(wù)器每臺(tái)都生成自己獨(dú)立的 secret千萬別圖省事直接復(fù)制同一個(gè) .google_authenticator 文件否則一臺(tái)失守等于整片線上全部暴露。