Linux下PAM模組學習總結

散盡浮華發表於2018-03-29

 

在Linux中執行有些程式時,這些程式在執行前首先要對啟動它的使用者進行認證,符合一定的要求之後才允許執行,例如login, su等。在Linux中進行身份或是狀態的驗證程式是由PAM來進行的,PAM(Pluggable Authentication Modules)可動態載入驗證模組,因為可以按需要動態的對驗證的內容進行變更,所以可以大大提高驗證的靈活性。

一、PAM模組介紹

Linux-PAM(即linux可插入認證模組)是一套共享庫,使本地系統管理員可以隨意選擇程式的認證方式。換句話說,不用(重新編寫)重新編譯一個包含PAM功能的應用程式,就可以改變它使用的認證機制,這種方式下,就算升級本地認證機制,也不用修改程式。
PAM使用配置/etc/pam.d/下的檔案,來管理對程式的認證方式.應用程式 呼叫相應的配置檔案,從而呼叫本地的認證模組.模組放置在/lib/security下,以載入動態庫的形式進,像我們使用su命令時,系統會提示你輸入root使用者的密碼.這就是su命令通過呼叫PAM模組實現的。

二、PAM的配置檔案說明

PAM配置檔案有下面兩種寫法:
1)寫在/etc/pam.conf檔案中,但centos6之後的系統中,這個檔案就沒有了。
2)將PAM配置檔案放到/etc/pam.d/目錄下,其規則內容都是不包含 service 部分的,即不包含服務名稱,而/etc/pam.d 目錄下檔案的名字就是服務名稱。如: vsftpd,login等,只是少了最左邊的服務名列。如:/etc/pam.d/sshd

[root@centos6-test06 ~]# cat /etc/pam.d/sshd 
#%PAM-1.0
auth	   required	pam_sepermit.so
auth       include      password-auth
account    required     pam_nologin.so
account    include      password-auth
password   include      password-auth
# pam_selinux.so close should be the first session rule
session    required     pam_selinux.so      close
session    required     pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session    required     pam_selinux.so      open env_params
session    required     pam_namespace.so
session    optional     pam_keyinit.so      force revoke
session    include      password-auth

由上面的pam模組檔案內容看,可以將pam配置檔案分為四列

  • 第一列代表模組型別
  • 第二列代表控制標記
  • 第三列代表模組路徑
  • 第四列代表模組引數

1)第一列:PAM的模組型別
Linux-PAM有四種模組型別,分別代表四種不同的任務,它們是:
認證管理(auth)賬號管理(account)會話管理(session)密碼(password)管理,一個型別可能有多行,它們按順序依次由PAM模組呼叫。

對以上四種模組型別進一步補充說明:
auth:表示鑑別類介面模組型別用於檢查使用者和密碼,並分配許可權;
這種型別的模組為使用者驗證提供兩方面服務。讓應用程式提示使用者輸入密碼或者其他標記,確認使用者合法性;通過他的憑證許可許可權,設定組成員關係或者其他優先權。

account:表示賬戶類介面,主要負責賬戶合法性檢查,確認帳號是否過期,是否有許可權登入系統等;
這種模組執行的是基於非驗證的帳號管理。他主要用於限制/允許使用者對某個服務的訪問時間,當前有效的系統資源(最多可以多少使用者),限制使用者位置(例如:root只能通過控制檯登入)。

多數情況下auth和account會一起用來對使用者登入和使用服務的情況進行限制。這樣的限制會更加完整。比如下面是一個具體的例子:login是一個應用程式。Login要完成兩件工作——首先查詢使用者,然後為使用者提供所需的服務,例如提供一個shell程式。通常Login要求使用者輸入名稱和密碼進行驗證。當使用者名稱輸入的時候,系統自然會去比對該使用者是否是一個合法使用者,是否在存在於本地或者遠端的使用者資料庫中。如果該賬號確實存在,那麼是否過期。這些個工作是由account介面來負責。

如果使用者滿足上述登入的前提條件,那麼它是否具有可登入系統的口令,口令是否過期等。這個工作就要由auth介面來負責了,他通常會將使用者口令資訊加密並提供給本地(/etc/shadow)或者遠端的(ldap,kerberos等)口令驗證方式進行驗證。

如果使用者能夠登入成功,證明auth和account的工作已經完成。但整個驗證過程並沒有完全結束。因為還有一些其他的問題沒有得到確認。例如,使用者能夠在伺服器上同時開啟多少個視窗登入,使用者可以在登入之後使用多少終端多長時間,使用者能夠訪問哪些資源和不能訪問哪些資源等等。也就是說登入之後的後續驗證和環境定義等還需要其他的介面。這就是我們下面要提到的兩組介面:

session:會話類介面。實現從使用者登入成功到退出的會話控制;
處理為使用者提供服務之前/後需要做的些事情。包括:開啟/關閉交換資料的資訊,監視目錄等,設定使用者會話環境等。也就是說這是在系統正式進行服務提供之前的最後一道關口。

password:口令類介面。控制使用者更改密碼的全過程。也就是有些資料所說的升級使用者驗證標記。

注意:上述介面在使用的時候,每行只能指定一種介面型別,如果程式需要多種介面的話,可在多行中分別予以規定。

2)第二列:PAM的控制標記

PAM使用控制標記來處理和判斷各個模組的返回值.(在此只說明簡單的認證標記)。

規定如何處理PAM模組鑑別認證的結果,簡而言之就是鑑別認證成功或者失敗之後會發生什麼事,如何進行控制。單個應用程式可以呼叫多種底層模組,通常稱為“堆疊”。對應於某程式按照配置檔案中出現順序執行的所有模組成為“堆”,堆中的各模組的地位與出錯時的處理方式由control_flag欄的取值決定,他的四種可能的取值分別為required、Requisite、sufficient或_optional:

required:表示該行以及所涉及模組的成功是使用者通過鑑別的必要條件。換句話說,只有當對應於應用程式的所有帶 required標記的模組全部成功後,該程式才能通過鑑別。同時,如果任何帶required標記的模組出現了錯誤,PAM並不立刻將錯誤訊息返回給應用程式,而是在所有模組都呼叫完畢後才將錯誤訊息返回撥用他的程式。 反正說白了,就是必須將所有的模組都執行一次,其中任何一個模組驗證出錯,驗證都會繼續進行,並在執行完成之後才返回錯誤資訊。這樣做的目的就是不讓使用者知道自己被哪個模組拒絕,通過一種隱蔽的方式來保護系統服務。就像設定防火牆規則的時候將拒絕類的規則都設定為drop一樣,以致於使用者在訪問網路不成功的時候無法準確判斷到底是被拒絕還是目標網路不可達。

requisite:與required相仿,只有帶此標記的模組返回成功後,使用者才能通過鑑別。不同之處在於其一旦失敗就不再執行堆中後面的其他模組,並且鑑別過程到此結束,同時也會立即返回錯誤資訊。與上面的required相比,似乎要顯得更光明正大一些。

sufficient:表示該行以及所涉及模組驗證成功是使用者通過鑑別的充分條件。也就是說只要標記為sufficient的模組一旦驗證成功,那麼PAM便立即嚮應用程式返回成功結果而不必嘗試任何其他模組。即便後面的層疊模組使用了requisite或者required控制標誌也是一樣。當標記為sufficient的模組失敗時,sufficient模組會當做 optional對待。因此擁有sufficient 標誌位的配置項在執行驗證出錯的時候並不會導致整個驗證失敗,但執行驗證成功之時則大門敞開。所以該控制位的使用務必慎重。

optional:他表示即便該行所涉及的模組驗證失敗使用者仍能通過認證。在PAM體系中,帶有該標記的模組失敗後將繼續處理下一模組。也就是說即使本行指定的模組驗證失敗,也允許使用者享受應用程式提供的服務。使用該標誌,PAM框架會忽略這個模組產生的驗證錯誤,繼續順序執行下一個層疊模組。

include:表示在驗證過程中呼叫其他的PAM配置檔案。在RHEL系統中有相當多的應用通過完整呼叫/etc/pam.d/system-auth來實現認證而不需要重新逐一去寫配置項。這也就意味著在很多時候只要使用者能夠登入系統,針對絕大多數的應用程式也能同時通過認證。

另外還有一種比較複雜的格式為value = action的語法來設定控制標誌,標誌之間會以空格分開。格式如下:

value1 = action1 value2 = action2 ……

其中value可以是下列Linux PAM庫的返回值:
success、open_err、symbol_err、service_err、 system_err、buf_err、perm_denied、auth_err、cred_insufficient、authinfo_unavail、user_unknown、maxtries、new_authtok_reqd、acct_expired、 session_err、cred_unavail、cred_expired、cred_err、no_module_data、conv_err、 authtok_err、authtok_recover_err、authtok_lock_busy、authtok_disable_aging、 try_again、ignore、abort、authtok_expired、module_unknown、bad_item和default。

最後一個(default)能夠用來設定上面的返回值無法表達的行為。

actionN可以是一個非負整數或者是下面的記號之一:ignore、ok、done、bad、die和reset。如果是非負整數J,就表示需要忽略後面J個同樣型別的模組。通過這種方式,系統管理者可以更加靈活地設定層疊模組,模組的層疊路徑由單個模組的反應決定。

關於這幾個記號的詳細解釋:
ignore:如果使用層疊模組,那麼這個模組的返回值將被忽略,不會被應用程式知道。
bad:他表示這個返回碼應該被看作是模組驗證失敗的標誌。如果這個模組是層疊模組的第一個驗證失敗的模組,那麼他的狀態值就是整個層疊模組驗證的狀態值和結果。
die:終止層疊模組驗證過程,立刻返回到應用程式。
ok:告訴PAM這個模組的返回值將直接作為所有層疊模組的返回值。也就是說,如果這個模組前面的模組返回狀態是PAM_SUCCESS,那這個返回值就會覆蓋前面的返回狀態。注意:如果前面的模組的返回狀態表示模組驗證失敗,那麼不能使用這個返回值再加以覆蓋。
done:終止後續層疊模組的驗證,把控制權立刻交回應用程式。
reset:清除所有層疊模組的返回狀態,從下一個層疊模組重新開始驗證。

3)模組路徑
模組路徑.即要呼叫模組的位置. 如果是64位系統,一般儲存在/lib64/security,如: pam_unix.so,同一個模組,可以出現在不同的型別中.它在不同的型別中所執行的操作都不相同.這是由於每個模組,針對不同的模組型別,編制了不同的執行函式。

4)模組引數
模組引數,即傳遞給模組的引數.引數可以有多個,之間用空格分隔開,如:password required pam_unix.so nullok obscure min=4 max=8 md5。

三、PAM模組的工作原理和流程

以RHEL系統為例,當pam安裝之後有兩大部分:在/lib/security目錄下的各種pam模組以及/etc/pam.d和/etc/pam.d目錄下的針對各種服務和應用已經定義好的pam配置檔案。當某一個有認證需求的應用程式需要驗證的時候,一般在應用程式中就會定義負責對其認證的PAM配置檔案。以vsftpd為例,在它的配置檔案/etc/vsftpd/vsftpd.conf中就有這樣一行定義:

pam_service_name=vsftpd 

表示登入FTP伺服器的時候進行認證是根據/etc/pam.d/vsftpd檔案定義的內容進行。

那麼,當程式需要認證的時候已經找到相關的pam配置檔案,認證過程是如何進行的?下面我們將通過解讀/etc/pam.d/system-auth檔案予以說明。

首先要宣告一點的是:system-auth是一個非常重要的pam配置檔案,主要負責使用者登入系統的認證工作。而且該檔案不僅僅只是負責使用者登入系統認證,其它的程式和服務通過include介面也可以呼叫到它,從而節省了很多重新自定義配置的工作。所以應該說該檔案是系統安全的總開關和核心的pam配置檔案。

下面是/etc/pam.d/system-auth檔案的全部內容:

[root@centos6-test06 ~]# grep -v ^# /etc/pam.d/system-auth
auth        required      pam_env.so
auth        sufficient    pam_unix.so nullok try_first_pass
auth        requisite     pam_succeed_if.so uid >= 500 quiet
auth        required      pam_deny.so

account     required      pam_unix.so
account     sufficient    pam_localuser.so
account     sufficient    pam_succeed_if.so uid < 500 quiet
account     required      pam_permit.so

password    requisite     pam_cracklib.so try_first_pass retry=3 type=
password    sufficient    pam_unix.so sha512 shadow nullok try_first_pass use_authtok
password    required      pam_deny.so

session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_unix.so

第一部分表示,當使用者登入的時候,首先會通過auth類介面對使用者身份進行識別和密碼認證。所以在該過程中驗證會經過幾個帶auth的配置項。

其中的第一步是通過pam_env.so模組來定義使用者登入之後的環境變數, pam_env.so允許設定和更改使用者登入時候的環境變數,預設情況下,若沒有特別指定配置檔案,將依據/etc/security/pam_env.conf進行使用者登入之後環境變數的設定。

然後通過pam_unix.so模組來提示使用者輸入密碼,並將使用者密碼與/etc/shadow中記錄的密碼資訊進行對比,如果密碼比對結果正確則允許使用者登入,而且該配置項的使用的是“sufficient”控制位,即表示只要該配置項的驗證通過,使用者即可完全通過認證而不用再去走下面的認證項。不過在特殊情況下,使用者允許使用空密碼登入系統,例如當將某個使用者在/etc/shadow中的密碼欄位刪除之後,該使用者可以只輸入使用者名稱直接登入系統。

下面的配置項中,通過pam_succeed_if.so對使用者的登入條件做一些限制,表示允許uid大於500的使用者在通過密碼驗證的情況下登入,在Linux系統中,一般系統使用者的uid都在500之內,所以該項即表示允許使用useradd命令以及預設選項建立的普通使用者直接由本地控制檯登入系統。

最後通過pam_deny.so模組對所有不滿足上述任意條件的登入請求直接拒絕,pam_deny.so是一個特殊的模組,該模組返回值永遠為否,類似於大多數安全機制的配置準則,在所有認證規則走完之後,對不匹配任何規則的請求直接拒絕。

第二部分的三個配置項主要表示通過account賬戶類介面來識別賬戶的合法性以及登入許可權。

第一行仍然使用pam_unix.so模組來宣告使用者需要通過密碼認證。第二行承認了系統中uid小於500的系統使用者的合法性。之後對所有型別的使用者登入請求都開放控制檯。

第三部分會通過password口另類介面來確認使用者使用的密碼或者口令的合法性。第一行配置項表示需要的情況下將呼叫pam_cracklib來驗證使用者密碼複雜度。如果使用者輸入密碼不滿足複雜度要求或者密碼錯,最多將在三次這種錯誤之後直接返回密碼錯誤的提示,否則期間任何一次正確的密碼驗證都允許登入。需要指出的是,pam_cracklib.so是一個常用的控制密碼複雜度的pam模組,關於其用法舉例我們會在之後詳細介紹。之後帶pam_unix.so和pam_deny.so的兩行配置項的意思與之前類似。都表示需要通過密碼認證並對不符合上述任何配置項要求的登入請求直接予以拒絕。不過使用者如果執行的操作是單純的登入,則這部分配置是不起作用的。

第四部分主要將通過session會話類介面為使用者初始化會話連線。其中幾個比較重要的地方包括,使用pam_keyinit.so表示當使用者登入的時候為其建立相應的金鑰環,並在使用者登出的時候予以撤銷。不過該行配置的控制位使用的是optional,表示這並非必要條件。之後通過pam_limits.so限制使用者登入時的會話連線資源,相關pam_limit.so配置檔案是/etc/security/limits.conf,預設情況下對每個登入使用者都沒有限制。關於該模組的配置方法在後面也會詳細介紹。

可見,不同應用程式通過配置檔案在認證過程中呼叫不同的pam模組來定製具體的認證流程。其中我們不難看出,其實可以根據實際的需要對pam的配置檔案進行修改以滿足不同的認證需求,例如下面的例子:

#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth    required    pam_env.so
auth    required    pam_tally.so onerr=fail deny=5
auth    sufficient  pam_unix.so nullok try_first_pass
auth    requisite   pam_succeed_if.so uid >= 500 quiet
auth    required    pam_deny.so

account required    pam_unix.so
account sufficient  pam_succeed_if.so uid < 500 quiet
account required    pam_permit.so

password    requisite pam_cracklib.so try_first_pass retry=3 minlen=10 lcredit=-1 ucredit=-1 dcredit=-1 ocredit=-1 difok=6
password    requisite pam_passwdqc.so use_first_pass enforce=everyone
password    sufficient pam_unix.so md5 remember=6 shadow nullok try_first_pass use_authtok
password    required pam_deny.so

session     optional pam_keyinit.so revoke
session     required pam_limits.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required pam_unix.so

在其中就增加了對使用者密碼修改時複雜度的限制,使用者多次錯誤輸入密碼之後的鎖定限制以及使用者使用密碼歷史等限制選項。

所以我們通過對上述system-auth配置檔案的修改,模組的增加和選項的變化,從很大的程度上增加了使用者登入驗證的安全性要求。我們會在之後的文章中對該配置進行詳細說明。

另外也一定需要注意,在整個的PAM配置檔案當中,配置項以及模組呼叫的邏輯順序非常關鍵。因為PAM是按照配置項的先後順序來進行驗證。錯誤的模組呼叫順序很可能導致嚴重的安全問題甚至系統錯誤。所以對PAM配置進行修改的時候務必要考慮這一點。

四、常用的PAM模組介紹

PAM模組 結合管理型別 說明
pam_unix.so

auth

提示使用者輸入密碼,並與/etc/shadow檔案相比對.匹配返回0

account 檢查使用者的賬號資訊(包括是否過期等).帳號可用時,返回0.
password 修改使用者的密碼. 將使用者輸入的密碼,作為使用者的新密碼更新shadow檔案
pam_shells.so

auth

account 

如果使用者想登入系統,那麼它的shell必須是在/etc/shells檔案中之一的shell
pam_deny.so

account

auth

password

session

該模組可用於拒絕訪問
pam_permit.so

auth

account

password

session

模組任何時候都返回成功.
pam_securetty.so auth 如果使用者要以root登入時,則登入的tty必須在/etc/securetty之中.
pam_listfile.so

auth

account

password session

訪問應用程的控制開關
pam_cracklib.so password

這個模組可以插入到一個程式的密碼棧中,用於檢查密碼的強度.

pam_limits.so session 定義使用系統資源的上限,root使用者也會受此限制,可以通過/etc/security/limits.conf或/etc/security/limits.d/*.conf來設定

 五、PAM模式使用說明

1)pam_access.so模組

pam_access.so模組主要的功能和作用是根據主機名(包括普通主機名或者FQDN)、IP地址和使用者實現全面的訪問控制。pam_access.so模組的具體工作行為根據配置檔案/etc/security/access.conf來決定。該配置檔案的主體包含了三個欄位——許可權、使用者和訪問發起方。格式上是一個用""隔開的表。
第一個欄位:許可權(permission),使用"+"表示授予許可權,用"-"表示禁止許可權。
第二個欄位:使用者(user),定義了使用者、組以及用"@"表示的在不同主機上的同名使用者和同一主機上不同名使用者。
第三個欄位:訪問發起方(origins),定義了發起訪問的主機名稱、域名稱、終端名稱。

而且/etc/security/access.conf檔案提供了很多範例供修改時參考,並且都給出了具體的說明,例如:

#禁止非root使用者通過tty1訪問相關服務
#-:ALL EXCEPT root:tty1

#禁止除了wheel、shutdown以及sync之外的所有使用者訪問相關服務
#-:ALL EXCEPT wheel shutdown sync:LOCAL

#禁止wheel使用者通過.win.tue.nl之外的其它它終端訪問相關服務
#-:wheel:ALL EXCEPT LOCAL .win.tue.nl

# 禁止下面的使用者從任何主機登入。其它使用者可以從任意地方訪問相關服務
#-:wsbscaro wsbsecr wsbspac wsbsym wscosor wstaiwde:ALL

# root使用者允許通過cron來使用tty1到tty6終端訪問相關服務
#+ : root : cron crond :0 tty1 tty2 tty3 tty4 tty5 tty6

# 使用者root允許從下面的地址訪問相關服務
#+ : root : 192.168.200.1 192.168.200.4 192.168.200.9
#+ : root : 127.0.0.1

# 使用者root可以從192.168.201.網段訪問相關服務
#+ : root : 192.168.201.

# 使用者root可以從.foo.bar.org中任何主機訪問相關服務
#+ : root : .foo.bar.org

# 使用者root不允許從任何主機訪問相關服務
#- : root : ALL

# 使用者@nis_group和foo可以從任何主機訪問相關服務
#+ : @nis_group foo : ALL

# 使用者john只能從127.0.0.0/24來對本機相關服務進行訪問
#+ : john : 127.0.0.0/24

# 使用者john可以通過ipv4和ipv6的地址對本機相關服務進行訪問
#+ : john : ::ffff:127.0.0.0/127

# 使用者john可以通過ipv6的地址訪問本機相關服務
#+ : john : 2001:4ca0:0:101::1

# 使用者john可以通過ipv6的主機IP地址來訪問本機
#+ : john : 2001:4ca0:0:101:0:0:0:1

# 使用者john可以通過ipv6的IP地址和掩碼來訪問相關服務
#+ : john : 2001:4ca0:0:101::/64

# 開放所有使用者對本機所有相關服務的訪問
#- : ALL : ALL

示例說明(vsftp):
如果要在網路內架設一個FTP伺服器,而且在該FTP伺服器上需要強制地指定某個使用者只能通過某個IP地址登入,這個時候pam_access.so模組就派上用場了。假設我的FTP伺服器是使用vsftp來構建的,具體操作是:

1)修改FTP伺服器的/etc/pam.d/vsftpd檔案,在呼叫account介面處插入"account    required     pam_access.so"這行內容,如下:
[root@centos6-test06 ~]# vim /etc/pam.d/vsftpd
#%PAM-1.0
session    optional     pam_keyinit.so    force revoke
auth       required pam_listfile.so item=user sense=deny file=/etc/vsftpd/ftpusers onerr=succeed
auth       required pam_shells.so
auth       include  password-auth
account    include  password-auth
account    required     pam_access.so                 //新增這一行內容
session    required     pam_loginuid.so
session    include  password-auth

上述配置表示當針對FTP訪問執行使用者類介面的時候會增加pam_access.so的認證。

2)修改/etc/security/access.conf配置檔案,
在檔案底部新增下面的兩行:
[root@centos6-test06 ~]# vim /etc/security/access.conf
- : kevin : ALL EXCEPT 192.168.10.101
- : grace : ALL EXCEPT 192.168.10.102

前提是已經在系統上事先建立了kevin和grace兩個使用者。上面的配置表示:
kevin使用者不能從192.168.10.101之外的任何客戶端訪問FTP伺服器;
grace使用者不能從192.168.10.102之外的任何客戶端訪問FTP伺服器。

3)修改/etc/vsftpd/vsftpd.conf檔案,禁用匿名登入:
[root@centos6-test06 ~]# vim /etc/vsftpd/vsftpd.conf
......
Anonymous_enable = NO 

這樣當重啟vsftpd服務之後,使用者kevin將只能從192.168.10.101訪問ftp服務,而grace將只能從192.168.10.102訪問ftp服務。
所以當針對這種需求而且不想使用防火牆以及應用程式自帶的認證機制的時候,通過pam_access.so可以實現所需的效果。

2)pam_listfile.so

pam_listfile.so模組的功能和pam_access.so模組類似,目標也是實現基於使用者/組,主機名/IP,終端的訪問控制。不過它實現的方式和pam_access.so會稍微有些不同,因為它沒有專門的預設配置檔案。訪問控制是靠pam配置檔案中的控制選項和一個自定義的配置檔案來實現的。而且除了針對上述訪問源的控制之外,還能夠控制到ruser,rhost,所屬使用者組和登入shell。所以有些使用者認為它的功能似乎比pam_access.so更加靈活和強大一些。

對於pam_listfile.so的配置方法,可以參考vsftpd檔案中對pam的呼叫方式。熟悉vsftpd的人都知道,在vsftpd預設配置中,root使用者是不允許通過ftp方式直接訪問FTP伺服器的。這個功能實際上是由/etc/vsftpd/vsftpd.conf,/etc/vsftpd/ftpusers和/etc/pam.d/vsftpd共同控制的。 因為在/etc/pam.d/vsftpd中有這樣的一行配置:

[root@centos6-test06 ~]# cat /etc/pam.d/vsftpd
......
auth       required pam_listfile.so item=user sense=deny file=/etc/vsftpd/ftpusers onerr=succeed

表示當使用者試圖登入FTP伺服器的時候,會呼叫pam_listfile.so模組來驗證使用者是否可以登入,這裡item=user表示訪問控制是基於user即使用者實現的。那麼哪些使用者可以登入呢?就是除了file選項所定義的/etc/vsftpd/ftpusers檔案之外的使用者,這是由另外一個選項sense=deny所決定的。而在/etc/vsftpd/vsftpd.conf中明確指定了對使用者的認證需要通過/etc/pam.d/vsftpd中的配置呼叫pam模組:

[root@centos6-test06 ~]# cat /etc/vsftpd/vsftpd.conf |grep pam_service_name
pam_service_name=vsftpd

而恰好root使用者又在/etc/vsftpd/ftpusers檔案中,所以這成為了制約root登入FTP伺服器的一個必要條件(但不是唯一條件)。所以針對這種情況,要開放和允許root使用者登入FTP的許可權,至少有三種改法:

1)修改/etc/pam.d/vsftpd檔案,將sense=deny改成sense=allow。這樣會正好將情況反轉過來,FTP伺服器只允許/etc/vsftpd/ftpusers檔案內的使用者登入;
2)修改/etc/pam.d/vsftpd檔案,註釋掉呼叫pam_listfile.so那行。這樣FTP伺服器在認證使用者的時候將不再考慮pam_listfile.so模組的任何限制;
3)將root從/etc/vsftpd/ftpuser檔案中註釋掉;

不過需要注意的是,root使用者比較特殊,因為它在vsftpd配置中的限制不僅僅來自於pam,vsftpd本身的配置中也對其做了限制。當我們看/etc/vsftpd/user_list檔案的時候,還將會看到這樣的配置說明:

[root@centos6-test06 vsftpd]# cat /etc/vsftpd/user_list
# vsftpd userlist
# If userlist_deny=NO, only allow users in this file
# If userlist_deny=YES (default), never allow users in this file, and
# do not even prompt for a password.
# Note that the default vsftpd pam config also checks /etc/vsftpd/ftpusers
# for users that are denied.
........
........

表示當vsftpd.conf中userlist_deny=NO的時候,系統將只允許user_list中的使用者登入FTP伺服器;如果userlist_deny=YES,情況將截然相反——此時user_list變成了黑名單,裡面的使用者將一概不允許登入FTP伺服器。所以要徹底開放root登入FTP的許可權,我們還要在/etc/vsftpd/vsftpd.conf中增加userlist_deny=YES或者註釋掉user_list中的root

不過不管怎麼說,vsftpd中禁用root使用者的直接登入是在絕大多數FTP伺服器上預設的安全措施,所以開放root許可權時應該慎重。

另外除了通過pam_listfile.so實現基於使用者的訪問控制之外,還可以實現基於其它條件的訪問控制。這個可以具體看看pam_listfile.so模組的選項就會比較清楚了,使用pam_listfile.so模組配置的格式分為五個部分:分別是item、onerr、sense、file以及apply。 其中:
a)item=[tty|user|rhost|ruser|group|shell]:定義了對哪些列出的目標或者條件採用規則,顯然,這裡可以指定多種不同的條件。
b)onerr=succeed|fail:定義了當出現錯誤(比如無法開啟配置檔案)時的預設返回值。
c)sense=allow|deny:定義了當在配置檔案中找到符合條件的專案時的控制方式。如果沒有找到符合條件的專案,則一般驗證都會通過。
d)file=filename:用於指定配置檔案的全路徑名稱。
e)apply=user|@group:定義規則適用的使用者型別(使用者或者組)。

而至於file檔案的寫法就簡單了,每行一個使用者或者組名稱即可。所以,當需要對其它服務進行類似的訪問控制的時候,就可以照葫蘆畫瓢。例如現在需要在SSH伺服器上對ssh客戶端實現基於使用者的訪問控制

示例說明一:
不允許bobo賬號通過ssh方式登入。做法如下:

1)針對這種需求只需要更改/etc/pam.d/sshd檔案,並在該檔案中新增一行(一定要新增到第一行):
[root@centos6-test06 ~]# vim /etc/pam.d/sshd
auth required pam_listfile.so  item=user sense=deny file=/etc/pam.d/denyusers onerr=succeed
......

2)建立bobo賬號
[root@centos6-test06 ~]# useradd bobo
[root@centos6-test06 ~]# passwd bobo
Changing password for user bobo.
New password: 
Retype new password: 
passwd: all authentication tokens updated successfully.

3)建立檔案/etc/pam.d/denyusers,並在檔案中寫入使用者資訊。
[root@centos6-test06 ~]# echo "bobo" > /etc/pam.d/denyusers
[root@centos6-test06 ~]# cat /etc/pam.d/denyusers
bobo

4)測試使用bobo賬號通過ssh方式登入不上了
[root@centos6-test06 ~]# ssh -p22 bobo@localhost
bobo@localhost's password: 
Permission denied, please try again.
bobo@localhost's password:

表示使用者以ssh登入必須要通過pam_listfile.so模組進行認證,認證的物件型別是使用者,採用的動作是禁止,禁止的目標是/etc/pam.d/denyuser檔案中所定義的使用者。
這樣在該條目新增到該檔案之後,使用bobo賬號從其它主機遠端ssh訪問伺服器會出現密碼錯誤的提示,但是使用root或者其它使用者則訪問能夠成功!

再次強調,要注意pam模組使用的順序,剛才的規則一定要新增到/etc/pam.d/sshd檔案的auth的第一行之前,否則不會生效!!!!!

示例說明二:
僅僅允許kevin使用者可以通過ssh遠端登入。做法如下:

在/etc/pam.d/sshd檔案中新增一條(務必新增到檔案的第一行!):
auth required pam_listfile.so item=user sense=allow file=/etc/sshdusers onerr=succeed

新增兩個使用者kevin和grace

[root@centos6-test06 ~]# useradd kevin
[root@centos6-test06 ~]# passwd kevin
[root@centos6-test06 ~]# useradd grace
[root@centos6-test06 ~]# passwd grace

編輯file指定的檔案,新增上一個使用者kevin(這一步是關鍵)

[root@centos6-test06 ~]# echo "kevin" >/etc/sshdusers          //檔案/etc/sshdusers是在上面新增到/etc/pam.d/sshd中定義的

然後驗證,發現使用kevin賬號能正常ssh登入,使用grace賬號就不能正常ssh登入了!

[root@centos6-test06 ~]# ssh -p22 kevin@localhost
kevin@localhost's password: 
Last login: Thu Mar 29 12:02:18 2018 from 192.168.10.206

[root@centos6-test06 ~]# ssh -p22 grace@localhost
grace@localhost's password: 
Permission denied, please try again.

[root@centos6-test06 ~]# ssh -p22 root@localhost
root@localhost's password: 
Permission denied, please try again.

注:此處如果root也使用ssh遠端連線,也會受到pam_listfile.so限制的。

溫馨提示:
如果發生錯誤,Linux-PAM 可能會改變系統的安全性。這取決於你自己的選擇,你可以選擇不安全(開放系統)和絕對安全(拒絕任何訪問)。通常,Linux-PAM 在發生錯誤時,傾向於後者。任何的配置錯誤都可能導致系統整個或者部分無法訪問。配置 Linux-PAM 時,可能遇到最大的問題可能就是 Linux-PAM 的配置檔案/etc/pam.d/*被刪除了。如果發生這種事情,你的系統就會被鎖住。有辦法可以進行恢復,最好的方法就是用一個備份的映象來恢復系統,或者登入進單使用者模式然後進行正確的配置。

3)pam_limits.so模組

pam_limits.so模組的主要功能是限制使用者會話過程中對各種系統資源的使用情況。預設情況下該模組的配置檔案是/etc/security/limits.conf。而該配置檔案的基本格式實際上是由4個欄位組成的表,其中具體限制的內容包括:

Domain            type            item                                     value
使用者名稱/組名       軟/硬限制                                                   具體值
                                core——core檔案大小 (KB)
                                data——最大資料大小(KB)
                                fsize——最大檔案大小(KB)
                                memlock——最大可用記憶體空間(KB)
                                nofile——最大可以開啟的檔案數量
                                rss——最大可駐留空間(KB)
                                stack——最大堆疊空間(KB)
                                cpu——最大CPU使用時間(MIN)
                                nproc——最大執行程式數
                                as——地址空間限制
                                maxlogins——使用者可以登入到系統最多次數
                                locks——最大鎖定檔案數目

需要注意的是,如果沒有任何限制可以使用"-"號,並且針對使用者限制的優先順序一般要比針對組限制的優先順序更高。使用pam_limits.so模組的最常見的場景是在執行Oracle資料庫的RHEL伺服器中,因為一般Oracle資料庫在安裝之前,按照其官方文件的說明需要先對某些使用者(Oracle)使用系統資源的情況進行限制。所以我們總是能夠在Oracle資料庫伺服器的/etc/security/limits.conf檔案中看到類似這樣的配置:

[root@centos6-test06 ~]# vim /etc/security/limits.conf
.......
oracle           soft    nproc   2047
oracle           hard    nproc   16384
oracle           soft    nofile  1024
oracle           hard    nofile  65536

結合上面的配置檔案說明,可知Oracle資料庫需要對Oracle使用者使用資源的情況進行一些限制,包括: oracle使用者最大能開啟的程式數不超過16384,最大能開啟的檔案數不超過65536。

至於soft和hard的區別,不同於磁碟配額中的軟限制和硬限制。普通使用者可以調整自己的soft limit但最高不能超過hard limit,而且除了root以外的普通使用者也不能夠隨意更改hard limit。該調整完成之後一般可以使用ulimit命令檢視。

順便提一下,針對nofile,這個只是基於使用者層面的限制和調整方法。基於系統層面的限制和調整方法是修改/etc/sysctl.conf檔案,直接改fs.file-max引數,調整之後sysctl –p生效。

示例說明:
pam_limits.so模組也可以使用在對一般應用程式使用的資源限制方面。如果需要在SSH伺服器上對來自不同使用者的ssh訪問進行限制,就可以呼叫該模組來實現相關功能。例如,當需要限制使用者bobo登入到SSH伺服器時的最大連線數(防止同一個使用者開啟過多的登入程式)。限制操作如下:

由於/etc/pam.d/system-auth中,預設就會通過pam_limits.so 限制使用者最多使用多少系統資源
[root@centos6-test06 ~]# cat /etc/pam.d/system-auth|grep limits.so
session     required      pam_limits.so

因此只需要在/etc/security/limits.conf檔案中增加一行對bobo使用者產生的連線數進行限定:
[root@centos6-test06 ~]# vim /etc/security/limits.conf
......
bobo             hard    maxlogins       2

最後測試
從客戶端以bobo身份登入SSH伺服器時,在客戶端上可以開啟兩個控制檯登入。
但當客戶端開啟第三個登入視窗的時候會被伺服器拒絕,但其它使用者不會受到限制。

注意:這樣限制的只是從客戶端以ssh方式登入次數的場景,如果從xshell登入,則不受限制!

4)pam_rootok.so模組

一般情況下,pam_rootok.so模組的主要作用是使uid為0的使用者,即root使用者能夠直接通過認證而不用輸入密碼。pam_rootok.so模組的一個典型應用是插入到一些應用程式的認證配置檔案中,當root使用者執行這些命令的時候可以不用輸入口令而直接通過認證。比如說"su"命令,為什麼當以root使用者執行"su"切換到普通使用者身份的時候是不需要輸入任何口令而可以直接切換過去?當我們檢視一下/etc/pam.d/su檔案的內容就不會奇怪了。因為該檔案的第一行就是:

[root@centos6-test06 ~]# cat /etc/pam.d/su
......
auth        sufficient  pam_rootok.so

而如果將該行配置註釋掉的情況下,就會發現即便以root使用者切換普通使用者的時候仍然要求輸入口令。

另外一種方法,只需要將上述的"sufficient"改成"required"即可。因為這樣,pam_rootok.so模組的驗證通過就成為了必要條件之一。

pam_rootok.so模組的另外一個應用是在chfn命令中。Chfn命令用於改變/etc/passwd中的使用者的說明欄位。當以root身份執行chfn命令修改使用者資訊的時候是不用輸入密碼的。但是以普通使用者身份執行chfn則需要輸入密碼之後才能改變自己的使用者說明。這實際上也是因為在/etc/pam.d/chfn配置檔案中的第一行呼叫了pam_rootok.so的結果。

不過這裡即便將該配置中的第一行註釋掉,root使用者通過chfn修改自己資訊的時候仍然不需要使用密碼。所以恐怕效果不是很明顯。究其原因主要是很多PAM模組對root使用者是不會產生限制的。

示例說明(禁用使用者間使用su切換命令):

su的缺點
1)不安全su工具在多人蔘與的系統管理中,並不是最好的選擇,su只適用於一兩個人蔘與管理的系統,畢竟su並不能讓普通使用者受限的使用;超級使用者root密碼應該掌握在少數使用者手中。
2)麻煩:需要把root密碼告知每個需要root許可權的人。

可以在/etc/pam.d/su檔案裡設定禁止使用者使用su命令
[root@centos6-test06 ~]# vim /etc/pam.d/su
auth sufficient pam_rootok.so
# Uncomment the following line to implicitly trust users in the "wheel" group.
#auth sufficient pam_wheel.so trust use_uid
# Uncomment the following line to require a user to be in the "wheel" group.
#auth required pam_wheel.so use_uid
...........

a)以上標紅的兩行是預設狀態(即開啟第一行,註釋第二行)這種狀態下是允許所有使用者間使用su命令進行切換的!(或者兩行都註釋也是執行所有使用者都能使用su命令,但root下使用su切換到其他普通使用者需要輸入密碼;如果第一行不註釋,則root使用su切換普通使用者就不需要輸入密碼)
b)如果開啟第二行表示只有root使用者和wheel組內的使用者才可以使用su命令。
c)如果註釋第一行開啟第二行,表示只有wheel組內的使用者才能使用su命令,root使用者也被禁用su命令。

5) pam_userdb.so模組

pam_userdb.so模組的主要作用是通過一個輕量級的Berkeley資料庫來儲存使用者和口令資訊。這樣使用者認證將通過該資料庫進行,而不是傳統的/etc/passwd和/etc/shadow或者其它的一些基於LDAP或者NIS等型別的網路認證。所以存在於Berkeley資料庫中的使用者也稱為虛擬使用者。

pam_userdb.so模組的一個典型用途就是結合vsftpd配置基於虛擬使用者訪問的FTP伺服器。

相對於本地使用者以及匿名使用者來說,虛擬使用者只是相對於FTP伺服器而言才有用的使用者,這些使用者被嚴格地限定在pam_userdb資料庫當中。所以虛擬使用者只能訪問FTP伺服器所提供的資源,因而可以大大提高系統安全性。另外相對於匿名使用者而言,虛擬使用者必須通過使用者名稱和密碼才能夠訪問FTP的資源。這樣也提高了對FTP使用者下載的可管理性。

基於虛擬使用者實現的vsftpd的原理基本上是這樣一個過程:先定義一些專門針對FTP的虛擬使用者,然後將使用者資訊加入到系統自帶的資料庫中(但不是passwd)從而生成一個訪問FTP的虛擬使用者列表,這裡使用的資料庫是db4也就是Berkeley DB。然後可以通過使用pam_userdb.so模組來呼叫該資料庫儲存使用者資訊以及實現FTP使用者認證。當然同時也可以在系統中通過對配置檔案的定義和劃分來實現對不同虛擬使用者不同型別的訪問控制。

FTP虛擬賬號登入環境部署:http://www.cnblogs.com/kevingrace/p/5587140.html

6)pam_cracklib.so模組

pam_cracklib.so是一個常用並且非常重要的PAM模組。該模組主要的作用是對使用者密碼的強健性進行檢測。即檢查和限制使用者自定義密碼的長度、複雜度和歷史等。如不滿足上述強度的密碼將拒絕使用者使用。pam_cracklib.so比較重要和難於理解的是它的一些引數和計數方法,其常用引數包括: 

debug:    將除錯資訊寫入日誌;
type=xxx: 當新增/修改密碼時,系統給出的預設提示符是"New UNIX password:"以及"Retype UNIX password:",而使用該引數可以自定義輸入密碼的提示符,比如指定type=your own word;
retry=N:  定義登入/修改密碼失敗時,可以重試的次數;
Difok=N:  定義新密碼中必須至少有幾個字元要與舊密碼不同。但是如果新密碼中有1/2以上的字元與舊密碼不同時,該新密碼將被接受;
minlen=N: 定義使用者密碼的最小長度;
dcredit=N:定義使用者密碼中必須至少包含多少個數字;
ucredit=N:定義使用者密碼中必須至少包含多少個大寫字母;
lcredit=N:定義使用者密碼中必須至少包含多少個小些字母;
ocredit=N:定義使用者密碼中必須至少包含多少個特殊字元(除數字、字母之外);

特別要注意:
當N>0時,N代表新密碼中最多可以有N個指定的字元!!
當N<0時,N代表新密碼中最少可以有N個指定的字元!!

同時建議重啟系統使之生效!

/etc/pam.d/login檔案裡包含了/etc/pam.d/system-auth檔案的配置

[root@centos6-test06 ~]# cat /etc/pam.d/login|grep system-auth
auth       include      system-auth
account    include      system-auth
password   include      system-auth
session    include      system-auth

如下看pam_cracklib.so的一個應用例項:在/etc/pam.d/system-auth中使用pam_cracklib.so來限制使用者修改自己密碼時必須滿足一定的強健性要求。

[root@centos6-test06 ~]# cat /etc/pam.d/system-auth
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth        required      pam_env.so
auth        sufficient    pam_unix.so nullok try_first_pass
auth        requisite     pam_succeed_if.so uid >= 500 quiet
auth        required      pam_deny.so

account     required      pam_unix.so
account     sufficient    pam_localuser.so
account     sufficient    pam_succeed_if.so uid < 500 quiet
account     required      pam_permit.so

password    requisite     pam_cracklib.so try_first_pass retry=3 type=
password    sufficient    pam_unix.so md5 shadow nullok try_first_pass use_authtok
password    required      pam_deny.so

session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_unix.so
 
-----------------------------------------------------------------------------
從上面使用pam_cracklib.so的策略看,要求使用者修改密碼時必須要滿足9位,並且密碼中至少要包含一個大寫字母、小寫字母、數字和特殊符號。
 
但是實際上像minlen和所有credit所對應的數值可以是非0之外的正負整數,那麼這些數值到底表示什麼意思呢?
很多人將其簡單地理解為某一類字元的位數,其實遠遠沒有那麼簡單。
 
下面我們對這些數值和關係做一個簡短的說明:
 
首先要明確整個環境中密碼的長度要滿足下面的計算公式:
計算公式:
最小密碼長度(minlen)應該小於或者等於 dcredit+ucredit+lcredit+ocredit+其它分值 (同時滿足 * credit的條件)。
 
注意:
*credit=-1表示至少有一個的意思
*credit=N(N表示當滿足條件的時候加N分,例如dcredit=2表示一個數字加2分,兩個數字加4分)
所以這裡minlen其實更準確的表述應該是mincredit。
 
所以在下面的例子中,當pam_cracklib.so的引數按如下方式指定:
password    requisite     pam_cracklib.so try_first_pass retry=3 minlen=12 dcredit=2 ucredit=0 lcredit=0 ocredit=0
 
那麼當使用者執行命令修改密碼的時候:
[bobo@centos6-test06 ~]$ passwd
Changing password for user bobo.
Changing password for bobo
(current) UNIX password:
New UNIX password:                   輸入密碼"1\=poiuyt"   不成功      1個數字再加2分
 
此時密碼有一個數字,2分,其它的字元每個1分,總共10分,不滿足minlen的位數需求,所以該密碼不能通過。
BAD PASSWORD: is too simple
New UNIX password:                   輸入密碼"12\=poiuyt"   成功     2個數字再加2分
Retype new UNIX password:
 
此時密碼有兩個數字,4分,其它的字元每個1分,總共12分,滿足minlen的位數需求,所以密碼可以通過。
New UNIX password:                   輸入密碼"1\=poiuytre"   成功     1個數字再加2分
Retype new UNIX password:
 
此時密碼有1個數字,2分,其它的字元每個1分,總共12分,滿足minlen的位數需求,所以密碼可以通過。
 
因此通過上述的配置基本可以得出這樣的結論:
 
當某類credit為正數N的時候,表示密碼中該類字元一個可以加N分;當某類credit為負數N的時候,表示密碼中某類字元必須具備N個。時間關係我將不會一一演示。
 
所以當輸入的密碼所有的字元總分大於或者等於minlen,並且滿足所有credit的要求,該密碼通過; 即:輸入的密碼長度(每個輸入值都算數)+*credit(加分)>=minlen
 
所以pam_cracklib.so模組在系統安全管理策略和管理中的用途是非常重要和廣泛的。

7)pam_pwhistroy.so模組

pam_pwhistory.so模組也是一個常用模組,一般輔助pam_cracklib.so,pam_tally.so以及pam_unix.so等模組來加強使用者使用密碼的安全度。不過pam_pwhistory.so模組起的是另一類的作用,即專門為使用者建立一個密碼歷史檔案,防止使用者在一定時間內使用已經用過的密碼。

示例說明:(特別注意:/etc/pam.d/system-auth下的配置針對的是普通使用者,在root使用者下是無效的)
當需要限定使用者在90天之內不能重複使用以前曾經使用過的10個密碼,那麼具體操作方法是去修改/etc/pam.d/system-auth檔案,在password介面處增加:

[root@centos6-test06 ~]# vim /etc/pam.d/system-auth
......
password  required  pam_cracklib.so  retry=3  password  required  pam_pwhistory.so enforce_for_root remember=10

----------------------------------------------------------------
此時使用者使用過的密碼將會記錄到/etc/security/opasswd檔案中。但是pam_pwhistory.so並沒有什麼選項可以限定密碼在多少天之內無法被重複使用,
所以上述的90天是無法配置的。一個簡單的解決方法就是當90天左右的時候,手動清空一次opasswd檔案即可。

當然,如果要實現同樣的功能除了pam_pwhistory.so模組之外還有其它的辦法。比較常用的是pam_unix.so模組。
具體方法是修改/etc/pam.d/system-auth檔案,給pam_unix.so模組里加上remember=10這個選項,修改之後的配置檔案為:
[root@centos6-test06 ~]# vim /etc/pam.d/system-auth
.......
password required pam_unix.so md5 remember=10 use_authtok

這樣系統將同樣記住10個已經使用的密碼。

不過此時/etc/security/opasswd檔案因為記錄了N個使用過的密碼,所以安全性就十分關鍵了,所以要確保該檔案只能被root使用者讀取和編輯:
[root@centos6-test06 ~]# touch /etc/security/opasswd
[root@centos6-test06 ~]# chown root:root /etc/security/opasswd
[root@centos6-test06 ~]# chmod 600 /etc/security/opasswd

==========總結幾個PAM模組比較常見的實操案例===========

1)怎樣才能強迫使用者設定的密碼不能與過去3次內的密碼重複?(特別注意:/etc/pam.d/system-auth下的配置針對的是普通使用者,在root使用者下是無效的)

修改/etc/pam.d/system-auth,增加pam_unix.so的引數,如下:
[root@centos6-test06 ~]# vim /etc/pam.d/system-auth
......
password    sufficient    pam_unix.so md5 shadow nullok try_first_pass use_authtok remember=3  

2)如何要求使用者設定的密碼必須至少包含5個數字和3個特殊符號?

修改/etc/pam.d/system-auth,在password使用pam_cracklib.so設定的最後附加 dcredit=-5 ocredit=-3
[root@centos6-test06 ~]# vim /etc/pam.d/system-auth
......
password    requisite     pam_cracklib.so try_first_pass retry=3 dcredit=-5 ocredit=-3  

----------------------------------------------------------------------
同時注意:
密碼中的n個數字和n個特殊字元不能全部放在一起!!

3)如何限制kevin使用者最多同時登陸4個?(同時可以限制root使用者)

這需要pam_limits.so模組。由於/etc/pam.d/system-auth中,預設就會通過pam_limits.so 限制使用者最多使用多少系統資源.
[root@centos6-test06 ~]# cat /etc/pam.d/system-auth|grep limits.so
session     required      pam_limits.so

因此只需要在/etc/security/limits.conf 中加入以下內容:
[root@centos6-test06 ~]# vim /etc/security/limits.conf
......
kevin        hard       maxlogins       4  

4)某使用者連續登陸失敗2次就鎖定該賬號,禁止登陸?(預設只能嘗試登入三次,由retry=N決定的)

現在很多地方都有限制使用者登入的功能,Linux也是如此,當你登入失敗多次後就可以限制使用者登入,從而起到保護電腦安全的作用,通過PAM模組即可實現。
Linux有一個pam_tally2.so的PAM模組,來限定使用者的登入失敗次數,如果次數達到設定的閾值,則鎖定使用者。
 
編譯PAM的配置檔案
[root@centos6-test06 ~]# vi  /etc/pam.d/login    //在#%PAM-1.0下面新增一行
#%PAM-1.0
auth       required     pam_tally2.so  onerr=fail deny=2 unlock_time=300 even_deny_root root_unlock_time=10
......
 
引數解釋:
onerr=fail         表示定義了當出現錯誤(比如無法開啟配置檔案)時的預設返回值;
even_deny_root     表示也限制root使用者;
deny               表示設定普通使用者和root使用者連續錯誤登陸的最大次數,超過最大次數,則鎖定該使用者;
unlock_time        表示設定普通使用者鎖定後,多少時間後解鎖,單位是秒;
root_unlock_time   表示設定root使用者鎖定後,多少時間後解鎖,單位是秒;
 
此處使用的是 pam_tally2模組,如果不支援pam_tally2,可以使用pam_tally模組。
另外,不同的pam版本,設定可能有所不同,具體使用方法,可以參照相關模組的使用規則。
 
特別注意:
一定要將內容新增到#%PAM-1.0的下面,即在第二行新增內容,一定要寫在前面!!
如果寫在後面,雖然使用者被鎖定,但是隻要使用者輸入正確的密碼,還是可以登入的!
 
------------------------------------------
也可以將上面的內容新增到/etc/pam.d/password-auth檔案中,因為/etc/pam.d/login檔案中包括(include)了password-auth配置
[root@centos6-test06 ~]# vim /etc/pam.d/system-auth      //同樣新增到auth區域的第一行
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth       required     pam_tally2.so  onerr=fail deny=2 unlock_time=300 even_deny_root root_unlock_time=10
 
========================================================================================
特別注意:
上面的配置只是限制了使用者從tty終端登入,而沒有限制遠端ssh登入,如果想限制遠端登入,需要在/etc/pam.d/sshd檔案裡配置
[root@centos6-test06 ~]# vim /etc/pam.d/sshd            //同樣新增到auth區域的第一行
#%PAM-1.0
auth       required     pam_tally2.so  onerr=fail deny=2 unlock_time=300 even_deny_root root_unlock_time=10
 
這樣的話,使用ssh遠端登入的時候,連續輸入兩次錯誤密碼,就會被鎖定了!
如果輸入錯誤次數沒有達到deny設定的次數,再輸入正確密碼就可以登入。
 
 
驗證:
[bobo@centos6-test06 ~]$ ssh -p22 kevin@localhost
kevin@localhost's password:                     //第一次輸入密碼錯誤
Permission denied, please try again.   
kevin@localhost's password:                     //第二次輸入密碼錯誤,此時已被鎖定
Permission denied, please try again.
kevin@localhost's password:                     //接著第三次再輸入正確密碼,還是無法登入進去,因為已被鎖定300s了!
Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
 
因為被鎖定300s了!在這個時間內,就算再輸入正確密碼也是無法順利登入到機器的!
[bobo@centos6-test06 ~]$ ssh -p22 kevin@localhost
kevin@localhost's password:
Permission denied, please try again.
 
接著可以解鎖!!
檢視使用者登入失敗的次數。由下面命令可知,已經輸錯3次了
[root@centos6-test06 ~]# pam_tally2 --user kevin
Login           Failures Latest failure     From
kevin               3    03/30/18 07:35:49  ::1
 
解鎖指定使用者
[root@centos6-test06 ~]# pam_tally2 -r -u kevin
Login           Failures Latest failure     From
kevin               3    03/30/18 07:35:49  ::1
[root@centos6-test06 ~]# pam_tally2 --user kevin
Login           Failures Latest failure     From
kevin               0
 
接著,就可以輸入正確密碼登入機器了
[bobo@centos6-test06 ~]$ ssh -p22 kevin@localhost
kevin@localhost's password:
Last login: Fri Mar 30 07:40:04 2018 from ::1
[kevin@centos6-test06 ~]$

5)如何限制root只能從kevin.com這臺計算機使用ssh遠端登陸?

由於ssh伺服器的程式檔案使用sshd,而sshd剛好支援PAM,驗證如下:
[root@centos6-test06 ~]# ldd /usr/sbin/sshd | grep libpam.so  
    libpam.so.0 => /lib64/libpam.so.0 (0x00007f36f254d000)

修改/etc/pam.d/sshd,加入第二行,如下:
[root@centos6-test06 ~]# vim /etc/pam.d/sshd 
auth       include      system-auth  
account    required     pam_access.so accessfile=/etc/deny_sshd  
account    required     pam_nologin.so  

建立/etc/deny_sshd檔案
[root@centos6-test06 ~]# touch /etc/deny_sshd
[root@centos6-test06 ~]# vim /etc/deny_sshd
-:root:ALL EXCEPT kevin.com