用wsl实现 kerberos 认证协议
一、环境准备
1、先打开docker,在桌面上创建文件夹,在空白处右键点击打开终端,然后在终端输入wsl
2、导入容器镜像,在Kali终端,分别输入
tar xJvf krb5-bundle.tar.xz -C ./find . -maxdepth 1 -name "krb*.tar" | xargs -I {} bash -c "docker load <{}"# 确认镜像导入是否成功,下面应该输出三个镜像
docker image ls | grep krb5
#krb5-kdc-server-example-com
#krb5-machine-example-com
#krb5-service-example-com
3、创建容器网桥,输入以下代码
注:这次的实验涉及到 kerberos 域(默认为 EXAMPLE.COM
),不能再使用 docker 网桥内部 DNS 解析,必须固定 ip。
如果之前创建的网桥与本次创建的网桥存在地址段冲突,建议先把之前的网桥都清理掉,或者手动修改后续所有的网段。
一键清理残留的容器和旧的容器网桥:docker container prune -f && docker network prune -f
docker network create \--driver=bridge \--subnet="10.5.0.0/24" \--ip-range="10.5.0.0/24" \--gateway="10.5.0.254" \"example.com"
docker network ls | grep example.com
二、环境启动
1、创建工作目录,后续命令执行和文件创建都应该通过这个目录
mkdir ~/kerberos && cd ~/kerberos
2、打开这个目录,输入
explorer.exe .
3、在这个路径下创建 compose.yaml
文件,直接新建文本文档,输入下面的代码,然后选择所有文件,并修改后缀名
version: "3"services:machine-example-com:image: localhost/krb5-machine-example-comcontainer_name: krb5-machine-example-comhostname: krb5-machine-example-comdomainname: example.comnetworks:example.com:ipv4_address: 10.5.0.1extra_hosts:- "krb5-machine-example-com.example.com:10.5.0.1"- "krb5-kdc-server-example-com.example.com:10.5.0.2"- "krb5-service-example-com.example.com:10.5.0.3"volumes:- ./traffic-cap:/root/traffic-capkdc-server-example-com:image: localhost/krb5-kdc-server-example-comcontainer_name: krb5-kdc-server-example-comhostname: krb5-kdc-server-example-comdomainname: example.comnetworks:example.com:ipv4_address: 10.5.0.2extra_hosts:- "krb5-machine-example-com.example.com:10.5.0.1"- "krb5-kdc-server-example-com.example.com:10.5.0.2"- "krb5-service-example-com.example.com:10.5.0.3"volumes:- ./traffic-cap:/root/traffic-capservice-example-com:image: localhost/krb5-service-example-comcontainer_name: krb5-service-example-comhostname: krb5-service-example-comdomainname: example.comnetworks:example.com:ipv4_address: 10.5.0.3extra_hosts:- "krb5-machine-example-com.example.com:10.5.0.1"- "krb5-kdc-server-example-com.example.com:10.5.0.2"- "krb5-service-example-com.example.com:10.5.0.3"volumes:- ./traffic-cap:/root/traffic-capnetworks:example.com:external: true
4、启动容器
# 清理旧的残余容器
docker-compose down# 拉起容器
docker-compose up -d
# 下面三个容器的状态应该为 up(因为重新做了一遍,该状态为Started)
# krb5-service-example-com
# krb5-kdc-server-example-com
# krb5-machine-example-comdocker ps | grep krb5# 确保 supervisord 进程已拉起
containers=(krb5-machine-example-com krb5-kdc-server-example-com krb5-service-example-com)
for c in "${containers[@]}";doecho "check container: $c"docker exec $c supervisorctl status
done
# check container: krb5-machine-example-com
# httpserver RUNNING pid 2, uptime 0:00:14
# check container: krb5-kdc-server-example-com
# httpserver RUNNING pid 2, uptime 0:00:12
# krb5-admin-server RUNNING pid 3, uptime 0:00:12
# krb5-kdc RUNNING pid 4, uptime 0:00:12
# check container: krb5-service-example-com
# httpserver RUNNING pid 2, uptime 0:00:10
# sshd RUNNING pid 3, uptime 0:00:10
5、确认 ssh 服务已启动,并确认开启了 GSSAPI 认证
# 确认 service 容器 sshd 服务已启动,并监听了默认的 22 端口
docker exec krb5-service-example-com netstat -lnpt | grep 22# 存在 GSSAPIAuthentication yes 表明 GSSAPI 认证已开启
docker exec krb5-service-example-com cat /etc/ssh/sshd_config | grep -i gss
6、service 节点创建 bob 用户,验证 sshd 服务基于密码认证的功能正常
# machine 节点 是 ssh 客户端
# 可以看到在 machine 节点上,用户是 root,主机名为 hostname
docker exec krb5-machine-example-com /bin/sh -c "id && hostname"# 随意输入一个密码,这个密码可以与 kerberos不同
docker exec -i krb5-service-example-com adduser bob# machine ssh 客户端尝试使用密码认证的方式登录 bob 账户
# 这次输入的密码和上面命令设置的一致
docker exec -it krb5-machine-example-com ssh -v bob@krb5-service-example-com -o PreferredAuthentications=password# 登录成功后,可以看到是以 bob 的身份进入了 krb5-service-example-com 节点
whoami && hostname# 退出登陆
exit
7、kerberos-kdc 创建用户/服务实体
# 实验为了好记,采用这种弱口令,现实中,不能这么操作
# 创建用户实体 `alice`,口令为`alice`
# 创建用户实体 `bob`,口令为`bob`
# 创建服务实体 `host/krb5-service-example-com.example.com`,服务实体口令为随机生成
# 所有实体均在 `EXAMPLE.COM` 域内
docker exec krb5-kdc-server-example-com /bin/sh -c "
cat << EOF | kadmin.local
add_principal -pw alice \"alice@EXAMPLE.COM\"
add_principal -pw bob \"bob@EXAMPLE.COM\"
add_principal -randkey \"host/krb5-service-example-com.example.com@EXAMPLE.COM\"
EOF
"# 查看实体列表,下面应该有如下输出
# alice@EXAMPLE.COM
# bob@EXAMPLE.COM
# host/krb5-service-example-com.example.com@EXAMPLE.COM
docker exec krb5-kdc-server-example-com kadmin.local list_principals | grep -E 'alice|bob|host'
8、kerberos-kdc 创建长期密钥文件 keytab
,密钥文件和实体身份关联,并将分发给客户端和服务
# 这里只给用户 bob 和 服务实体进行了关联
docker exec krb5-kdc-server-example-com /bin/sh -c "
cat << EOF | kadmin.local
ktadd -k /etc/krb5-service.keytab -norandkey \"host/krb5-service-example-com.example.com@EXAMPLE.COM\"
ktadd -k /etc/bob.keytab -norandkey \"bob@EXAMPLE.COM\"
EOF
"# 先从kdc拷贝出长期密钥文件拷贝到宿主机
mkdir -p keytabs
docker cp krb5-kdc-server-example-com:/etc/krb5-service.keytab ./keytabs/krb5-service.keytab
docker cp krb5-kdc-server-example-com:/etc/bob.keytab ./keytabs/bob.keytab# 查看长期密钥内容
cat keytabs/bob.keytab
cat keytabs/krb5-service.keytab# 宿主机分发到各实体中
docker cp ./keytabs/krb5-service.keytab krb5-service-example-com:/etc/krb5.keytab
docker cp ./keytabs/bob.keytab krb5-machine-example-com:/etc/bob.keytab
9、验证 kerberos 用户、服务实体的合法性
# 使用口令验证用户,这个命令提示需要输入口令, 报 Warning: encryption type 是正常现象
# 输入口令 alice 完成。没有错误返回说明用户存在
docker exec -i krb5-machine-example-com kinit alice@EXAMPLE.COM# 输入口令 bob 完成。没有错误返回说明用户存在
docker exec -i krb5-machine-example-com kinit bob@EXAMPLE.COM# 使用长期密钥验证用户身份,没有错误返回说明密钥合法
docker exec krb5-machine-example-com kinit -kt /etc/bob.keytab bob@EXAMPLE.COM# 因为我们验证了身份,此时已经拿到了 bob 身份票据`krbtgt/EXAMPLE.COM@EXAMPLE.COM`
docker exec krb5-machine-example-com klist# 验证服务实体存在,且客户端有权限访问(前面已经拿到了身份票据)
docker exec krb5-machine-example-com kvno host/krb5-service-example-com.example.com# 此时拿到了服务票据`host/krb5-service-example-com.example.com@EXAMPLE.COM`
docker exec krb5-machine-example-com klist# 销毁票据缓存
docker exec krb5-machine-example-com kdestroy# 此时会报错,已经不存在票据缓存了
docker exec krb5-machine-example-com klist# 验证服务端长期密钥合法性,没有错误返回说明合法
docker exec krb5-service-example-com kinit -kt /etc/krb5.keytab# 销毁票据缓存
docker exec krb5-service-example-com kdestroy
三、基于 kerberos 的 ssh 认证
1、捕获报文
需要在 linux 环境中单独开启一个终端,运行下面的命令
# 抓取客户端报文
docker exec krb5-machine-example-com tcpdump -i any -w /root/traffic-cap/machine.pcap
2、正常登录流程
在做环境启动的终端,继续输入
# 获取身份票据
docker exec krb5-machine-example-com kinit -kt /etc/bob.keytab bob@EXAMPLE.COM# 获取服务票据
docker exec krb5-machine-example-com kvno host/krb5-service-example-com.example.com# 确认票据
docker exec krb5-machine-example-com klist# 登录服务
docker exec -it krb5-machine-example-com ssh -v bob@krb5-service-example-com -o PreferredAuthentications=gssapi-with-mic
3、分析报文
在第1步的终端,按ctrl+c
结束抓包
ls ~/kerberos/traffic-cap/
将 machine.pcap
报文拖到 wireshark 中
注:如果用wireshark打不开 machine.pcap
报文,可能是因为wireshark版本过低,建议直接在官网更新。