Part 1: Keberos 介绍
在计算机科学领域,Kerberos 是麻省理工学院Athena 项目的一部分。它之所以被命名为 Kerberos,是因为它涉及三个实体,很像三头狗,它们通过通信来确定客户端和服务器的身份。称为密钥分发中心(简称 KDC)的受信任第三方可帮助客户端和服务相互证明其身份。它是一个网络认证系统,解决了不可信网络中的两个重要问题:
Kerberos 是一种安全、单点登录、受信任的第三方和相互身份验证服务:
-
Security:Kerberos 是安全的,因为它从不通过网络传输密码。事实上,它使用了一种新颖的方法,即发送在设定的时间间隔后过期的有时间限制的加密消息,以向给定服务器证明用户的身份。
-
SIngle-Sign On:Kerberos 允许用户只输入一次密码,然后在 Kerberos领域内的设定时间段内访问各种 kerberized 服务,而无需重新输入密码。
-
Trusted third party:Kerberos 使用称为 KDC(密钥分发中心)的集中式身份验证服务器,网络中的所有其他实体都信任该服务器。所有身份验证请求都通过此服务器进行路由。
-
Mutual authentication:在 Kerberos 中,两个通信方相互证明自己的身份。例如,使用 Kerberos 的网络中的用户可以向邮件服务器进行身份验证,暗示“我就是我声称的那个人”,作为回报,邮件服务器证明它确实是邮件服务器,而不是邮件服务器中的其他服务。网络伪装成邮件服务器。
Part 2: Keberos 协议流概述
以下是典型 Kerberos 工作流中涉及的主要实体:
- 客户端:客户端代表用户为服务请求发起通信
- 服务器:服务器托管用户想要访问的服务
- 身份验证服务器 (AS):AS 执行所需的客户端身份验证。如果认证成功,AS 会向客户端发出一个名为 TGT(Ticket Granting Ticket)的票据。此票向其他服务器保证客户端已通过身份验证
- 密钥分发中心 (KDC):在 Kerberos 环境中,身份验证服务器在逻辑上分为三个部分:数据库 (db)、身份验证服务器 (AS) 和票证授予服务器 (TGS)。这三个部分依次存在于称为密钥分发中心的单个服务器中
- Ticket Granting Server (TGS):TGS 是一个将服务票据作为服务发布的应用服务器
现在让我们分解协议流程。
首先,Kerberos 流中涉及三个关键的密钥。客户端/用户、TGS 和与 AS 共享的服务器都有唯一的密钥。
- 客户端/用户(Client):从用户密码派生的哈希
- TGS 密钥:用于确定 TGS 的密码的哈希值
- 服务器密钥:用于确定提供服务的服务器的密码哈希。
协议流程包括以下步骤:
第 1 步:初始客户端身份验证请求。用户向身份验证服务器 (AS) 请求一个 Ticket Granting Ticket (TGT)。此请求包括客户端 ID。
第 2 步:KDC 验证客户端的凭据。AS 检查数据库中的客户端和 TGS 的可用性。如果 AS 找到这两个值,它会使用用户的密码散列生成客户端/用户密钥。
AS 然后计算 TGS 密钥并创建由客户端/用户密钥加密的会话密钥 (SK1)。然后,AS 生成一个包含客户端 ID、客户端网络地址、时间戳、生存期和 SK1 的 TGT。然后 TGS 密钥对票证进行加密。
第3步:客户端解密消息。客户端使用客户端/用户密钥解密消息并提取 SK1 和 TGT,生成验证客户端 TGS 的验证器。
第 4 步:客户端使用 TGT 请求访问。客户端通过将提取的 TGT 和创建的身份验证器发送到 TGS 来从提供服务的服务器请求票证。
第 5 步:KDC 为文件服务器创建票证。然后 TGS 使用 TGS 密钥解密从客户端收到的 TGT 并提取 SK1。TGS 解密验证器并检查它是否匹配客户端 ID 和客户端网络地址。TGS 还使用提取的时间戳来确保 TGT 没有过期。
如果该过程成功地执行了所有检查,则 KDC 会生成一个服务会话密钥 (SK2),该密钥在客户端和目标服务器之间共享。
最后,KDC 创建一个包含客户端 ID、客户端网络地址、时间戳和 SK2 的服务票证。然后使用从 db 获得的服务器密钥加密此票证。客户端收到一条包含服务票证和 SK2 的消息,均使用 SK1 加密。
第6步:客户端使用文件票证进行身份验证。客户端使用 SK1 解密消息并提取 SK2。该过程生成一个新的验证器,其中包含客户端网络地址、客户端 ID 和时间戳,用 SK2 加密,并将其和服务票证发送到目标服务器。
第7步:目标服务器接收解密和认证。目标服务器使用服务器的密钥解密服务票证并提取 SK2。服务器使用 SK2 解密验证器,执行检查以确保验证器的客户端 ID 和客户端网络地址与服务票证匹配。服务器还会检查服务票证以查看它是否已过期。
一旦满足检查,目标服务器就会向客户端发送一条消息,验证客户端和服务器已相互验证。用户现在可以参与安全会话。
Part 3: 实验信息设置
理想情况下,Kerberos 应该安装在经过强化的专用服务器上,因为领域的安全性与 KDC 的物理和网络安全性比较好。为简单起见,这次实验我将在同一个 docker 容器中安装 KDC 和 AS。
Part 4: 设置DOCKER-COMPOSE 环境
1. 为了创建实验所需的docker-compose架构,我们需要创建一个特定的目录树:
├── kerberos │ ├── client │ │ └── Dockerfile │ ├── docker-compose.yaml │ └── server │ └── Dockerfile │ └── ssh-server │ └── Dockerfile │ └── apache-server │ └── Dockerfile
Docker-compose.yaml
#docker-compose.yaml version: '3.3' services: server: container_name: kerberos_server hostname: server.kerberosproject1234.com build: context: ./server networks: vpcbr2: ipv4_address: 10.6.0.5 extra_hosts: - "server.kerberosproject1234.com:10.6.0.5" - "client.kerberosproject1234.com:10.6.0.6" - "ssh-server.kerberosproject1234.com:10.6.0.4" - "apache.kerberosproject1234.com:10.6.0.3" tty: true client: container_name: kerberos_client2 hostname: client.kerberosproject1234.com build: context: ./client tty: true networks: vpcbr2: ipv4_address: 10.6.0.6 extra_hosts: - "server.kerberosproject1234.com:10.6.0.5" - "client.kerberosproject1234.com:10.6.0.6" - "ssh-server.kerberosproject1234.com:10.6.0.4" - "apache.kerberosproject1234.com:10.6.0.3" ssh-server: container_name: ssh-server hostname: apache.kerberosproject1234.com build: context: ./ssh-server networks: vpcbr2: ipv4_address: 10.6.0.4 extra_hosts: - "server.kerberosproject1234.com:10.6.0.5" - "client.kerberosproject1234.com:10.6.0.6" - "ssh-server.kerberosproject1234.com:10.6.0.4" - "apache.kerberosproject1234.com:10.6.0.3" tty: true apache-server: container_name: apache-server hostname: apache.kerberosproject1234.com build: context: ./apache-server networks: vpcbr2: ipv4_address: 10.6.0.3 extra_hosts: - "server.kerberosproject1234.com:10.6.0.5" - "client.kerberosproject1234.com:10.6.0.6" - "ssh-server.kerberosproject1234.com:10.6.0.4" - "apache.kerberosproject1234.com:10.6.0.3" tty: true networks: vpcbr2: driver: bridge ipam: config: - subnet: 10.6.0.0/16
Client Dockerfile
#client/Dockerfile FROM ubuntu:18.04 RUN mkdir -p /run/systemd && echo 'docker' > /run/systemd/container RUN #(nop) CMD ["/bin/bash"] RUN apt-get update --fix-missing && apt-get install -y openssh-server RUN apt-get install -y iputils-ping RUN apt-get install -y sudo nano RUN mkdir /var/run/sshd RUN echo "root:toor" | chpasswd RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config RUN echo "export VISIBLE=now" >> /etc/profile RUN #(nop) EXPOSE 22 RUN #(nop) CMD ["/usr/sbin/sshd" "-D"]
Server Dockerfile
#server/Dockerfile FROM ubuntu:18.04 RUN mkdir -p /run/systemd && echo 'docker' > /run/systemd/container RUN apt-get update -y --fix-missing RUN apt-get install nano rsyslog -y RUN apt install inetutils-ping -y RUN apt-get install openssh-server -y
SSH-server Dockerfile
#ssh-server/Dockerfile FROM ubuntu:18.04 EXPOSE 749 88 22 RUN mkdir -p /run/systemd && echo 'docker' > /run/systemd/container RUN apt-get update -y --fix-missing RUN apt-get -qq install locales krb5-kdc krb5-admin-server RUN apt-get -qq install openssh-server RUN apt-get -qq install vim RUN apt-get install nano rsyslog -y RUN apt install inetutils-ping -y RUN apt-get -qq clean
Apache-server Dockerfile
#apache-server/Dockerfile FROM ubuntu:18.04 EXPOSE 749 88 80 RUN mkdir -p /run/systemd && echo 'docker' > /run/systemd/container RUN apt-get update -y --fix-missing RUN apt-get -qq install locales krb5-kdc krb5-admin-server RUN apt-get -qq install apache2 RUN apt-get -qq install vim RUN apt-get install nano rsyslog -y RUN apt install inetutils-ping -y RUN apt-get -qq clean
确保所有文件都放入指定的路径/apache-server/Dockerfile
/ssh-server/Dockerfile
, /client/Dockerfile
, /server/Dockerfile
and docker-compose.yaml,就可以运行以下指令。
docker-compose up --build -d
Part 5: server容器中的 KERBEROS 服务器配置
使用以下命令访问 docker 容器:
docker exec -it <container_id> bash
使用以下命令在服务器容器上安装 KDC 和管理服务器:
apt install krb5-kdc krb5-admin-server
通过查看/etc/krb5kdc/kdc.conf文件来验证配置。确保文件中的领域名称与实验室所需的领域名称相同。KDC 配置文件应如下所示:
[kdcdefaults] kdc_ports = 750,88 [realms] kerberosproject1234.com = { database_name = /var/lib/krb5kdc/principal admin_keytab = FILE:/etc/krb5kdc/kadm5.keytab acl_file = /etc/krb5kdc/kadm5.acl key_stash_file = /etc/krb5kdc/stash kdc_ports = 750,88 max_life = 10h 0m 0s max_renewable_life = 7d 0h 0m 0s master_key_type = des3-hmac-sha1 #supported_enctypes = aes256-cts:normal aes128-cts:normal default_principal_flags = +preauth }
Part 6: KERBEROS 数据库配置
1. Kerberos 使用数据库来存储代表网络上的用户和服务的主体。可以使用以下命令为您的领域创建数据库:
krb5_newrealm
2. kadmin是管理 Kerberos 数据库的有用工具。您可以使用此工具添加或删除主体。可以使用以下命令:
kadmin.local
3. 在控制台中添加 2 个用户主体: abc, abc2:
addprinc <principal>
使用以下命令为你的 ssh-server 和 apache-server 添加主机主体:
addprinc -randkey host/ssh-server.kerberosproject1234.com@kerberosproject1234.com addprinc -randkey HTTP/apache.kerberosproject1234.com@kerberosproject1234.com
为 SSH 服务器和 Apache 生成两个 keytab 文件,使用以下命令:
ktadd -k /etc/ssh-server.keytab host/ssh-server.kerberosproject1234.com@kerberosproject1234.com ktadd -k /etc/apache.keytab HTTP/apache.kerberosproject1234.com@kerberosproject1234.com
3. 将生成的文件ssh-server.keytab
到apache.keytab
复制到主机上以供进一步使用。
Part 7: 设置客户端容器
使用以下命令在 docker 容器上安装 Kerberos 客户端软件包:
apt-get install krb5-user krb5-config
注意:要填写Part 3中的一些信息
通过查看/etc/krb5.conf 文件确保配置如下所示:
Part 8: 设置ssh-server容器
1. 打开 ssh-server 容器,您会看到/etc/krb5.conf
文件内容类似于下图所示:
[libdefaults] default_realm = ATHENA.MIT.EDU # The following krb5.conf variables are only for MIT Kerberos. kdc_timesync = 1 ccache_type = 4 forwardable = true proxiable = true
2. 在它们前面添加 # 来注释掉这些行
将以下内容复制进去:
[libdefaults] default_realm = kerberosproject1234.com [realms] kerberosproject1234.com = { kdc_ports = 88,750 kadmind_port = 749 kdc = server.kerberosproject1234.com admin_server = server.kerberosproject1234.com }
3. 在ssh-server容器上创建一个账户并为该帐户设置密码,确保能够以该用户身份登录到服务器容器。
4. 在服务器容器上配置 OpenSSH 以允许 Kerberos 身份验证。这可以通过编辑/etc/ssh/sshd_config中的文件来实现。我们可以通过更新配置文件中的Kerberos和GSSAPI*标志来启用 Kerberos。在此处阅读更多有关于GSSAPI的信息。
注意:将KerberosTicketCleanup的值设置为“否”,因为我们需要令牌值作为 kerberos 身份验证日志中的证明。
5. 最后将我们之前在本地主机上复制的文件ssh-server.keytab 复制到 ssh-server 容器中,并将其放在文件夹中。确保将文件重命名为 krb5.keytab,并为文件提供适当的权限。
Part 9: 设置apache-server容器
1. 在 apache-server 容器中打开/etc/krb5.conf
,会看到文件的内容与以下类似:
[libdefaults] default_realm = ATHENA.MIT.EDU # The following krb5.conf variables are only for MIT Kerberos. kdc_timesync = 1 ccache_type = 4 forwardable = true proxiable = true
2. 在它们前面添加 # 来注释掉这些行
3. 将以下内容复制到 krb5.conf 文件中
[libdefaults] default_realm = kerberosproject1234.com [realms] kerberosproject1234.com = { kdc_ports = 88,750 kadmind_port = 749 kdc = server.kerberosproject1234.com admin_server = server.kerberosproject1234.com }
4. 安装 Apache 的 mod_auth_kerb 认证模块
apt-get install libapache2-mod-auth-kerb
注意:apache 模块必须在使用前加载。一般安装上述包时,模块会被启用。启用的模块可以在 /etc/apache2/mods-enabled 中找到。但是如果没有加载 apache 模块,可以通过在 apache2.conf 中添加以下指令来手动启用它。
LoadModule auth_kerb_module /usr/lib/apache2/modules/mod_auth_kerb.so
5. 将生成的 keytab 文件复制到您的 apache 服务器并适当更改权限
chown root.www-data apache.keytab chmod 640 /etc/apache.keytab
6. 在/etc/apache2/sites-enabled/000-default.conf 中完成 Apache – Kerberos 配置
<Directory "/var/www/html/test"> AuthType Kerberos AuthName "KERBEROS AUTHENTICATION" KrbAuthRealms kerberosprojectNUID.com Krb5Keytab /etc/apache.keytab KrbMethodNegotiate On KrbMethodK5Passwd Off #KrbSaveCredentials Off #KrbVerifyKDC Off Require valid-user </Directory>
记得重启apache服务,让修改生效
7. 现在,在/var/www/html/test/restricted.test中创建一个文件 来检查 Kerberos 身份验证是否正常工作。
mkdir /var/www/html/test/restricted.test echo "Restricted Acceess to Kerberos Prinicpals \n 1234" >/var/www/html/test/restricted.test
Part 10: 来自客户端容器的 SSH KERBEROS 身份验证
1. KDC 请求abc
在第 2 部分步骤 2(a) 中创建的用户主体的 TGT。您可以使用以下命令。在继续之前确保现在报告了错误。
kinit <name>
将获得以下的类似结果:
@client:/# klist Ticket cache: FILE:/tmp/krb5cc_0 Default principal: jose@kerberosproject1234.com Valid starting Expires Service principal 09/24/21 13:13:19 09/24/21 23:13:19 krbtgt/kerberosproject1234.com@kerberosproject1234.com renew until 09/25/21 13:13:15 @client:/#
2. 现在从您的客户端容器(存储 TGT 的位置)中,您将访问 Apache 服务器上的受限 Web 目录 (/test)。如果系统运行良好,您应该能够提供您创建的主体名称 (abc2) 并在不提供任何密码的情况下进行身份验证(因为您的kerberos 服务票证将在后台使用)
3. 从客户端容器到服务器容器的 ssh 连接应该如下所示:
ssh -vvv <your_first_name>@ssh-server.kerberosproject1234.com
4. 如无问题,应该会获得以下的类似输出:
Part 11: 来自客户端的 APACHE KERBEROS 身份验证
1. 向 KDC 请求<your_first_name2>
在第 2 部分步骤中创建的用户主体的 TGT。您可以使用以下命令。在继续之前确保现在报告了错误。
kinit <your_first_name2>
将得到以下类似输出:
@client:/# klist Ticket cache: FILE:/tmp/krb5cc_0 Default principal: jose@kerberosproject1234.com Valid starting Expires Service principal 09/24/21 13:13:19 09/24/21 23:13:19 krbtgt/kerberosproject1234.com@kerberosproject1234.com renew until 09/25/21 13:13:15 @client:/#
2. 现在,从您的客户端容器(存储 TGT 的位置)中,您将访问 Apache 服务器上的受限 Web 目录 (/test)。如果系统运行良好,您应该能够提供您创建的主体名称 (<your_first_name2>) 并在不提供任何密码的情况下进行身份验证(因为您的kerberos 服务票证将在后台使用)。
3. 首先尝试使用不允许访问该受限文件的用户进行访问
curl "http://apache.kerberosproject1234.com/test/restricted.test" -u : --negotiate
4. 现在,尝试使用允许访问该目录的 kerberos 主体进行访问,以便从 apache 获得正确的响应。如无意外,将获得以下类似输出:
这是我以前做过的实验,本来想边写边再做一遍的,但是到一半太懒了,就用了一些以前的截图,步骤我觉得描述都还算详细,不出意外,会得到相似结果的。