搭建一个基于 Kerberos 认证的 NFS 服务器


上一篇文章:
认识 NFS 文件共享协议


一、前言

前段时间在研究网络安全的时候了解到了 Kerberos 这个东西。

然后突然想起这不是 NFS 唯一支持的身份验证方式吗?!

由于当时学 NFS 的时候感觉 Kerberos 很复杂,然后就一直没有去研究它。

这次决定把 Kerberos 彻底弄懂,然后给 NFS 服务器加上认证!

本文纯属个人学习经验分享。如有错误,请尽管提出,非常感谢!


二、Kerberos 简介

和 X.509 数字证书一样,Kerberos 也是一种第三方认证系统。

Kerberos 通过一个所有节点都信赖的第三方(认证器)来实现通信双方的相互认证、防伪以及数据加密。

与 X.509 数字证书不同的是,Kerberos 使用的是对称加密,而 X.509 数字证书使用的是非对称加密。

Kerberos 由三部分组成:「服务器(SS)」、「客户端(C)」、「第三方服务器」。

「第三方服务器」又包含了三个子系统(物理合一):「认证服务器(AS)」、「票据授予服务器(TGS)」、「密钥分发中心(KDC)」。

这个「第三方服务器」通常被称作「Kerberos 认证服务器」、「认证服务器」等。

目前常用的 Kerberos 版本为 5。


三、Kerberos 简要工作原理

下面以一种比较简单易懂的表达方式阐述个人对 Kerberos 工作原理的理解。

3.1 准备工作

  • 「KDC」在初始化的时候生成「? TGS <--> AS」。「? TGS <--> AS」只有「第三方服务器」知道。
  • 「C」在「KDC」中注册自己,并获取到一个私钥「? C」。「? C」只有「C」和「第三方服务器」知道。
  • 「SS」在「KDC」中注册自己,并获取到一个私钥「? SS」。「? SS」只有「SS」和「第三方服务器」知道。

3.2 工作流程

一次标准的 Kerberos 认证流程分为六个阶段。

⚠️ 注意
• Kerberos 对各节点间时间同步的要求非常高,因为 Kerberos 验证基本上每一步都用到了时间戳。而为了方便理解,下文我并没有将时间戳标示出来。

3.2.1 第一阶段

  • 「C」把「个人信息」生成「? 1」发送给「AS」。

3.2.2 第二阶段

  • 「AS」查找对应的「? 1」中的「个人信息」记录,如果找到则生成「? C <--> TGS」。
  • 「AS」用「? C」对「? C <--> TGS」、进行加密,生成「? 2」。
  • 「AS」用「? TGS <--> AS」对「? C <--> TGS」和「? 1」进行加密,生成「? 1」。
  • 「AS」把「? 2」和「? 1」发送给「C」。

说明
• 「? 1」称为「票据授权票据(TGT)」。

3.2.3 第三阶段

  • 「C」用「? C」解密「? 2」,得到「? C <--> TGS」(如果「C」是假冒的,那么将无法解密得到「? C <--> TGS」)。
  • 「C」用「? C <--> TGS」加密「? 1」,生成「? 3」。
  • 「C」把「要访问的服务器信息」生成「? 4」。
  • 「C」把「? 1」、「? 3」和「? 4」发送给「TGS」。

说明
• 「? 3」称为「验证器(Authenticator)」。

3.2.4 第四阶段

  • 「TGS」用「? TGS <--> AS」解密「? 1」,得到「? C <--> TGS」。
  • 「TGS」用「? C <--> TGS」解密「? 3」,得到「? 1」。验明客户端真身。
  • 「TGS」查找对应的「? 4」中的「要访问的服务器信息」记录,如果找到则生成「? C <--> SS」。
  • 「TGS」用「? C <--> TGS」对「? C <--> SS」进行加密,生成「? 5」。
  • 「TGS」用「? S」对「? C <--> SS」和「? 1」进行加密,生成「? 2」。
  • 「TGS」把「? 5」和「? 2」发送给「C」。

说明
• 「? 2」称为「服务票据」。

3.2.5 第五阶段

  • 「C」用「? C <--> TGS」解密「? 5」,得到「? C <--> SS」。
  • 「C」用「? C <--> SS」加密「? 1」,生成「? 6」。
  • 「C」把「? 6」和「? 2」发送给「SS」。

说明
• 「? 6」称为「验证器(Authenticator)」。

3.2.6 第六阶段

  • 「SS」用「? S」解密「? 2」,得到「? C <--> SS」(如果「SS」是假冒的,那么将无法解密得到「? C <--> SS」)。
  • 「SS」用「? C <--> SS」解密「? 6」,得到「? 1」。验明客户端真身。
  • 「SS」向「C」表示同意提供服务。后续数据使用「? C <--> SS」进行加密。

四、操作环境

NFS 服务器(同时作为 Kerberos 认证器) NFS 客户端
• IP: 10.0.0.101
• 域名:server.nfs
• 操作系统:CentOS 7.4.1708 最小安装(已关闭防火墙和 SELinux)
• 共享目录:/tmp
• IP: 10.0.0.102
• 域名:client.nfs
• 操作系统:CentOS 7.4.1708 最小安装(已关闭防火墙和 SELinux)

五、NFS 服务器的配置

5.1 安装 NFS、Kerberos 相关工具

执行以下命令:

yum -y install nfs-utils krb5-server krb5-workstation

5.2 配置 hosts 文件

由于 Kerberos 只支持域名验证,所以必须将服务器和客户端的 IP 绑定到对应的域名上。

一般修改下 /etc/hosts 文件就可以了。

执行以下命令:

echo "10.0.0.101  server.nfs" > /etc/hosts
echo "10.0.0.102  client.nfs" > /etc/hosts

5.3 修改 Kerberos 配置文件

请使用 vim 之类的文本编辑器打开 /etc/krb5.conf

# 后面的内容为注释,方便大家以实际情况修改)

说明
• 下面配置 Kerberos 的默认领域(realm)。

找到 default_realm 这一行,将其修改为:

 default_realm = NFS    # 默认领域为 NFS

说明
• 下面配置 Kerberos 领域(realm)的参数。

找到 [realms] 这一部分,将整个部分修改为:

[realms]
 NFS = {    # 建立一个名为 NFS 的领域
  kdc = server.nfs  # KDC 为 server.nfs
  admin_server = server.nfs # 管理服务器为 server.nfs
 }

说明
• 下面配置要将哪些域名包含在哪些领域(realm)内。

找到 [domain_realm] 这一部分,将整个部分修改为:

[domain_realm]
 .nfs = NFS # 以 .nfs 为后缀的域名都加入到该领域中

然后保存退出。

最终配置文件内容如下:

# Configuration snippets may be placed in this directory as well
includedir /etc/krb5.conf.d/

[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 dns_lookup_realm = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true
 rdns = false
 default_realm = NFS
 default_ccache_name = KEYRING:persistent:%{uid}

[realms]
 NFS = {
  kdc = server.nfs
  admin_server = server.nfs
 }

[domain_realm]
 .nfs = NFS

5.4 配置 Kerberos 服务器管理访问控制参数

说明
• 此步骤是为了方便客户端从 KDC 获取密钥。等搭建测试完成之后,如果没有远程管理 KDC 的需要,建议把这个文件清空。

请使用 vim 之类的文本编辑器打开 /var/kerberos/krb5kdc/kadm5.acl

把里面的 EXAMPLE.COM 修改为上一步设置的领域(realm)名,即 NFS

然后保存退出。

最终配置文件内容如下:

*/[email protected] *

5.5 配置 NFS 共享目录

请使用 vim 之类的文本编辑器打开 /etc/exports

加入以下内容:

/tmp *(rw,all_squash,sec=krb5p)

说明
1. 这里的 sec=krb5p 选项表示开启 Kerberos 认证和加密。如果是 sec=krb5 的话则只开启 Kerberos 认证而不开启加密。
2. vim 可能会有红色提示错误,请不要管它。
3. 如果想了解详细的配置方法,请参考上一篇文章。

然后保存退出。

5.6 初始化 KDC 数据库

执行以下命令:

kdb5_util create -s

按提示设定 KDC 数据库的密码即可。

说明
• KDC 数据库的位置:/var/kerberos/krb5kdc

运行结果:

Loading random data #如果卡在这里,说明熵不够。可以开启另一个终端,执行下 dd if=/dev/urandom of=/dev/null
Initializing database '/var/kerberos/krb5kdc/principal' for realm 'NFS',
master key name 'K/[email protected]'
You will be prompted for the database Master Password.
It is important that you NOT FORGET this password.
Enter KDC database master key: #输入密码
Re-enter KDC database master key to verify: #确认密码

5.7 启动 NFS、Kerberos 服务

执行以下命令:

systemctl start krb5kdc kadmin nfs-secure nfs

如需开机启动,请执行:

systemctl enable krb5kdc kadmin nfs-secure nfs

5.8 配置 KDC 数据库 & 取得密钥

执行以下命令:

kadmin.local

执行之后会进入一个交互界面。

然后按下面提示执行命令即可(kadmin.local:后面的内容均为需要执行的命令):

Authenticating as principal root/[email protected] with password.
kadmin.local:  addprinc root/[email protected]                  ← 创建管理员账户
WARNING: no policy specified for root/[email protected]; defaulting to no policy
Enter password for principal "root/[email protected]":          << 输入管理员账户密码
Re-enter password for principal "root/[email protected]":       << 确认管理员账户密码
Principal "root/[email protected]" created.
kadmin.local:  addprinc -randkey host/[email protected]    ← 注册认证器,并生成密钥(格式:addprinc -randkey host/<认证器域名>@<领域名>)
WARNING: no policy specified for host/[email protected]; defaulting to no policy
Principal "host/[email protected]" created.
kadmin.local:  addprinc -randkey nfs/[email protected]     ← 注册 NFS 服务器,并生成密钥(格式:addprinc -randkey nfs/<NFS 服务器域名>@<领域名>)
WARNING: no policy specified for nfs/[email protected]; defaulting to no policy
Principal "nfs/[email protected]" created.
kadmin.local:  addprinc -randkey nfs/[email protected]     ← 注册 NFS 客户端,并生成密钥(格式:addprinc -randkey nfs/<NFS 客户端域名>@<领域名>)
WARNING: no policy specified for nfs/[email protected]; defaulting to no policy
Principal "nfs/[email protected]" created.
kadmin.local:  ktadd host/[email protected]                ← 取得认证器的密钥(格式:ktadd host/<认证器域名>@<领域名>)
Entry for principal host/[email protected] with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab.
Entry for principal host/[email protected] with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab.
kadmin.local:  ktadd nfs/[email protected]                 ← 取得 NFS 服务器的密钥(格式:ktadd nfs/<NFS 服务器域名>@<领域名>)
Entry for principal nfs/[email protected] with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab.
Entry for principal nfs/[email protected] with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab.
kadmin.local:  exit                                     ← 退出交互界面

⚠️ 注意
• 密钥保存在 /etc/krb5.keytab 这个文件中,请确保它的安全。


六、NFS 客户端的配置

6.1 安装 NFS、Kerberos 相关工具

执行以下命令:

yum -y install nfs-utils krb5-workstation

6.2 配置 hosts 文件

该步骤与 5.2 完全相同,这里不再赘述。

6.3 修改 Kerberos 配置文件

该步骤与 5.3 完全相同,这里不再赘述。

6.4 从 KDC 上取得密钥

执行以下命令:

kadmin

执行之后会进入一个交互界面。

然后按下面提示执行命令即可(kadmin:后面的内容均为需要执行的命令):

Authenticating as principal root/[email protected] with password.
Password for root/[email protected]:           << 输入上面 5.8 设定的管理员密码
kadmin:  ktadd nfs/[email protected]      ← 取得 NFS 客户端的密钥(格式:ktadd nfs/<NFS 客户端域名>@<领域名>)       
Entry for principal nfs/[email protected] with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab.
Entry for principal nfs/[email protected] with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab.
kadmin:  exit                          ← 退出交互界面

⚠️ 注意
• 密钥保存在 /etc/krb5.keytab 这个文件中,请确保它的安全。

6.5 启动 NFS 加密服务

执行以下命令:

systemctl start nfs-secure

如需开机启动,请执行:

systemctl enable nfs-secure

6.6 连接 NFS 服务

执行以下命令:

(在正常的 NFS 挂载命令的 mount.nfs 后面加上 -o sec=krb5p即可 )

mount.nfs -o sec=krb5p server.nfs:/tmp /mnt

如果没有报错,说明挂载成功。


七、结果验证

7.1 检查挂载点

在客户端上执行以下命令:

mount | grep sec=krb5

运行结果:

server.nfs:/tmp on /mnt type nfs4 (rw,relatime,vers=4.1,rsize=262144,wsize=262144,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=krb5,clientaddr=10.0.0.102,local_lock=none,addr=10.0.0.101)

能看到挂载点,说明挂载成功。

7.2 读写测试

在客户端上执行以下命令:

echo Kerberos > /mnt/test.txt

然后在服务器上执行以下命令:

cat /tmp/test.txt 

如果在服务器上能看到:

Kerberos

那就大功告成了!


八、防火墙设置

如果需要设置防火墙,除了要打开 NFS 相关端口之外,还要打开以下端口:

  • TCP/UDP 88
  • TCP/UDP 749 (用于 Kerberos 服务器管理以及取密钥,用完可关闭)

九、参考文献

  1. 利用 kerberos 提供票據加密 – 鳥哥的 Linux 私房菜
  2. RHCE 系列(七):在 Linux 客户端配置基于 Kerberos 身份验证的 NFS 服务器 – Linux 中国
  3. kerberos 认证原理 — 讲的非常细致,易懂 – CSDN 博客
  4. RHEL7: Use Kerberos to control access to NFS network shares. – CertDepot

发表评论

电子邮件地址不会被公开。