pam_access.so模塊主要的功能和作用是根據主機名(包括普通主機名或者FQDN)、IP地址和用戶實現全面的訪問控制。 pam_access.so模塊的具體工作行為根據配置文件/etc/security/access.conf來決定。該配置文件的主體包含了三個字段 ——權限、用戶和訪問發起方。格式上是一個用“:”隔開的表。
第一個字段:權限(permission),使用“+”表示授予權限,用“-”表示禁止權限。
第二個字段:用戶(user),定義了用戶、組以及用“@”表示的在不同主機上的同名用戶和同一主機上不同名用戶。
第三個字段:訪問發起方(origins),定義了發起訪問的主機名稱、域名稱、終端名稱。
而且該文件提供了很多范例供修改時參考,並且都給出了具體的說明,例如:
#禁止非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
那麼具體如何應用到實際環境中呢?我們來設計這樣一個例子:
如果要在網絡內架設一個FTP服務器,而且在該FTP服務器上需要強制地指定某個用戶只能通過某個IP地址登錄。這個時候pam_access.so模塊就派上用場了。
假設我的FTP服務器是使用vsftp來構建的,那麼具體方法是:
首先修改FTP服務器的/etc/pam.d/vsftpd文件,在調用account接口處插入:
"account required pam_access.so"到第一行,那麼整個文件的內容如下:
[root@localhost ~]# cat /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 system-auth account required pam_access.so account include system-auth session include system-auth session required pam_loginuid.so
- : admin1 : ALL EXCEPT 192.168.10.251 - : admin2 : ALL EXCEPT 192.168.10.252
最後再修改/etc/vsftpd/vsftpd.conf文件,禁用匿名登錄:
Anonymous_enable = NO
這樣當重啟vsftpd服務之後,用戶admin1將只能從192.168.10.251訪問ftp服務,而admin2將只能從192.168.10.252訪問ftp服務。
所以當針對這種需求而且不想使用防火牆以及應用程序自帶的認證機制的時候,通過pam_access.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中有這樣的一行配置:
auth required pam_listfile.so item=user sense=deny file=/etc/vsftpd/ftpusers onerr=succeed
而在/etc/vsftpd/vsftpd.conf中明確指定了對用戶的認證需要通過/etc/pam.d/vsftpd中的配置調用pam模塊:
pam_service_name=vsftpd
而恰好root用戶又在/etc/vsftpd/ftpusers文件中,所以這成為了制約root登錄FTP服務器的一個必要條件(但不是唯一條件)。
所以針對這種情況,我們要開放和允許root用戶登錄FTP的權限,至少有三種改法:
修改/etc/pam.d/vsftpd文件,將sense=deny改成sense=allow。這樣會正好將情況反轉過來,FTP服務器只允許/etc/vsftpd/ftpusers文件內的用戶登錄;
修改/etc/pam.d/vsftpd文件,注釋掉調用pam_listfile.so那行。這樣FTP服務器在認證用戶的時候將不再考慮pam_listfile.so模塊的任何限制;
將root從/etc/vsftpd/ftpuser文件中注釋掉;
不過需要注意的是,root用戶比較特殊,因為它在vsftpd配置中的限制不僅僅來自於pam,vsftpd本身的配置中也對其做了限制。當我們看/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、sense、file、onerr以及apply。 其中:
item=[tty|user|rhost|ruser|group|shell]:定義了對哪些列出的目標或者條件采用規則,顯然,這裡可以指定多種不同的條件。
onerr=succeed|fail:定義了當出現錯誤(比如無法打開配置文件)時的缺省返回值。
sense=allow|deny:定義了當在配置文件中找到符合條件的項目時的控制方式。如果沒有找到符合條件的項目,則一般驗證都會通過。
file=filename:用於指定配置文件的全路徑名稱。
apply=user|@group:定義規則適用的用戶類型(用戶或者組)。
而至於file文件的寫法就簡單了,每行一個用戶或者組名稱即可。
所以,當我們需要對其它服務進行類似的訪問控制的時候,就可以照葫蘆畫瓢。例如現在需要在SSH服務器上對ssh客戶端實現基於用戶的訪問控制,目的是不允許admin從通過ssh登錄。
針對這種需求只需要更改/etc/pam.d/sshd文件,並在該文件中添加一行(添加到第一行):
auth required pam_listfile.so item=user sense=deny file=/etc/pam.d/denyusers onerr=succeed
然後建立文件/etc/pam.d/denyusers,並在文件中寫入用戶信息——>就寫admin即可。
表示用戶以ssh登錄必須要通過pam_listfile.so模塊進行認證,認證的對象類型是用戶,采用的動作是禁止,禁止的目標是/etc/pam.d/denyuser文件中所定義的用戶。
這樣在該條目添加到該文件之後,使用admin從其它主機遠程ssh訪問服務器會出現密碼錯誤的提示。但是使用root或者其它用戶則訪問能夠成功。
再次強調,要注意pam模塊使用的順序,剛才的規則一定要添加到auth的第一行之前,否則不會生效。
pam_listfile.so的另外一個案例是應用於諸如xinetd超級進程上的的非獨立服務的應用。例如筆者曾接觸過一個用戶在對系統進行安 全加固的時候需要禁止gssftp的匿名用戶登錄功能。這裡需要說明的是gssftp是RHEL系統上基於kerberos協議進行認證的一款輕量級的 FTP服務器。默認情況下,當修改了/etc/xinetd/gssftp配置文件並通過重啟xinetd啟動服務就可以開啟該服務。當開啟gssftp 服務之後,該ftp服務器也是允許匿名用戶登錄的。而且除了/etc/xinetd.d/gssftp之外沒有其它的配置文件可以對該服務進行過多的定 制。這個時候實際上也可以借用pam_listfile.so模塊來對其進行一些簡單的控制。
參考如下的例子,如果要禁用匿名登錄,則可以修改/etc/xinetd.d/gssftp文件如下:
[root@localhost ~]# cat /etc/xinetd.d/gssftp # default: off # description: The kerberized FTP server accepts FTP connections \ # that can be authenticated with Kerberos 5. service ftp { flags = REUSE socket_type = stream wait = no user = root server = /usr/kerberos/sbin/ftpd # server_args = -l -a log_on_failure += USERID disable = no }
auth required pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed並根據PAM配置文件內容建立相應配置文件/etc/ftpusers,內容為:
anonymous ftp
這樣修改之後的效果是,當沒有改server_args時,那麼啟用/etc/ftpusers之後,所有用戶都無法登錄服務器;而如果保存了 server_args之後,只有pam_listfile.so指定在/etc/ftpusers文件中的用戶不能登錄FTP服務器,而且在輸入用戶名 之後會被直接拒絕掉。但root或者其它自建立的用戶可以訪問FTP服務器。
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文件中看到類似這樣的配置:
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訪問進行限制,就可以調用該模塊來實現相關功能。例如,當需要限制用戶admin登錄到SSH服務器時的最大連接數(防止同一個用戶開啟過多的登 錄進程),就可以在/etc/pam.d/sshd文件中增加一行對pam_limits.so模塊的調用:
session required pam_limit.so然後在/etc/security/limits.conf文件中增加一行對admin用戶產生的連接數進行限定:
admin hard maxlogins 2
完成之後重啟服務器端的sshd服務。
之後我們可以看到,從客戶端以admin身份登錄SSH服務器時,在客戶端上可以打開兩個控制台登錄。但當客戶端開啟第三個登錄窗口的時候會被服務器拒絕,但其它用戶不會受到限制。
一般情況下,pam_rootok.so模塊的主要作用是使uid為0的用戶,即root用戶能夠直接通過認證而不用輸入密碼。
pam_rootok.so模塊的一個典型應用是插入到一些應用程序的認證配置文件中,當root用戶執行這些命令的時候可以不用輸入口令而直接通過認證。
比如說“su”命令,為什麼當以root用戶執行“su”切換到普通用戶身份的時候是不需要輸入任何口令而可以直接切換過去?
當我們查看一下/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用戶是不會產生限制的。
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服務器配置方法,其中也包含了對pam_userdb.so模塊的使用。
我的實驗環境很簡單:
FTP服務器的IP地址是:10.66.0.136,使用的操作系統是RHEL 5.4,FTP服務是vsftpd。
操作步驟:
1.備份配置文件:
[root@dhcp-0-136 ~]# cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.bak2.建立虛擬用戶數據庫文件login.txt:
[root@dhcp-0-136 vsftpd]# pwd /etc/vsftpd [root@dhcp-0-136 vsftpd]# cat login.txt ftpuser1 123 ftpuser2 123 ftpuser3 123
該文件單數行為用戶名稱,雙數行為用戶訪問FTP服務器時的口令。
完成之後根據該文件內容創建登錄用戶數據庫文件:
[root@dhcp-0-136 vsftpd]# db_load -T -t hash -f /etc/vsftpd/login.txt /etc/vsftpd/vsftpd_login.db
之後需要確認系統上已經安裝Berkeley DB,即db4軟件包。
完成之後,在/etc/vsftpd/vsftpd.conf目錄下會產生vsftpd_login.db文件。
設置該文件的訪問權限為僅root可讀寫:
[root@dhcp-0-136 vsftpd]# chmod 600 vsftpd_login.db
3.使用PAM來實現對登錄FTP用戶的限制:
現在需要創建一個使用數據庫的pam配置文件,在這裡該文件命名為vsftpd.pam,在/etc/pam.d目錄下。
[root@dhcp-0-136 ~]# touch /etc/pam.d/vsftpd.pam [root@dhcp-0-136 ~]# vi /etc/pam.d/vsftpd.pam在該文件中寫入下面的兩行:
[root@dhcp-0-136 ~]# cat /etc/pam.d/vsftpd.pam auth required /lib/security/pam_userdb.so db=/etc/vsftpd/vsftpd_login account required /lib/security/pam_userdb.so db=/etc/vsftpd/vsftpd_login假如說以後添加了新的用戶,那麼修改login.txt,然後再次執行命令:
db_load -T -t hash -f /etc/vsftpd/login.txt /etc/vsftpd/vsftpd_login.db
生成新的數據庫即可。
4.建立一個本地用戶,其主目錄作為虛擬用戶對FTP服務器的訪問時的服務目錄:
[root@dhcp-0-136 ~]# useradd –d /home/ftpsite virtual
通過上面的步驟建立一個名為virtual的本地用戶,並且該用戶的主目錄是/home/virtual
5.現在通過對/etc/vsftpd/vsftpd.conf主配置文件的定義來使虛擬用戶可以訪問FTP服務:
[root@dhcp-0-136 ~]# vi /etc/vsftpd/vsftpd.conf既然該服務器要求使用虛擬用戶訪問,那麼需要先關閉匿名用戶訪問功能:
anonymous_enable=NO local_enable=YES另外出於安全考慮,此處添加的所有用戶都只賦予對FTP服務器只讀權限:
write_enable=NO anon_upload_enable=NO anon_mkdir_write_enable=NO anon_other_write_enable=NO確保用戶在登錄的時候使用剛才定義的PAM配置文件來進行身份驗證,因此更改此行為:
pam_service_name=/etc/pam.d/vsftpd.pam6.激活虛擬用戶功能,並將所有虛擬用戶對FTP服務器的訪問映射為剛才所添加的virtual用戶對FTP服務器的訪問。
guest_enable=YES guest_username=virtual
這個 guest_enable非常重要,該選項用來激活虛擬用戶! 而guest_username 是將所有虛擬用戶映射成先前所建立的真實用戶"virtual"。這也決定了虛擬用戶在整個文件系統中的位置,也就是"virtual"的主目錄 /home/ftpsite。
如果系統中還有本地用戶需要訪問FTP服務器,可以再次對本地用戶訪問FTP服務時的根目錄進行指定:
local_root=/home/ftpsite當然在這裡將local_root改為其它用戶也沒有任何問題。 再增加一行:
listen=YES表示FTP服務器將會以standalone的模式啟動。即不通過xinetd以及/etc/init.d下的腳本啟動,而可以直接執行vsftpd的啟動。最後啟動FTP服務:
[root@dhcp-0-136 ~]# service vsftpd restart
在服務啟動之後可在客戶端上進行測試: 我們可以使用剛才在自定義數據庫中建立的用戶ftpuser1、ftpuser2、ftpuser3分別登錄FTP服務器進行訪問測試,如果都能夠在 ftp的命令行中正常登錄則證明整個實驗成功! 但是如果訪問失敗,比如說如果出現 “failed to open directory",則有可能是因為目錄/home/ftpsite不是全局只讀屬性(如果想更改,可以通過設置 anon_world_readable_only=NO來實現,這個默認是YES,它是用來設置匿名用戶只能下載全局可讀的文件)。
7.在FTP服務器的虛擬用戶建立之後,可以考慮針對不同的虛擬用戶設置不同的訪問權限:
整個功能只有在使用虛擬帳號的情況下才能借助虛擬帳號的per-user功能來實現。
為了測試需要,現在添加另外三個新的用戶,分別是ftpuser4,ftpuser5和ftpuser6:
[root@dhcp-0-136 vsftpd]# cat login.txt ftpuser1 123 ftpuser2 123 ftpuser3 123 ftpuser4 123 ftpuser5 123 ftpuser6 123然後將該文件所有信息再次導入數據庫中:
[root@dhcp-0-136 vsftpd]# db_load -T -t hash -f /etc/vsftpd/login.txt /etc/vsftpd/vsftpd_login.db
假如在該場景中需要設置ftpuser4和ftpuser5用戶具有對主目錄的讀取權限,而ftpuser6具有對主目錄的寫入權限。
那麼可以針對這三個用戶分別建立配置文件來進行限制。
首先創建並且定義一個容納每個用戶配置文件的目錄:
[root@dhcp-0-136 vsftpd]# mkdir /etc/vsftpd_user_conf然後在主配置文件中進行定義,定義的是不同用戶配置文件所存儲的路徑,就在剛才建立的目錄下:
user_config_dir=/etc/vsftpd_user_conf進入該目錄創建不同用戶的配置文件:
[root@dhcp-0-136 vsftpd]# cd /etc/vsftpd_user_conf創建的ftpuser4配置文件的內容如下:
[root@dhcp-0-136 vsftpd]# ls /etc/vsftpd_user_conf ftpuser4 [root@dhcp-0-136 vsftpd]# cat /etc/vsftpd_user_conf/ftpuser4 anon_world_readalbe_only=NO通過上面的定義,ftpuser4用戶可以讀取的同時也能夠下載文件。但是如果寫成YES則意味著無法列出文件和目錄。
[root@dhcp-0-136 vsftpd]#cp /etc/vsftpd_user_conf/ftpuser4 /etc/vsftpd_user_conf/ftpuser5最後是定義ftpuser6的權限,該用戶可以向服務器目錄寫入和上傳,那麼配置文件內容為:
[root@dhcp-0-136 vsftpd]# vi /etc/vsftpd_user_conf/ftpuser6 anon_world_readable_only=NO 不僅僅是只讀,還可以下載 write_enable=YES 可以寫入 anon_upload_enable=YES 可以上傳 anon_mkdir_write_enable=YES 可以建立目錄如果ftpuser5已經提升為管理員,現在需要針對管理員定義一個更高的權限,可以將ftpuser5的配置文件增加一行:
anon_other_write_enable=YES 增加管理員用戶的刪除/重命名的權限
完成之後保存退出,並重啟服務:
分別測試ftpuser4、ftpuser5以及ftpuser6的權限會發現:
ftpuser4只有登錄浏覽權限;
ftpuser5除了登錄浏覽之外還可以刪除文件以及重命名文件
ftpuser6可以登錄浏覽並上傳和下載,但是對於已有的文件沒有寫入權限。
實驗到此基本成功!
在實際操作中,這種方法能夠更好解決對服務器訪問用戶細化地設置權限的問題。而且pam_userdb.so模塊也不僅僅只是用於在FTP服務中創建和使用虛擬用戶,類似的服務,例如postfix,web服務等,都可以使用該模塊實現類似功能。
pam_securetty.so模塊用於控制用戶登錄系統的時候所使用的終端。為說明該模塊的用法,我們可以例舉一個簡單的例子:
在RHEL操作系統上一旦開啟telnet服務之後,默認情況下root用戶是無法通過telnet登錄的。如果要開啟該功能的話,只需要修改/etc/pam.d/remote文件,將該文件中的:
auth required pam_securetty.so
這一行注釋掉即可。
當通過這種方式telnet成功之後,再執行who命令查看用戶登錄情況的時候不難發現,剛才root用戶telnet上來使用的終端是 pts/0,即網絡終端。那麼為什麼root用戶無法使用pts/0登錄系統呢?實際上這是pam_securetty.so模塊的配置文件/etc /securetty所定義的。默認情況下該文件中只定義了本地終端,所以另外一種改法是將pts/0,pts/1這類網絡終端以及所需要添加的其它類型 終端加入到該文件中去。這樣修改之後root用戶一樣可以登錄。
不過當我們使用非root用戶通過telnet登錄的時候會發現登錄成功的時候通過who顯示出來用的也是pts/0終端,那麼為什麼非root用戶不用修改securetty文件而root用戶就需要?其實答案很簡單,只要訪問/usr/share/doc/pam-/txt/README.pam_securetty文件(該目錄下也有其它PAM模塊的幫助文檔)就可以獲知,實際上pam_securetty.so和其它的pam模塊不同,它只針對root用戶起作用。
所以pam_securetty模塊和pam_limit.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:定義用戶密碼中必須包含多少個特殊字符(除數字、字母之外);
下面是關於pam_cracklib.so的一個應用實例——在/etc/pam.d/system-auth中使用pam_cracklib.so來限制用戶修改自己密碼時必須滿足一定的強健性要求。
[root@localhost ~]# 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 /lib/security/$ISA/pam_env.so auth sufficient /lib/security/$ISA/pam_unix.so likeauth nullok auth required /lib/security/$ISA/pam_deny.so account required /lib/security/$ISA/pam_unix.so account sufficient /lib/security/$ISA/pam_succeed_if.so uid < 100 quiet account required /lib/security/$ISA/pam_permit.so password required /lib/security/$ISA/pam_cracklib.so retry=3 minlen=9 dcredit=-1 ucredit=-1 lcredit=-1 ocredit=-1 password sufficient /lib/security/$ISA/pam_unix.so nullok use_authtok md5 shadow password required /lib/security/$ISA/pam_deny.so session required /lib/security/$ISA/pam_limits.so session required /lib/security/$ISA/pam_unix.so
從上面使用pam_cracklib.so的策略看,要求用戶修改密碼時必須要滿足9位,並且密碼中至少要包含一個大寫字母、小寫字母、數字和特殊符號。
但是實際上像minlen和所有credit所對應的數值可以是非0之外的正負整數,那麼這些數值到底表示什麼意思呢?很多人將其簡單地理解為某一類字符的位數,其實遠遠沒有那麼簡單。
下面我們對這些數值和關系做一個簡短的說明:
首先要明確整個環境中密碼的長度要滿足下面的計算公式:
計算公式:最小密碼長度(minlen)應該小於或者等於 dcredit+ucredit+lcredit+ocredit+其它分值 (同時滿足 * credit的條件),關於分值我們隨後會講解。 (參考file:///usr/share/doc/pam-0.99.6.2/html/sag-pam_cracklib.html理解)
(注)*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那麼當用戶執行命令修改密碼的時候:
[test@dhcp-0-185 ~]$ passwd Changing password for user test. Changing password for test (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模塊在系統安全管理策略和管理中的用途是非常重要和廣泛的。
pam_pwhistory.so模塊也是一個常用模塊,一般輔助pam_cracklib.so,pam_tally.so以及 pam_unix.so等模塊來加強用戶使用密碼的安全度。不過pam_pwhistory.so模塊起的是另一類的作用,即專門為用戶建立一個密碼歷史 檔案,防止用戶在一定時間內使用已經用過的密碼。
例如,當需要限定用戶在90天之內不能重復使用以前曾經使用過的10個密碼,那麼具體操作方法是去修改/etc/pam.d/system-auth文件,在password接口處增加:
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這個選項,修改之後的配置文件為:
password required pam_unix.so md5 remember=10 use_authtok
這樣系統將同樣記住10個已經使用的密碼。
具體情況請參考: http://www.deer-run.com/~hal/sysadmin/pam_unix.html
不過此時/etc/security/opasswd文件因為記錄了N個使用過的密碼,所以安全性就十分關鍵了,所以要確保該文件只能被root用戶讀取和編輯:
# touch /etc/security/opasswd # chown root:root /etc/security/opasswd # chmod 600 /etc/security/opasswd
pam_tally.so模塊也是在系統中經常使用的一個pam模塊。其主要作用是監控用戶的不成功登錄嘗試的次數,在達到模塊限制的次數時會鎖定用戶一段時間以防止一些黑客軟件的暴力破解。
pam_tally.so模塊的使用方法和剛才一樣,也是需要通過修改/etc/pam.d/system-auth來實現相關功能。
例如要實現這樣的功能:用戶登錄時候可以允許三次輸入錯誤密碼嘗試,如果三次密碼輸入都錯誤會鎖定用戶並且將其登錄行為記錄到/var/log/faillog文件(或者可以自定義日志文件)中。
具體的修改方法是將下面的這兩行分別加入auth和account部分:
auth required /lib/security/pam_tally.so onerr=fail no_magic_root account required /lib/security/pam_tally.so deny=3 no_magic_root reset另外在順序方面最好能夠將剛才的配置項放到sufficient之前,修改之後的全文如下:
[root@localhost log]# 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 /lib/security/$ISA/pam_env.so auth required /lib/security/pam_tally.so onerr=fail no_magic_root auth sufficient /lib/security/$ISA/pam_unix.so likeauth nullok auth required /lib/security/$ISA/pam_deny.so account required /lib/security/$ISA/pam_unix.so account required /lib/security/pam_tally.so deny=3 no_magic_root reset account sufficient /lib/security/$ISA/pam_succeed_if.so uid < 100 quiet account required /lib/security/$ISA/pam_permit.so password requisite /lib/security/$ISA/pam_cracklib.so retry=3 password sufficient /lib/security/$ISA/pam_unix.so nullok use_authtok md5 shadow password required /lib/security/$ISA/pam_deny.so session required /lib/security/$ISA/pam_limits.so session required /lib/security/$ISA/pam_unix.so
並且手工建立/var/log/faillog文件用以記錄多次嘗試登錄的用戶信息。
在測試的時候可以發現,如果用戶使用錯誤的密碼連續登錄三次,該賬號將被鎖定lock_time所定義的時間。如果用戶使用正確的密碼登錄,再退出 使用錯誤的密碼連續登錄三次,之後返回再次使用正確的密碼登錄也會出現authentication fail的錯誤提示,同時登錄的控制台被記錄到了/var/log/faillog文件中。
[root@localhost log]# strings faillog tty2 tty2
在剛才的例子中deny表示三次錯誤輸入密碼則認證失敗,reset表示一旦成功輸入密碼則允許。
pam_winbind.so模塊一般用於混和集中式認證環境的用戶認證中。所謂混合集中式認證一般指的是當在企業環境中擁有大量不同類型的操作系 統,例如不同數量的Windows,Linux,Unix服務器,此時通過一些配置方案,可以使用戶能夠通過一個賬戶口令登錄和訪問所有類型的操作系統。 典型的實現方式是使用Windows Server自帶的活動目錄來存放和管理用戶,而將所有的其它服務器和操作系統都加入到Windows的認證域中,這樣這些操作系統上的登錄用戶不光可以 支持本地的用戶登錄,還可以通過LDAP查找和支持目錄服務中的用戶登錄。
而Winbind就是應用於這種環境的典型方案之一。Winbind實際上是Samba軟件包的一款組件,在RHEL系統下被包含在了samba- common包中。Winbind在Linux上實現了對微軟產品通訊的RPC調用、可插拔驗證模塊和名字服務切換,通過Samba接口與Windows 域控制器獲得聯系,可以使Windows域用戶能在Linux主機上以Linux用戶身份方式進行操作。通過設定Linux服務器的name service switch配置可以讓系統通過Winbind程序來解析用戶信息。最終實現的效果就是可以使用Windows的活動目錄來集中存放用戶,這些用戶只要通 過活動目錄認證就可以同時在Windows服務器和Linux服務器上登錄以及使用相關的系統資源。
為了說明winbind組件和winbind.so模塊的用法,下面我們將介紹一個結合Windows Server 2008和RHEL 5實現的集中式認證環境的配置案例。Windows Server 2003通過自帶的活動目錄(Active Directory)充當目錄服務器,而RHEL 5會利用其自帶的Samba軟件包提供的winbind組件從活動目錄中獲取用戶和認證信息進行認證。
下面我們將開始正式進入實際操作部分。按照以往的慣例,在動手之前有必要介紹一下拓撲結構、目標和大致的操作步驟。
例如:我將構建一個叫做jerrywjl.com的域作為一個公司基本的管理單位,並且在該域中安裝了W2K8E的服務器將升級為域控制器和KDC 服務器,由於微軟活動目錄需要依靠DNS命名空間定位資源,所以升級域控制器的操作需要事先有DNS服務器的支持。考慮到升級過程中活動目錄會動態更新 DNS服務器的各種資源記錄,為了簡化配置的難度,我將域控制器和DNS服務器放置在同一台主機上。即需要在該服務器上事先建立DNS服務。
所有其它本網絡內的服務器都安裝RHEL5U2系統,並通過配置加入到這個域網絡環境中。由於硬件數量有限,所以服務器 server.jerrywjl.com同時充當文件服務器、郵件服務器以及FTP服務器。這個需求可以通過在DNS服務器上指派多個別名來實現。所有的 Linux服務器加入到Windows域內意味著對這些服務的訪問要通過活動目錄中的Kerberos認證,只有通過認證的域內用戶才可以訪問活動目錄之 內上述資源。
而其中比較特殊的是squid.jerrywjl.com是代理服務器,該服務器有兩個接口,是內部網絡用戶訪問外部的唯一合法出口。為了提高安全性,要求所有用戶在使用該代理服務器之前先通過基本認證核實域內用戶身份,通過認證的用戶才能使用代理服務器訪問外部網絡。
現在正式開始。
第一步操作:構建和配置Windows Server 2008 Enterprise Edition服務器,並將該服務器升級為域控制器。
W2K8E的安裝和以前版本有很大差異,首先在硬件方面,要求針對32bit版本至少要有512M內存和16G以上硬盤空間。在安裝系統完成之後首 次登錄會以administrator身份進行,但必須要修改administrator用戶的密碼並滿足包含字母、數字、特殊符號和最小七位的復雜度需 求。由於這一部分操作比較簡單,所以我就不花時間做過多介紹。在系統安裝完成之後需要進行基本的網絡配置。選擇“start”並點擊“network”之 後選擇“network and sharing center”然後是“manage network connections”開啟“local area connections”最後選擇“properties”,將IP地址修改為192.168.10.100,DNS地址指向本機,同時修改主機名為 w2k8e,采用的域名後綴為jerrywjl.com。方法是選擇“start”並右鍵點擊“computer”並選擇“properity”,在 “system”屬性中選擇“advanced system setting”,之後點擊“computer name”標簽並選擇“change”輸入新的主機名並選擇“more”來更改dns suffix。這一步操作在完成之後需要重啟系統以生效。
在系統重啟之後,點擊“start”選擇“cmd”並輸入“dcpromo”,該命令即將把本服務器升級為域控制器。點擊“next”之後點擊 “create a new domain in a new forest”,表示該域控制器將是整個域林的第一台域控制器。然後輸入要添加的域名jerrywjl.com並選擇下一步,在域的兼容模式中使用 windows server 2008。進入下一步是DNS服務器的配置,眾所周知升級活動目錄必須要在網絡中有DNS的支持,和W2K3E不同的是W2K8E將DNS的配置過程集成 到了域控制器的升級過程中,所以只需要聲明DNS服務器的地址,域控制器在升級完成之後也自動完成了DNS服務器的配置。確定之後將會彈出一個要求建立 DNS委派的對話框,可以一路確定繼續進行下去。
下面的接口就要求指定域控制器數據庫、日志和系統文件的位置,這裡都保持默認即可。在下面的步驟中將要指定一個還原模式的密碼,也就是說如果該服務 器從域控制器降級為普通服務器,需要輸入該密碼之後方可進行。到此為止,所有的信息都已經收集完成,下一步會給出一個信息匯總,之後點擊“Next”將開 始升級域控制器。在升級完成之後必須要按照要求重啟系統以使所有配置生效。重啟完成之後,系統的架構將發生重大改變,該服務器已經由一台普通的工作組中的 計算機提升為域控制器。原來的管理員administrator也由普通的工作組內管理員提升為集域、企業、架構管理員權限於一身的 administrator。在重啟完成之後,有幾個重要的標志用以確認該服務器的角色提升成功。如查看計算機名稱的時候將發現該計算機已經加入域內,並 且在“administrative tools”中看到增加了一些新的工具,如“Active Directory Users and Computers”和“Active Directory Site and Services”等。到此為止,在W2K8E上的域控制器升級的工作則順利完成。
在配置其它的Red Hat服務器之前,由於W2K8E也是DNS服務器,所以需要在該服務器上增加RHEL所有服務器的A(主機)記錄和CNAME(別名)記錄,這樣所有的 域內資源都可以域名的方式去訪問。具體的方法是在W2K8E上點擊“start”並點擊“run”在出現的命令行對話框中輸入“dnsmgmt.msc” 以開啟DNS管理配置工具。然後在jerrywjl.com下中的空白區域右鍵點擊並選擇“New Host(A or AAAA)”然後輸入相應主機名和IP地址,分別是server.jerrywjl.com和squid.jerrywjl.com,再為 server.jerrywjl.com建立別名ftp,mail。完成之後可以在命令行中執行nslookup進行解析測試,如果能夠正向解析到所有記 錄則表明DNS和各種資源記錄都沒有問題。另外,如果需要的話可以在DNS管理配置工具中建立反向區域和添加相應的PTR指針與CNAME記錄。
到此為止在W2K8E上的配置就暫時告一段落。下面開始配置第一台RHEL5U2服務器。 首先指定基本信息,包括指定本機的IP地址和DNS服務器地址,同時比較重要的是保證RHEL和W2K8E的系統時間吻合,因為在Kerberos的工作 流程中需要依靠時間戳來作為認證流程中的一個重要依據。所以我制定一個簡單的任務計劃使RHEL作為時間客戶端並每隔十分鐘到服務器同步並校正自己的時 鐘。
下面將要修改/etc/krb5.conf文件。如果Linux系統要配置通過Kerberos認證,/etc/krb5.conf文件十分重要。 該文件包含了所有的Kerberos的基本配置信息。其中所謂的realm也稱為Kerberos的認證領域,在大多數情況下Kerberos認證領域和 DNS解析到的域名空間一致,只不過在/etc/krb5.conf中Kerberos認證領域需要大寫,所以該檔修改之後的結果如下:
[logging] default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmind.log [libdefaults] default_realm = JERRYWJL.COM dns_lookup_realm = false dns_lookup_kdc = false ticket_lifetime = 24h forwardable = yes [realms] JERRYWJL.COM = { kdc = w2k8e.jerrywjl.com:88 admin_server = w2k8e.jerrywjl.com:749 default_domain = jerrywjl.com } [domain_realm] .jerrywjl.com = JERRYWJL.COM jerrywjl.com = JERRYWJL.COM [appdefaults] pam = { debug = false ticket_lifetime = 36000 renew_lifetime = 36000 forwardable = true krb4_convert = false }然後進入/etc/samba目錄下,備份保存原有配置文件smb.conf,然後修改該配置文件並加入新的內容。其中security = ads指定該服務器的驗證源為Windows 2003以上版本的域控制器,password server用於指定該域控制器的地址以及相應的Kerberos realm。
security = ads password server = 192.168.10.100 realm = JERRYWJL.COM
接著是指定使用Winbind服務所需要的信息。
在下面的Winbind配置信息中的“idmap uid”和“idmap gid”指定了一個用戶ID范圍。該ID范圍實際上是Winbind從Windows的活動目錄中獲取用戶信息之後該用戶和相應組在Linux系統的id 值映像范圍,“winbind enum users”和“winbind enum groups”表示是否通過winbind列舉活動目錄中的用戶和組。而“winbind separator”則用於指定映像的用戶或者是服務器名稱和Kerberos realm名稱之間所使用的連接符號,默認是\,如果改成+則表示通過Winbind獲得的用戶名稱格式是“DOMAIN + user”以及“DOMAIN + group”而“template homedir”,“template shell”表示通過winbind獲得的域用戶在Linux系統中登錄所使用的主目錄位置以及登錄shell,“winbind use default domain”表示用戶名稱將以何種方式被轉換或映射。所以我對Winbind部分的配置如下:
idmap uid = 100000-200000 idmap gid = 100000-300000 winbind enum groups = yes winbind enum users = yes winbind separator = + template homedir = /home/%D/%U template shell = /bin/bash winbind use default domain = no對該檔保存退出。然後還要修改一個關鍵的配置文件/etc/nsswitch.conf,將原有的:
passwd: files shadow: files group: files修改為:
passwd: files winbind shadow: files group: files winbind
表示該服務器在驗證用戶登錄的時候,如果用戶不在本地用戶數據庫中則會自動通過winbind來搜索windows活動目錄內的用戶數據庫。/etc/nsswitch.conf是NSS即Name Service Switch的配置文件。
保存之後可以重新啟動samba和winbind服務,並使這兩個服務在系統啟動的時候自動啟動。然後以Windows管理員administrator的身份執行kinit命令以從W2K8E上獲得Kerberos的TGT票據。方法是執行命令:
# kinit [email protected]
該命令執行成功沒有任何提示,但即說明了已經正常獲得了TGT票據。這裡比較常見的錯誤是會出現諸如“Clock skew too great while getting initial credentials”這樣的信息,最有可能的原因是當前系統和KDC服務器的時間差過大而導致獲取TGT票據失敗,因此需要檢查一下兩台主機的時鐘。
如果上述命令執行無誤,可以執行命令net ads join將RHEL加入到Windows域內。
# net ads join –U administrator加入成功之後要確保在當前系統上執行wbinfo –t無錯誤信息提示:
# wbinfo –t
命令wbinfo的功能是從winbind daemon中查詢所獲得的信息。而-t選項用於驗證當前的Linux服務器加入到Windows域內之後是否在域內建立了可信任的服務器賬號。如果有報錯信息的話,可能需要重啟一下winbind服務。
在正常完成上述操作之後,就可以通過wbinfo和getent命令獲得從Windows活動目錄上獲得的用戶與組的信息。所有獲得的域內用戶信息 都是以Kerberos realm name + username/groupname的格式出現。這就意味這以後在使用這些Windows帳戶登錄系統或者服務的時候也要使用該格式。而且在W2K8E 的組件“active directory users and computers”的computers中可以看到剛加入域的該服務器的信息。
最後為當前服務器增加Winbind作為的獲得域內資源和進行認證的方式之一。具體方法是在終端執行“setup”並選擇 “Authentication Configuration”並在“User info”和“Authentication”中都選擇使用Winbind,確認所有的信息之後進入下一步並點擊“OK”即可,在完成之後winbind 服務將會被自動重啟。這樣操作最終的結果是Windows中的管理員administrator可以JERRYWJL+administrator這個登 錄名在RHEL上登錄成功。
pam_mkhomedir.so模塊的主要作用是幫助用戶在登錄系統的時候自動創建家目錄,並且隨之生成該用戶的profile文件。所以該模塊 在實現一些混合集中式認證的場景中會非常有用。因為當這些來自目錄服務的用戶登錄成功之後,一般不會像本地用戶登錄那樣可以自動創建自己的家目錄。
所以來自目錄服務的用戶登錄之後所做的一切操作和配置都無法永久保存,除非管理員手動地給這些登錄用戶創建家目錄。不過目錄服務中的用戶的數量一般 都非常大,手工操作的工作量和准確率可想而知。所以在這種情況下就需要使用pam_mkhomedir.so模塊,當用戶登錄系統認證成功的時候,該模塊 會自動為用戶創建家目錄以及生成相關的profile文件。
我們可以結合上面的RHEL + Windows Server實現混和集中式認證的案例來繼續說明pam_mkhomedir.so模塊的用法。在上例中,當windows系統上的用戶 administrator成功地在RHEL上登錄之後,唯一的問題是沒有自己的主目錄。這個時候終於輪到pam_mkhomedir.so模塊出場了!
在這個方案中我們只需要簡單修改PAM和系統用戶登錄的相關配置文件/etc/pam.d/system-auth並增加一行session的控制信息如下:
session required pam_mkhomedir.so skel=/etc/skel umask=0022 silent
表示用戶登錄之後會利用pam_mkhomedir.so這個pam模塊自動建立自己的主目錄,並會從/etc/skel目錄下拷貝用戶原始配置文 件到所建立的目錄中,當然所有的操作都會在後台執行。這個更改是實時生效的,也就是說更改完成之後無需重啟任何服務,只要使用域內用戶重新登錄Linux 系統即可發現與這個用戶同名的主目錄就能夠自動建立在/home/JERRYWJL目錄下。這樣通過W2K8E活動目錄認證用戶訪問RHEL資源的基本架 構就已經搭建完成。
另外進行這個實驗的用戶應該可以發現,在當執行setup並選擇使用winbind結合活動目錄進行認證的時候,當完成這一步驟時系統會自動修改 /etc/pam.d/system-auth文件,並在其中添加一個新的配置項——即使用pam_winbind.so進行用戶驗證用戶,此模塊專用於 結合活動目錄進行用戶認證,並將獲取的信息轉換成Linux系統所能兼容的用戶信息格式,所以整個的配置文件將變成:
#%PAM-1.0 # This file is auto-generated. # User changes will be destroyed the next time authconfig is run. auth required /lib/security/$ISA/pam_env.so auth sufficient /lib/security/$ISA/pam_unix.so likeauth nullok auth sufficient /lib/security/$ISA/pam_winbind.so use_first_pass auth required /lib/security/$ISA/pam_deny.so account required /lib/security/$ISA/pam_unix.so broken_shadow account [default=bad success=ok user_unknown=ignore] /lib/security/$ISA/pam_winbind.so account required /lib/security/$ISA/pam_permit.so password required /lib/security/$ISA/pam_cracklib.so retry=3 type= password sufficient /lib/security/$ISA/pam_unix.so nullok use_authtok md5 shadow password sufficient /lib/security/$ISA/pam_winbind.so use_authtok password required /lib/security/$ISA/pam_deny.so session required /lib/security/$ISA/pam_limits.so session required /lib/security/$ISA/pam_unix.so session required pam_mkhomedir.so skel=/etc/skel umask=0022 silent
此時當用administrator登錄Linux系統的時候會發現其主目錄會自動建立。
其實結合RHEL + Windows Server進行集中式認證的實現方法不僅僅只有winbind一種手段。
使用Winbind的方法由於涉及到AD,Kerberos,Samba,Winbind這幾方面內容,因而在有些用戶看來配置過程似乎有些復雜。所以在 今天的內容中,我們將完全放棄使用Samba和Winbind而將RHEL系統配置為一個具有更出色兼容性的LDAP客戶端來實現類似的功能。
這種方案的原理實際上包括下面幾個內容:
首先我們將Windows AD作為網絡中的IDM系統,所有的用戶信息,包括用戶名,UID,口令,登錄shell、有效期等等按理說都會存儲在AD當中。
然後Linux系統會通過自身的應用程序編程接口和LDAP查詢工具集來和AD服務器通訊並訪問AD中的這些用戶信息。
這種訪問方式實際上應用到了Linux系統中的一個PAM模塊——pam_ldap。pam_ldap這個模塊類似於常見的 pam_unix.so。一般來說如果Linux本地用戶登錄系統時會使用的pam_unix.so,該模塊可以將用戶登錄時輸入的用戶名和密碼與系統本 地用戶數據庫/etc/passwd和/etc/shadow中所記錄的信息進行核對,如果驗證通過則允許登錄;而pam_ldap模塊的基本功能則是會 以AD上某個固定用戶的身份和口令連接到Windows DC上查詢AD數據庫(之所以要以一個固定用戶身份執行這個操作時因為默認情況下,Windows AD是不允許以匿名方式查詢和訪問的,所以這個固定用戶在AD上不但要確實存在,而且要具備足夠的權限),另外pam_ldap.so在查詢到AD中用戶 信息的同時也能對AD中加密的用戶口令進行正確轉換以實現身份認證,認證成功之後才允許用戶登錄或進行後續訪問。
除了pam_ldap.so模塊之外,Linux系統還提供了一個Open LDAP的工具集,其中最關鍵的工具和命令是ldapsearch,管理員通過手動執行該命令能夠從AD上獲得目錄內的信息。這對於在配置的過程中進行調試和排錯將相當有用。
當然在這個認證過程中為了保證密碼之類的敏感信息在網絡中傳遞的安全性,Linux客戶端要和基於Windows操作系統的Kerberos KDC進行安全通訊,這樣則必須要啟用另外一個PAM模塊——pam_krb5.so,它能夠使Linux客戶端以正確的實例從Kerberos KDC上獲取TGT(票據授權票據),並通過一個完整的Kerberos認證過程來實現用戶信息的安全傳遞。因為在默認情況下Windows的域控制器和 Kerberos的KDC是集成於一體的。
另外,當使用pam_ldap查詢到用戶信息時,還有一個非常關鍵的問題需要解決,這就是Windows AD中存儲的用戶信息和Linux Open LDAP所存儲的用戶信息格式和名稱是不統一的。如果大家曾經看過我以前介紹Open LDAP的文章則很容易建立這樣的概念:所有的LDAP服務器實際上基本上都在使用LDAP(輕量級目錄訪問協議),這個協議規定了LDAP中的所有信息 都必須有一個命名方式,而命名方式歸根結底是由架構檔,即schema所決定。由於歷史方面的問題,我們實在無法保證不同的目錄服務產品都是用統一的架構 檔,這就意味著很有可能在Windows AD的目錄服務器上添加的用戶的一些屬性雖然能夠被Linux系統的LDAP查詢工具和應用程序編程接口獲得,但無法通過NSS名字轉換服務轉換成用戶登 錄或者其它服務所需要的屬性。
舉一個簡單的例子:假如我們在Linux系統中添加一個本地用戶或者在Linux的Open LDAP中添加一個用戶,這個用戶如果要能夠登錄到Linux系統則必須包括用戶名、用戶ID(UID)、用戶家目錄、默認登錄Shell以及用戶口令等 基本信息。這樣當用戶登錄的時候,Linux系統的名稱服務(NSS)會將用戶轉換成UID來驗證用戶身份,驗證成功方可登錄。但是在Windows系統 中,顯然我們不能指望所添加的用戶具有和Linux系統上一樣的用戶屬性和信息,無法獲得這些信息將意味著無法登錄Linux系統。
所以這個時候我們不但要使用pam_ldap,還要使用一個叫做nss_ldap的應用程序擴展庫來實現將Windows AD用戶的架構所定義的一些屬性和Linux Open LDAP架構所定義的,用戶登錄必須的屬性進行一一映像。(實際上pam_ldap和nss_ldap分別是RHEL系統中一個叫做nss_ldap的安 裝包提供的pam模塊擴展和應用鏈接庫擴展,所以在RHEL系統中必須確保已經安裝了nss_ldap包。)而映射的方法也很簡單,因為nss_ldap 提供了一個配置文件/etc/ldap.conf,該檔可以根據需求更改。我們只需要按照其規定的格式指定兩種目錄產品的用戶屬性對應關系即可。
那麼這種對應包括:
將一些Windows AD的schema所定義的用戶屬性名稱映像為Linux Open LDAP schema所擁有的用戶屬性。例如在Linux的Open LDAP中UID對應Windows AD中的sAMAccountName,當然類似這樣的映射還有很多;
這也是比較大的問題:Linux Open LDAP的架構中規定的一些用戶屬性實際上在Windows AD上是根本不存在的,針對這個問題相信諸位已經想到了方法,就是通過一些特殊的方式來擴展Windows AD上的用戶屬性。
所以在Windows系統上實際上已經提供了一個這樣的工具,叫做SFU(Service For Unix)。該工具在W2K3E的R2版本上已經被加入到標准安裝光盤中。而在W2K3E的非R2版本上也可以通過手動安裝來實現其功能。這是一個在 Windows系統上專門對Unix系統訪問提供支持的組件。通過SFU可以將某些Windows操作系統集成到現有的UNIX環境中。它提供的組件可以 簡化跨UNIX和Windows平台的網絡管理和用戶管理。
SFU為Interix提供了一個完整的高性能的UNIX環境,這個環境包含諸如csh或ksh的UNIX shell、數百款工具和實用程序,以及一整套完整的開發工具和庫(通過它們可以在Interix子系統中連接並使用基於 UNIX 的應用程序)。而SFU具體功能包括:
與Unix相結合,可將Unix的執行和客戶機環境應用到Microsoft Windows主機上,反之亦然;
可用於訪問網絡文件系統(NFS)的服務和命令。這樣UNIX和Windows環境之間就可以共享檔;
可訪問UNIX和Windows系統上的帳戶和密碼服務(PCNFS、NIS以及LDAP)的用戶映像服務;
用於Windows和UNIX環境的“一次性注冊”功能,UNIX和Windows操作系統之間可以對密碼進行同步並映像認證證書;
在功能齊全的UNIX環境中的Windows計算機上執行UNIX shell腳本和應用程序的功能;
目前SFU比較成熟的版本是3.5。在W2K3E的AD安裝完成之後通過“添加/刪除程序”可以方便地安裝。所以有了SFU,我們可以擴展AD目錄信息的schema,以方便和Linux系統的集成。
下面我們將要開始配置和實現該環境。按照我們的慣例,在開工之前需要完整說明一下當前的實驗拓撲結構和操作目標:
我將在一台W2K3E R2的操作系統上部署AD的域控制器,並且安裝和部署SFU作為IDM服務器。該服務器的IP地址是192.168.10.10,全稱域名(FQDN) 為:winsrv.example.com。由於域控制器需要DNS服務支持,所以在該服務器升級為域控制器之前必須先安裝和配置Windows的DNS 管理器。另外有一台RHEL 5.2的操作系統,IP地址是192.168.10.20,該服務器將DNS指向Windows服務器,其FQDN 為:linsrv.example.com,這樣該服務器將獲得DNS支持。
要實現的目標是管理員在域控制器上添加用戶或組信息能夠在RHEL系統上查詢到。而且該用戶能夠在RHEL系統上登錄。
首先是在Windows服務器上構建DNS服務器與域控制器。注意:我這裡使用的是W2K3E的R2版本,該版本有兩張安裝光盤。在Windows系統上部署DNS和域控制器的方法這裡不再贅述。
在Windows的AD部署完成之後需要安裝SFU,在W2K3E的R2版本上,SFU是系統自帶的組件。可以通過在Windows系統中點擊 “Start”->“Run”並運行“appwiz.cpl”來開啟“Add/Remove Rrogram”,接著選取“Add/Remove Windows Components”,雙擊選取其中的“Active Directory Services”以及其子項“Identity Management for Unix”和該項中的所有子項,其中包括“Administration Components”,“Password Synchronization”和“Service for Unix”並最終選擇“OK”和“Next”以執行安裝,同時在安裝的過程中按照提示插入第二張光盤即可,由於要安裝的軟件比較大,所以安裝時間將比較 長,在安裝完成之後按要求重啟域控制器。
在域控制器重啟之後,需要驗證SFU是否成功安裝。點擊“Start”->“Administrative Tools”->“Microsoft Identity Management for Unix”,此時應該能夠成功開啟IDM的接口以及看到SFU,所以SFU實際上是Windows實現跨系統平台的IDM的組件之一。接著,需要開啟 “Active Directory Users and Computers”並選取其中任何一個OU中的用戶或者組並右鍵點擊“properties”,這時可以發現在它的屬性中多出一個叫做“UNIX Attributes”的用戶屬性,並包含了“NIS Domain”、“UID”等只有Linux系統上才有的一些用戶屬性。這樣即證明SFU已經安裝成功。
實際上在W2K3E R2的版本上安裝SFU最大的好處就是基本上不需要用戶進行任何手動的配置,所有SFU配置采用默認即可。但是其實會有很多用戶還在使用W2K3E的早期 版本,在這個版本上SFU並沒有作為一個默認的系統組件被加入,那麼則需要從微軟的官方網站去下載SFU的安裝包執行手動安裝和配置,這是一個200多 MB的自解壓安裝程序,文件名是SFU35SEL_EN.exe。雙擊運行之後會默認解壓到系統的c:\documents and settings\administrator\local settings\temp目錄中,進入該目錄執行setup.exe文件將看到SFU的手動安裝接口,點擊“Next”之後在“Username”和 “Organization”處輸入執行安裝的用戶和組織,這裡我用“administrator”和“example.com”,接受協議並點擊 “Next”,在新打開的接口上選擇“Standard Installation”並進入下一步。在出現的對話框中選擇“Enable suid behavior for Interix programs”和“Changing Default Behavior to Case Sensitivity”這兩個選項。
其中“Enable suid behavior for Interix programs”表示根據POSIX標准,在系統執行某文件時,該檔有權限包含用於設置UID(setuid)和GID(setgid)的位。如果某檔 中設置了任一個位或同時設置了這兩個位,則執行該檔時的進程可獲得它的UID或GID。如果使用得當,此機制允許非特權用戶執行那些只允許具有更高權限的 檔管理器擁有者或組運行的程序。但如果使用不當,由於此行為允許非特權用戶執行僅應由管理員來執行的操作,則因此可能帶來安全隱患。所以默認情況下 Windows Services for UNIX 安裝程序不啟用對此機制的支持。但為了後續獲得更好的兼容性,目前我們應該啟用對setuid行為的支持。因此勾選該選項。
另外一個選項“Changing Default Behavior to Case Sensitivity”表示系統要求用戶選擇是否將對象名稱(比如文件名)的默認行為更改為區分大小寫。這個選擇將影響到系統的安全性以及 Windows Services for UNIX的作用原理。因為對於Windows系統大多數對象(比如文件和目錄)的名稱都是保留大小寫、但不區分大小寫的。所以在同一目錄中不能同時存在名 稱為例如sample.txt和Sample.txt的兩個檔,原因是 Windows在識別檔時會將它們看作是同一檔。但是UNIX操作系統是完全區分大小寫的。所以對象名稱之間只要存在對象名稱字符大小寫的差異時UNIX 系統就可區分它們,這樣像sample.txt和 Sample.txt就可以出現在同一目錄中並且UNIX系統對這些文件執行操作時可以區分它們。例如執行命令rm S*.txt可以刪除Sample.txt,但不會刪除sample.txt。為實現典型的UNIX行為,Server for NFS和Interix子系統在處理名稱時一般都是區分大小寫的。
此行為可能會帶來安全問題,特別是對於已習慣Windows中不區分大小寫的用戶。例如黑客可能將木馬版本的edit.exe以EDIT.EXE的 名稱保存在與原始檔所處的同一目錄中。如果用戶在 Windows命令提示符下鍵入edit,則可能不執行標准版本、而是執行木馬版本的(EDIT.EXE)。在啟用區分大小寫功能之前,Windows用 戶應意識到這類問題。
對於Windows XP(專業版)和Windows Server 2003系列操作系統,除了Win32子系統以外,其它子系統的默認行為均保留大小寫但不區分大小寫。在先前版本的Windows中,這類子系統默認情況 下是完全區分大小寫的。為支持標准的UNIX行為,在安裝(用於安裝Interix 子系統的)基本實用程序或Server for NFS時,Windows Services for UNIX安裝程序允許您更改Windows XP和Windows Server 2003系列操作系統的非Win32子系統的默認行為。如果您啟用了區分大小寫的功能,但隨後又卸除了Server for NFS和基本實用程序,則Windows Services for UNIX安裝程序將恢復非Win32子系統的默認行為,即不區分大小寫。這裡仍然是選擇該選項。 之後的另一個接口是配置用戶名稱映像:
用戶名稱映像起單一clearinghouse的作用,它提供了集中的用戶映像服務。用戶名稱映像允許在Windows 與UNIX的用戶和組帳戶之間創建映射。
用戶名稱映像允許為整個企業維護單一的映像數據庫。此特性大大方便了為多個運行Windows Services for UNIX的計算機配置驗證的過程。除Windows與UNIX用戶和組帳戶之間一對一的映像之外,用戶名稱映像還允許創建一對多的映射,即可以將多個 Windows賬戶與一個UNIX賬戶關聯起來。此特性非常有用,舉例來講,它讓管理員可以不必為個別用戶維護多個分立的UNIX賬戶,而只使用少數幾個 賬戶提供不同類的訪問權限即可。管理員可以使用簡單映射,通過完全相同的名稱將Windows與UNIX賬戶映射起來。當然管理員也可以創建高級映射,通 過不同的名稱將Windows與UNIX賬戶關聯起來。可以將之與簡單映射配合使用。
但在我們的實驗中實際上和“Network Information Serivce(NIS)”沒有任何關系。所以點擊下一步之後不需要輸入任何“NIS Domain”和“NIS Server Name”再次點擊下一步之後完成SFU的安裝。在SFU安裝完成之後,同樣可以像在R2系統那樣通過“Administration Components”看到SFU的接口以及用戶屬性中的“UNIX Attributes”。然後重啟系統以完成整個安裝。最後在Windows的cmd接口中執行services.msc開啟服務管理器,並確保其中的 Server for Nis這個服務的“Start Type”為“Automatic”並且“Status”為“Started”。
下面開始進行RHEL5系統上的配置。
首先完成RHEL5基本環境的設置,包括配置IP地址,關閉和禁用防火牆以及SELinux,在/etc/resolv.conf中將DNS服務器 指向Windows服務器,並且調整系統時間盡量和Windows服務器一致。這裡值得一提的是,因為後續要使用到Kerberos認證,所以時間精確度 的要求實際上將非常高。
由於我在內網中沒有一個標准的事件源,所以此采用一種簡單的方法,即將Windows服務器作為NTP服務器,並且在RHEL系統上制定一個任務計 劃,使用ntpdate每隔一分鐘和Windows系統對時一次即可。另外要確保在RHEL系統中安裝以下軟件包,尤其是openldap- servers,nss-ldap這兩個包和一些Kerberos的相關包。所需要的包全部在安裝光盤中提供,openldap-servers、 openldap、nss_ldap、mozldap、php-ldap、openldap-clients、python-ldap、 openldap-devel以及krb5-devel、krb5-libs、pam_krb5、krb5-auth-dialog、krb5- workstation,掛載光盤切換到Server目錄下執行rpm -ihv進行安裝即可。 完成上述的幾個步驟,RHEL5操作系統的基本環境配置即告一段落。
現在開始配置RHEL5作為Windows的AD和Kerberos KDC的客戶端以及成員服務器,在終端執行命令“setup”並選擇其中的“Authentication Configuration”並運行,然後選擇“Use LDAP”,“Use Shadow Passwords”以及“Use Kerberos”並繼續,在出現的“LDAP Setting”中填入LDAP方面的設置信息並執行下一步進入“Kerberos Setting”,分別如圖設置Kerberos的“Realm”,“KDC”和“Admin Serer”。完成之後就可以退出該接口了。所有的設定實際上會寫入到配置文件/etc/krb5.conf檔中,該檔內容如下:
[logging] default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmind.log [libdefaults] default_realm = EXAMPLE.COM dns_lookup_realm = false dns_lookup_kdc = false ticket_lifetime = 24h forwardable = yes [realms] EXAMPLE.COM = { kdc = 192.168.10.10:88 admin_server = 192.168.10.10:749 default_domain = example.com } [domain_realm] .example.com = EXAMPLE.COM example.com = EXAMPLE.COM [appdefaults] pam = { debug = false ticket_lifetime = 36000 renew_lifetime = 36000 forwardable = true krb4_convert = false }在完成了Kerberos客戶端配置之後,執行kinit命令來從Windows的KDC上初始化TGT(票據授權票據)。Kerberos是一個非常復雜的安全協議,關於Kerberos的原理和工作流程,請參照上例,這裡就不再贅述。命令為:
# kinit [email protected]如果能夠初始化TGT成功則不會有任何提示,當然前提是兩台系統的時間必須要保證准確。同時要修改/etc/pam.d/system-auth,配置RHEL5系統使用pam_ldap接口從Windows的域控制器上查詢用戶信息,下面是我修改之後的信息:
#%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 sufficient pam_ldap.so use_first_pass auth sufficient pam_krb5.so use_first_pass auth required pam_deny.so account required pam_unix.so broken_shadow account sufficient pam_ldap.so account sufficient pam_succeed_if.so uid < 500 quiet account [default=bad success=ok user_unknown=ignore] pam_krb5.so account required pam_permit.so password requisite pam_cracklib.so try_first_pass retry=3 password sufficient pam_ldap.so use_authok password sufficient pam_unix.so md5 shadow nullok try_first_pass use_authtok password sufficient pam_krb5.so use_authtok password required pam_deny.so session optional pam_keyinit.so revoke session required pam_limits.so session sufficient pam_mkhomedir.so skell=/etc/skell session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid session required pam_unix.so session optional pam_krb5.so在這個檔中實際上增加了下面的四行,這裡所增加的內容表示只要在LDAP服務器中確定該用戶合法身份以及驗證密碼無誤之後則允許登錄系統,並且允許登錄時自動創建該用戶的主目錄。不難看出,實際上這步操作是在為用Windows AD用戶直接登錄RHEL系統做准備。
auth sufficient pam_ldap.so use_first_pass account sufficient pam_ldap.so password sufficient pam_ldap.so use_authok session sufficient pam_mkhomedir.so skell=/etc/skell
而且除了pam_ldap.so模塊之外,我們還將發現通過Kerberos進行認證的部分實際上調用了另外一個pam模塊 pam_krb5.so。Kerberos進行票據驗證的細節將主要通過該模塊來進行。所以這個模塊的被自動添加到system-auth文件中,從很大 程度上屏蔽了認證實現的復雜度。
下面就到了最重要的一個步驟:如果要將RHEL作為Windows域控制器的成員服務器或者客戶端並且要確保從Windows AD上獲得的用戶信息可以在Linux系統上登錄,就必須要修改/etc/ldap.conf,該檔是由nss_ldap包所提供。該文件中首先會指定 LDAP服務器的ip地址、主機名等基本信息,然後會指定將以LDAP Server中的哪個用戶的身份和口令綁定到LDAP服務器上執行搜索和查詢(Windows域控制器默認情況下不允許執行匿名搜索),另外也指定了該用 戶在LDAP服務器上能夠搜索和查詢的范圍,最後也是最關鍵的,就是在該檔中將設置從LDAP服務器上獲取的用戶屬性和Linux系統上用戶屬性的映像關 系和映像圖。
前面曾經講到,由於兩種目錄服務的命名架構不同,Windows AD上可登錄的用戶信息屬性與類型和Linux上用於登錄的用戶信息屬性與類型存在很大的不同,而且關鍵是Linux系統上用於登錄的用戶信息屬性與類型 在Windows AD上絕大部分是默認不存在的。那麼之所以安裝SFU是基於這需求擴展了Windows AD上的架構,實際上則增加了用戶信息屬性與類型,但是擴展之後屬性與類型的名稱和Linux系統上的仍然有所不同,這個時候就需要在該檔中按照格式進行 手工的映像了。
修改/etc/ldap.conf檔,像剛才解釋的那樣,首先確定使用Windows AD上的哪一個用戶和密碼登錄Windows域進行搜索,所以在該文件中增加下面的信息:
base dc=example,dc=com binddn cn=administrator,cn=Users,dc=example,dc=com bindpw redhat
顯而易見,這裡我使用的是Windows AD上的系統管理員administrator和對應的密碼redhat,該用戶毋庸置疑在Windows系統以及域環境中已經具備了足夠的權限。而搜索的范圍自然也是整個的example.com這個域。
之後定義該用戶所在LDAP服務器,在這裡當然是Windows的域控制器,添加:
uri ldap://192.168.10.10/最後也是最關鍵的配置部分是手工定義我剛才提到的這些映射關系,添加下面的這些配置信息:
host winsrv.example.com nss_base_passwd cn=Users,dc=example,dc=com?one nss_base_shadow cn=Users,dc=example,dc=com?one nss_base_group cn=Group,dc=example,dc=com?one nss_map_objectclass posixAccount User nss_map_objectclass shadowAccount User nss_map_objectclass posixGroup Group nss_map_attribute uid sAMAccountName nss_map_attribute cn sAMAccountName nss_map_attribute homeDirectory unixHomeDirectory nss_map_attribute shadowLastChange pwdLastSet nss_map_attribute uniqueMember member nss_map_attribute gecos cn pam_login_attribute sAMAccountName pam_filter objectclass=User nss_base_passwd cn=Users,dc=winsrv,dc=example,dc=com pam_password ad上面的信息實際上就是一組標准的NSS信息的映像關系。其中:
host winsrv.example.com用於指定LDAP服務器的主機名或者FQDN; nss_base_passwd cn=Users,dc=example,dc=com?one nss_base_shadow cn=Users,dc=example,dc=com?one nss_base_group cn=Group,dc=example,dc=com?one
表示客戶端會根據/etc/nsswitch.conf文件中所定義的搜索順序,到cn=Users,dc=example,dc=com這個范圍 中搜索相應的用戶、組以及密碼信息。這裡的dc=com?one我認為應該是一個滿足格式兼容所需要做的一個轉換而已。而剩下的這一堆結構如 “nss_map_objectclass A B”和“nss_map_attribute A B”這一類的信息相信大家已經能夠猜到。實際上是Windows AD和Linux LDAP中的用戶屬性對應關系,其中A表示的是Linux系統中的用戶屬性名稱,而B表示在Windows中的用戶屬性名稱。例如在Linux的LDAP 服務器上,每添加一個用戶,它都需要有一個叫做“homeDirectory”的屬性並且建立相應的主目錄以滿足登錄需求,而如果在Windows的AD 上,則可能通過安裝SFU擴展出一個叫做unixHomeDirectory的屬性,其作用和Linux LDAP的homeDirectory屬性是大致一樣的,只不過叫法不同而已。但名稱不同則必須要在/etc/ldap.conf中明確指定,這樣 Linux系統上的名稱服務才能夠正確翻譯來自Windows AD的用戶屬性。而只有正確翻譯了這些相關的用戶屬性,Windows AD上的用戶才可以在RHEL上登錄。剩下的如pam_filter objectclass=Use,表示PAM模塊只會對user這個對象類型執行相關操作,而pam_password ad表示如果pam_ldap.so模塊對用戶密碼進行轉換和識別,將使用AD的相關協議來進行。
為了更好地理解這個難點,我們完全可以使用另外一種方法來嘗試直接從Windows的域控制器上獲得AD中的用戶信息,看看Windows AD域的用戶都有哪些自己認為標准的屬性和類型。這裡將以windows上的administrator用戶身份來直接搜索Windows AD目錄,使用的就是上面提到的ldapsearch命令,這是Open LDAP工具集中的命令之一。
執行下面的命令:
ldapsearch -x -b "dc=example,dc=com" -D "cn=administrator,cn=users,dc=example,dc=com" -w "redhat" -h 192.168.10.10 | grep Administrator從輸出的Windows用戶屬性和類型信息中,大家應該能夠理解這種對應關系的作用以及我們剛才的做法了。
# Administrator, Users, example.com dn: CN=Administrator,CN=Users,DC=example,DC=com cn: Administrator distinguishedName: CN=Administrator,CN=Users,DC=example,DC=com memberOf: CN=Administrators,CN=Builtin,DC=example,DC=com name: Administrator sAMAccountName: Administrator uid: Administrator msSFU30Name: Administrator unixHomeDirectory: /home/Administrator
最後我們來看一下,如何在Windows的AD上添加用戶並使該用戶可以在Linux系統中看到和直接登錄。
在執行這個操作前,還是首先使用administrator用戶進行一個測試,即只為Windows中的administrator用戶添加 Unix屬性。在Windows域控制器上選擇“Start”->“Administrative Tools”->“Active Directory Users and Computers”,然後右鍵選擇用戶“Administrator”點擊“Properties”並切換到“UNIX Attribute”,在該標簽中定義“NIS Domain”,“UID”(可以自行指定),“Login Shell”,“Home Directory”,最後一定要指定一個“Primary Group Name”(往往和UID一致),並選擇“Apply”。這樣即定義了該Windows用戶的Unix屬性。
而此時在RHEL系統上,可以立刻執行命令getent passwd命令,如果一切順利,如圖所示我們將看到Windows系統上的用戶Administrator用戶,由於用戶的信息只要滿足登錄需求就能被 getent所顯示出來,所以如果直接用該用戶登錄RHEL系統也能夠成功!
既然這樣,如果在Windows的“Active Directory Users and Computers”中選擇“example.com”的“users”容器,並添加兩個用戶tuser1和tuser2,並像剛才那樣定義好“UNIX Attribute”之後,在RHEL上一樣可以看到該用戶信息並且甚至可以直接登錄系統成功。
盡管實驗到此算是實現了我們需要的結果,不過不知道各位讀者是否看出一些問題?對了!相信大家已經發現,在/etc/ldap.conf所定義的所 有映像關系中似乎並沒有見到什麼通過安裝SFU所擴展出來的特殊屬性。這個問題實際上是因為在W2K3E的R2版本中已經整合了SFU,所以SFU的架構 或者擴展屬性已經加入到Windows AD的默認LDAP架構和屬性中,故並不需要在/etc/ldap.conf中再進行額外的指定。但目前仍然有很多用戶在使用W2K3E的非R2版本,並 且要像我上面所提到的那樣下載和完全手動安裝SFU,這樣通過SFU獲得的擴展架構和屬性就不是Windows AD的默認架構和屬性,於是這樣就需要在/etc/ldap.conf中去手動定義這些屬性和Linux LDAP的屬性相對應。因此,如果各位在使用W2K3E的非R2版本,那麼在/etc/ldap.conf文件的目錄屬性映像應該更改為下面的樣子:
nss_base_passwd cn=Users,dc=example,dc=com?one nss_base_shadow cn=Users,dc=example,dc=com?one nss_base_group cn=Group,dc=example,dc=com?one nss_map_objectclass posixAccount User nss_map_objectclass shadowAccount User nss_map_objectclass posixGroup Group nss_map_attribute uid sAMAccountName nss_map_attribute uidNumber msSFU30uidNumber nss_map_attribute gidNumber msSFU30gidNumber nss_map_attribute cn sAMAccountName nss_map_attribute uniqueMember member nss_map_attribute homeDirectory msSFU30homeDirectory nss_map_attribute loginShell msSFU30LoginShell nss_map_attribute gecos cn pam_login_attribute sAMAccountName pam_filter objectclass=User nss_base_passwd cn=Users,dc=winsrv,dc=example,dc=com pam_password ad
這樣在W2K3E的非R2版本中通過上述操作也一樣可以在Linux中看到所有的Windows目錄中的用戶信息和組信息。
通過以上幾篇文章對PAM的基本概念,工作原理和十幾個常用模塊的在實際應用環境當中的舉例講解,相信大家對可插拔認證模塊已經有了一定的了解和認 識。 由於時間和篇幅的關系,本人不可能將所有模塊的用法都一一舉例,所以希望對此有興趣的朋友通過充分的實驗來充分掌握其原理與細節,並通過活學活用PAM來 實現系統安全的有效增強。