FreeBSDKerberos
第一部分 Kerberos 協議介紹
1.Kerberos 協議簡介
在希臘神話中,Kerberos是守護地獄之門的三頭狗。在電腦世界裡,美國麻省理工學院(MIT)把他們開發的這一網路認證系統命名為Kerberos。 Kerberos認證協議是由美國麻省理工學院(MIT)在80年代首先提出並實現的,是該校Athena計劃的一部分。因為Kerberos是一個三方認證協議,根據稱為密匙分配中心(KDC)的第三方服務中心來驗證網路中電腦相互的身份,並建立密匙以保證電腦間安全連線。Kerberos協議基本上是可行的並且有效。KDC有兩個部分組成:證明伺服器AS和票據授權伺服器TGS。Kerberos是一種網路認證協議,允許一台電腦通過交換加密訊息在整個非安全網路上與另一台電腦互相證明身份。一旦身份得到驗證,Kerberos協議將會給這兩台電腦提供密匙,以進行安全通訊對話。Kerberos協議可以認證試圖等錄上網使用者的身份,並通過使用密匙密碼為使用者間的通訊加密。總的來說,Kerberos 是一種基於私密金鑰密碼編譯演算法的,需要可信任的第三方作為證明伺服器的網路認證系統。它允許在網路上通訊的實體互相證明彼此的身份,並且能夠阻止旁聽和重放等手段的攻擊。不僅如此,它還能夠提供對通訊資料保密性和完整性的保護。
Kerberos從提出到今天,共經曆了五個版本的發展。其中版本1到版本3主要由該校內部使用。當它發展到版本4的時候,已經取得了在MIT校園外的廣泛認同和應用。由於版本4的傳播,人們逐漸發現了它的一些局限性和缺點(例如適用網路環境有限, 加密過程存在冗餘等等).MIT充分吸收了這些意見,對版本4進行了修改和擴充,形成了今天非常完善的版本5。現在可以MIT提供的Kerberos V5的最新實現是版本krb5 1.3.3,本文中提到的實現都是以它為依據的。
2.Kerberos協議術語解釋
Principal:在Kerberos中,Principal是參加認證的基底實體。一般來說有兩種,一種用來表示Kerberos資料庫中的使用者,另一種用來代表某一特定主機,也就是說Principal是用來表示用戶端和服務端身份的實體, Principal的格式採用ASN.1標準,即Abstract Syntax Notation One,來準確定義),Principal是由三個部分組成:名字(name),執行個體(instance),REALM(域)。比如一個標準的Kerberos的使用者是:name/instance@REALM 。
Name:第一部分。在代表客戶方的情況,它是一個使用者名稱;在代表主機的情況,它是寫成host。
Instance:第二部分。對name的進一步描述,例如name所在的主機名稱或name的類型等,可省略。它與第一部分之間用‘ / ’分隔,但是作為主機的描述時寫成host/Instance。
Realm:第三部分。是Kerberos在管理上的劃分,在 KDC中所負責的一個域資料庫稱作為Realm。這個資料庫中存放有該網路範圍內的所有Principal和它們的密鑰,資料庫的內容被Kerberos的證明伺服器AS和票據授權伺服器TGS所使用。Realm通常是永遠是大寫的字元,並且在大多數Kerberos系統的配置中,一般Realm和該網路環境的DNS域是一致的。與第二部分之間用‘@’分隔,預設為本地的Realm。
比如,Principal “ cnhawk/hawk.the9.com@THE9.COM ” 表示Realm “ THE9.COM ”中主機hawk.the9.com上的使用者cnhawk ,而Principal “ host/hawk.the9.com @THE9.COM ” 則通常用來表示Realm “ THE9.COM”中主機hawk.the9.com。
Credential: Ticket和與它相聯絡的工作階段金鑰合在一起稱為Credential。之所以有這個概念是因為它們是用戶端在向伺服器證明自己的身份時必需的兩樣東西.在一個Ticket的生存期內用戶端會將這兩樣東西以Credential為單位儲存在一個Cache檔案中。
Ticket: 一個Ticket是一個用於安全的傳遞使用者身份所需要的資訊的集合。它不僅包含該使用者的身份,而且包含其它一些相關的資訊。一般來說,它主要包括客戶方Principal,目的服務方Principal,客戶方IP地址,時間戳記(分發該Ticket的時間),該Ticket的生存期,以及工作階段金鑰等內容。它的格式亦用ASN.1來準確定義。
Authenticator: 在用戶端向服務端進行認證時,伴隨Ticket一起發送的另外一個部分,它的作用是證明發送Ticket 的使用者就是擁有Ticket的使用者,即防止重放攻擊。它的主要內容是一個時間戳記(用戶端發送Ticket的時間),在rfc1510中有它的完整的ASN.1定義。
AS(Authentication Server): 為使用者分發TGT(Ticket Granting Ticket)的伺服器。
TGT(Ticket Granting Ticket): 使用者向TGS(Ticket Granting Server)證明自己身份的Ticket.
TGS(Ticket Granting Server): 為使用者分發到最終目的Ticket的伺服器,使用者使用這個Ticket向自己要求提供服務的伺服器證明自己的身份。在實現上,AS和TGS實際上是由同一程式完成的,因為它們的實現機制並沒有太大的差別,只是在加密所發出的Ticket時所使用的密鑰不同(AS使用使用者的密鑰,而TGS使用工作階段金鑰)。
KDC(Key Distribution Center):密鑰發放中心,通常將AS和TGS統稱為KDC,有時也把AS 單獨稱為KDC。
3.認證過程
1) Client → KDC:使用者cnhawk向密鑰分配中心(KDC)申請TGT;
2) KDC → Client:通過KDC的使用者密碼認證,cnhawk得到KDC發放的TGT;
3) Client → KDC:申請取得使用者cnhawk所需要的host/s;
4) KDC → Client:KDC根據使用者cnhawk提供的TGT,KDC向cnhawk發放host/s;
5) Client → Server:使用者cnhawk向Server提供cnhawk,TGT和host/s ;Server根據主機的上儲存的host/s和使用者cnhawk的資訊來驗證cnhawk的登陸申請。
6) Server → Client:Server確認,發送資訊給Client允許cnhawk登陸Server。
4.一個應用執行個體
為了更清楚的說明Kerberos 5認證協議,實際應用中的例子(具體例子可以在我們後邊的實際應用中看到):假設某一區域網路A,它的DNS域為the9.com;Realm為THE9.COM;Kerberos的資料庫,AS以及TGS伺服器都在主機test1.the9.com上。A中主機test2.the9.com上的使用者cnhawk對應的Principal為cnhawk/test2.the9.com@THE9.COM;A中的另一台主機test3.the9.com上的telnet伺服器對應的Principal為host/test3.the9.com@THE9.COM。Rlogin的用戶端程式telnet和服務端程式telnetd都是支援Kerberos的,即都支援Kerberos認證協議。cnhawk想用telnet遠程登入到A中的另一台主機test3.the9.com上這時cnhawk所要完成的步驟是:
① 運行kinit程式。kinit程式的作用是向AS申請TGT,並將獲得的TGT和工作階段金鑰放在儲存Credential的檔案中。為此,cnhawk在命令列上鍵入:
% kinit cnhawk/test1.the9.com
kinit程式在收到AS發回的訊息後,就提示cnhawk輸入password:
% kinit cnhawk/test1.the9.com
cnhawk/test1.the9.com@THE9.COM's Password:
在cnhawk正確的輸入password後,kinit程式將這個password用約定的演算法轉化為cnhawk的密鑰,並用這個密鑰解密從TGS發回的訊息,從而獲得下一步使用的Credential。到此,kinit程式結束。由此可見,cnhawk的password並沒有在網上傳輸,在網上傳輸的只是由cnhawk的祕密金鑰加密後的東西。
② 運行telnet的用戶端程式telnet,為此cnhawk在命令列上鍵入:
test1# telnet -a -l cnhawk test3.the9.com
telnet程式首先在儲存Credential的檔案中尋找未到期的TGT,並把它交給TGS,從而獲得訪問test3.the9.com上rlogin服務的Ticket。接下來,它把這個Ticket和Authenticator一起發送給test3.the9.com的伺服器程式telnetd。telnetd在驗證了cnhawk的身份後,就搜尋本地cnhawk主目錄下的檔案“.k5login”,在“.k5login”檔案中放有允許用rlogin遠程登入到cnhawk帳戶下的Principal。在找到了cnhawk/test1.the9.com@THE9.COM之後,telnetd就申請一個虛擬終端,並fork一個shell,這時在test1.the9.com的終端上就會顯示:
test1# telnet -a -l cnhawk test3.the9.com
Trying test3.the9.com...
Connected to test3.the9.com.
Escape character is '^]'.
[ Trying mutual KERBEROS5 (host/test3.the9.com@THE9.COM)... ]
[ Kerberos V5 accepts you as `` cnhawk/test1.the9.com@THE9.COM' ]
FreeBSD/i386 (test3.the9.com) (ttyp1)
%id
uid=1001(cnhawk) gid=0(wheel) groups=0(wheel)
第二部分 Kerberos 5安裝和應用
1.系統安裝
需要安裝兩台FreeBSD 5.2.1的系統,一台FreeBSD 4.9 三個系統我是用虛擬機器上安裝的。
測試機A
作業系統:FreeBSD test1.the9.com 5.2.1-RELEASE FreeBSD 5.2.1-RELEASE #0: Mon Feb 23 20:45:55 GMT 2004 root@wv1u.btc.adaptec.com:/usr/obj/usr/src/sys/GENERIC i386
IP地址:192.168.0.2
機器名:test1.the9.com
測試機B
作業系統:FreeBSD test2.the9.com 4.9-RELEASE FreeBSD 4.9-RELEASE #0: Mon Oct 27 17:51:09 GMT 2003 root@freebsd-stable.sentex.ca:/usr/obj/usr/src/sys/GENERIC i386
IP地址:192.168.0.3
機器名:test2.the9.com
測試機C :
作業系統:FreeBSD test3.the9.com 5.2.1-RELEASE FreeBSD 5.2.1-RELEASE #0: Mon Feb 23 20:45:55 GMT 2004 root@wv1u.btc.adaptec.com:/usr/obj/usr/src/sys/GENERIC i386
IP地址:192.168.0.4
機器名:test3.the9.com
2.Kerberos 5軟體安裝和配置
Kerberos 5直接在ports中安裝就好了,最新版本為krb5-1.3.1_1。
在測試機A上安裝
Test1# cd /usr/ports/security/krb5/
Test1# make && make install
測試機B上安裝FreeBSD 4.9 在安裝的時候就選擇krb5
在B上安裝DNS
Test2# cd /usr/ports/dns/bind9
Test2# make && make install
在測試機C上安裝
Test3# cd /usr/ports/security/krb5/
Test3# make && make install
我們的選擇測試機A為KDC伺服器,測試機B為用戶端。
好我們現在登陸測試機A,在/etc/rc.conf裡添加上以下兩條
kerberos5_server_enable="YES"
kadmind5_server_enable="YES"
這樣伺服器下次重新啟動以後就可以直接啟動kerberos5服務了,然後建立/etc/krb5.conf,加上以下的內容;
[libdefaults]
default_realm = THE9.COM
[realms]
THE9.COM = {
kdc = test1.the9.com
admin_server = test1.the9.com
default_domain = the9.com
}
[domain_realm]
.the9.com = THE9.COM
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
因為Kerberos需要互相解析網域名稱,設定DNS,能夠互相解析地址。
登陸測試機B,
將測試機A上的/etc/krb5.conf拷貝到測試機B和測試機C上;
3.Kerberos 5的調試和部署
同時reboot掉兩個系統,機器啟動完成以後需要同步兩台伺服器的時間,時間對Kerberos 來說非常重要,Kerberos預設允許的時間位移量很小,如果兩台伺服器的時間差超過了Kerberos 允許值,就無法從KDC伺服器上取得票據。我寫了指令碼定時去時間伺服器上來同步時間。時間完成以後開始在測試機A上操作;
Test1# kstash
Master key: hawk
Verifying password - Master key: hawk
Test1# kadmin -l
kadmin> init THE9.COM //添加預設的網域名稱應該和krb5.conf裡保持一致
Realm max ticket life [unlimited]:
kadmin> add cnhawk/test1.the9.com //直接輸入使用者名稱/後面說明這個是哪個主機的使用者,登陸時候使用cnhawk/test1.the9.com@THE9.CON
Max ticket life [unlimited]:
Max renewable life [unlimited]:
Attributes []:
Password: hawk
Verifying password - Password: hawk
kadmin> exit
hawk#
使用者添加完成以後進行本地測試。
hawk# kinit cnhawk/test1.the9.com@THE9.COM
cnhawk/test1.the9.com@THE9.COM's Password:
hawk# klist -f
Credentials cache: FILE:/tmp/krb5cc_0
Principal: cnhawk/test1.the9.com@THE9.COM
Issued Expires Flags Principal
Jun 7 17:12:21 Jun 8 03:12:21 I krbtgt/THE9.COM@THE9.COM
我們可以看到本地已經拿到票據了。
下面添加測試機B的網域名稱地址資訊,就是允許測試機B能登陸測試機A。 特別注意Kerberos必須使用網域名稱來訪問機器。如果使用IP添加主機會出現一些意外的問題。
test1# kadmin -l
kadmin> add --random-key host/test1.the9.com //說明添加的是主機不是使用者
Max ticket life [1 day]:
Max renewable life [1 week]:
Principal expiration time [never]:
Password expiration time [never]:
Attributes []:
kadmin> ext host/test1.the9.com
kadmin> ext --keytab=/tmp/the9.keytab host/test1.the9.com
這樣完成以後就好了,基本配置已經結束了,可以使用。
調試
我們開始使用Kerberos的認證部署網路服務,注意Kerberos通過修改使用者主目錄下的.klogin和.k5login檔案,將你允許登陸的使用者Principal添加在檔案裡就好了。
test1# cat .k5login
# $FreeBSD: src/etc/root/dot.k5login,v 1.1 2003/04/30 20:58:49 markm Exp $
#
# user1/root@YOUR.REALM.WHEREVER
# user2/root@YOUR.REALM.WHEREVER
cnhawk/test1.the9.com@THE9.COM
這樣就可以了
使用Kerberos認證的telnet
修改/etc/inetd.conf 添加
telnet stream tcp nowait root /usr/libexec/telnetd telnetd -a user
然後開啟
test2# inetd
然後從test1登陸test2
test1# kinit cnhawk/test1.the9.com //先取得票據
cnhawk/test1.the9.com@THE9.COM's Password:
test1# klist –f //看看是不是取得
Credentials cache: FILE:/tmp/krb5cc_0
Principal: cnhawk/test1.the9.com@THE9.COM
Issued Expires Flags Principal
Jun 11 16:21:36 Jun 12 02:21:36 I krbtgt/THE9.COM@THE9.COM
//可以了
test1# telnet -a -l the9 192.168.0.3 //開始登陸
Trying 192.168.0.3...
Connected to test2.the9.com.
Escape character is '^]'.
[ Trying mutual KERBEROS5 (host/test2.the9.com@THE9.COM)... ]
[ Kerberos V5 accepts you as `` cnhawk/test1.the9.com@THE9.COM' ]
FreeBSD/i386 (test2.the9.com) (ttyp1)
//登陸歡迎詞
%id
uid=1001(the9) gid=0(wheel) groups=0(wheel)
% //好了成功了
使用Kerberos認證的ssh
修改測試A,B,C的sshd 設定檔。
# Kerberos options
KerberosAuthentication yes
KerberosOrLocalPasswd yes
然後重啟sshd
Test2#kill –HUP 80
開始從test1登陸到test2,因為只有ssh1支援Kerberos,所以使用ssh1串連同時開啟debug資訊。
test1# ssh -1v the9@test2.the9.com
OpenSSH_3.6.1p1 FreeBSD-20030924, SSH protocols 1.5/2.0, OpenSSL 0x0090703f
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Rhosts Authentication disabled, originating port will not be trusted.
debug1: Connecting to test2.the9.com [192.168.0.3] port 22.
debug1: Connection established.
debug1: identity file /root/.ssh/identity type -1
debug1: Remote protocol version 1.99, remote software version OpenSSH_3.5p1 FreeBSD-20030924
debug1: match: OpenSSH_3.5p1 FreeBSD-20030924 pat OpenSSH*
debug1: Local version string SSH-1.5-OpenSSH_3.6.1p1 FreeBSD-20030924
debug1: Waiting for server public key.
debug1: Received server public key (768 bits) and host key (1024 bits).
debug1: Host 'test2.the9.com' is known and matches the RSA1 host key.
debug1: Found key in /root/.ssh/known_hosts:3
debug1: Encryption type: 3des
debug1: Sent encrypted session key.
debug1: Installing crc compensation attack detector.
debug1: Received encrypted confirmation.
debug1: Trying Kerberos v5 authentication.
debug1: Kerberos v5 authentication accepted.
debug1: Requesting pty.
debug1: Requesting shell.
debug1: Entering interactive session.
Last login: Fri Jun 11 16:31:14 2004 from test1.the9.com
Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
The Regents of the University of California. All rights reserved.
FreeBSD 4.9-RELEASE (GENERIC) #0: Mon Oct 27 17:51:09 GMT 2003
FreeBSD/i386 (test2.the9.com) (ttyp1)
//登陸歡迎詞
%id
uid=1001(the9) gid=0(wheel) groups=0(wheel)
% //好了成功了
測試已經完成了。可以使用Kerberos了。
ftp 服務
%kinit cnhawk/test1.the9.com
Cnhawk/test1.the9.com @THE9.COM's Password:
%klist -f
Credentials cache: FILE:/tmp/krb5cc_1001
Principal: cnhawk/test1.the9.com@THE9.COM
Issued Expires Flags Principal
Jun 11 18:49:56 Jun 12 04:49:56 I krbtgt/THE9.COM@THE9.COM
%/usr/local/bin/ftp -v hawk.the9.com
Connected to hawk.the9.com.
220 hawk.the9.com FTP server (Version 5.60) ready.
334 Using authentication type GSSAPI; ADAT must follow
GSSAPI accepted as authentication type
GSSAPI authentication succeeded
Name (hawk.the9.com:cnhawk):
232 GSSAPI user cnhawk@THE9.COM is authorized as cnhawk
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>
好了FTP也可以接受登陸
總結
Kerberos使用中需要注意一些地方,例如,時間一定要保證同步,因為Kerberos靠時間戳記來保持同步,時間允許的飄溢量非常小。所以必須保證時間的準確。
cnhawk# kinit cnhawk/test1.the9.com@THE9.COM
cnhawk/test1.the9.com@THE9.COM's Password:
kinit: krb5_get_init_creds: time skew (314) larger than max (300)
cnhawk# ntpdate time.the9.com
7 Jun 16:59:49 ntpdate[623]: step time server 61.129.93.5 offset 211.348035 sec
cnhawk# kinit cnhawk/test1.the9.com @THE9.COM
cnhawk/test1.the9.com@THE9.COM's Password:
而且很多時候在登陸前要查看票據是不是到期了。
hawk# klist
Credentials cache: FILE:/tmp/krb5cc_0
Principal: cnhawk/test1.the9.com@THE9.COM
Issued Expires Principal
Jun 7 17:19:25 >>>Expired<<< krbtgt/THE9.COM@THE9.COM
Jun 7 17:20:23 >>>Expired<<< host/cnhawk.the9.com@THE9.COM
同時要注意認證時候不只是認證使用者資訊,還有主機資訊,要保證這兩個資訊都在KDC中樞資料庫上儲存。這樣才能保證使用者取得票據以後能順利登陸伺服器。