第一部分 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.coms 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.coms 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.coms 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.coms 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.coms 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.coms 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中心数据库上存储。这样才能保证用户取得票据以后能顺利登陆服务器。