文章目录
Kerberos认证介绍
Kerberos 是一种“可信第三方”的网络认证协议,最初由 MIT 开发,现已成为 Windows AD、Hadoop、NFS、HTTP SSO 等场景的核心身份验证机制。它的设计目标只有一句话:在不安全的网络里,让双方都能证明“我是谁”,却从不传输密码而是使用票据。 详细资料请自行网络搜索
认证流程图

测试环境搭建
配置 Kerberos Server
执行以下命令,安装ubuntu镜像
docker pull docker.1ms.run/library/ubuntu:latest

启动容器
执行以下命令
docker run -it ubuntu /bin/bash

安装Kerberos Server
执行以下命令安装kerberos服务端和kdc;
需要注意的是我们这个命令实在容器内部执行的哦。也就是上一步之后执行的
apt install -y krb5-kdc krb5-admin-server krb5-config

安装过程中需要填写一些参数

按以下参数填写即可
Default Kerberos version 5 realm : LAN
Kerberos servers for your realm : kdc.lan
Administrative server : kdc.lan
配置数据库
命令行执行
krb5_newrealm
执行后会让你设置Realm 的主密码;我这里输入的是root;简单又好记

创建管理员主体
输入以下命令创建管理员主题
kadmin.local
创建管理员
addprinc root/admin
输入了之后又会让你设置管理员密码这里我也是设置的root;简单又好记

设置完了之后输入:q ;退出

安装vim
安装一个vim 后面需要修改配置文件用得到它
注意 server容器和client容器都需要安装一个因为都要设置配置文件
apt install vim

这里直接输入:5
接着会让选时间区域,这里我选的重庆也就是输入:19;这里输入完之后vim就安装完成了

配置访问控制列表 (ACL)
执行以下命令查看账户权限是否正常
cat /etc/krb5kdc/kadm5.acl

出现上面的内容就说明我们的账号的权限是正常的
重启相关服务
service krb5-kdc restart
service krb5-admin-server restart
查看ip
这里查看ip主要是给后面客户端配置文件中使用
执行以下命令安装一个ip查看工具
apt install -y iproute2
使用工具查看ip
ip -4 -o addr show scope global

修改配置文件
修改配置文件中的LAN
vi /etc/krb5.conf
将LAN设置为本机IP
LAN = {
kdc = 172.17.0.2
admin_server = 172.17.0.2
}
修改后重新启动服务
service krb5-kdc restart
安装redis服务
执行以下命令安装redis服务供客户端通过票据来连接redis
apt-get install redis-server -y
检查redis服务是否正常
service redis-server status

创建Redis服务主体
在Kerberos服务端容器中创建Redis的SPN
kadmin.local -q "addprinc -randkey redis/redis-server.172.17.0.2"
再将Kerberos服务主体(SPN)的密钥提取到keytab文件中
kadmin.local -q "ktadd -k /etc/redis/redis.keytab -norandkey redis/redis-server.172.17.0.2"
执行后会提示创建成功

模拟通过Kerberos认证连接redis环境
需要注意的是redis只有企业版才有对Kerberos的直接支持,我们没有企业版我搜索了一下AI说可以通过HAProxy+SASL插件来实现,也可以使用nginx代理来实现,这里我选择使用nginx来实现
- 安装编译环境
apt-get install -y build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev wget
- 下载源码
wget http://nginx.org/download/nginx-1.15.0.tar.gz && \
tar -xzf nginx-1.15.0.tar.gz
3.下载spnego模块
这个库很久没有更新了最后更新说名文档里说的是支持1.15.0
git clone https://github.com/stnoonan/spnego-http-auth-nginx-module.git
这里需要在宿主机上下载下载好了再拷贝进容器,因为容器可能访问不了github.com


安装开发包:
apt install -y libkrb5-dev
验证开发包是否安装完成
dpkg -L libkrb5-dev | grep gssapi.h
出现以下界面就说明安装完成了

安装nginx
cd nginx-1.15.0
./configure --prefix=/usr/local/nginx
make
make install
之后执行编译:
make clean
./configure \
--prefix=/usr/local/nginx \
--with-http_ssl_module \
--with-cc-opt="-Wno-error=deprecated-declarations" \
--add-module=../spnego-http-auth-nginx-module
make -j$(nproc) && make install
出现以下内容就说明编译成功了

如果提示: Syntax error: end of file unexpected (expecting “then”)
这是因为Windows 风格换行符(CRLF),Unix shell 读到 \r 后把整行命令截断导致的
就进入到spnego-http-auth-nginx-module文件夹里执行以下脚本
apt install -y dos2unix
find . -type f -exec dos2unix {} \+
修改nginx配置文件
在http模块里新增以下内容
server{
listen 6380;
server_name redis-kerberos-proxy;
location /{
auth_gss on;
auth_gss_keytab /etc/redis/redis.keytab;
auth_gss_service_name "redis/redis-server.172.17.0.2";
auth_gss_allow_basic_fallback off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://127.0.0.1:6379;
}
}
启动nginx服务
/usr/local/nginx/sbin/nginx
出现master和worker就说明成功启动了

检查kerberos支持是否正常
/usr/local/nginx/sbin/nginx -V 2>&1 | tr ' ' '\n' | grep spnego
出现以下内容说明运行正常

到这里我们nginx的配置就成功了;这里我耗费了两天的时间才成功,好几种方式都测试了只有nginx这种方式成功了。
修改redis
修改redis使其支持网络ip连接
vim /etc/redis/redis.conf
修改内容如下
- 绑定地址
bind 0.0.0.0
- 关闭保护模式
protected-mode no
修改后执行以下命令重启服务
redis-cli shutdown
redis-server /etc/redis/redis.conf
service redis-server restart
到这一步管理端基本上就已经配置完成了
容器网络连通
在控制台输入以下命令创建一个网络
docker network create mynet
检查是否成功
docker network ls

把服务端和客户端加入网络
docker network connect mynet 2bb
docker network connect mynet e15
验证网络是否畅通
客户端安装一个ping
apt-get update && apt-get install -y iputils-ping
ping 服务器ip
出现以下内容就说明网络通了

验证redis 是否能正常连接
redis-cli -h 172.17.0.2 -p 6379

配置Kerberos Client
此时我们重新打开一个cmd命令行窗口
执行以下命令创建一个新的客户端容器
docker run -itd --name kerberos_client ubuntu:latest tail -f /dev/null
执行之后会返回一个md5字符串,然后我们执行以下命令查看容器
docker ps -a

进入容器
docker exec -it kerberos_client /bin/bash
执行以下命令安装客户端
apt install -y krb5-user libkrb5-3

安装过程中同样需要填写一些参数
按以下参数填写即可
Default Kerberos version 5 realm : LAN
Kerberos servers for your realm : kdc.lan
Administrative server : kdc.lan
编辑客户端配置文件
注意这里需要按照上面的教程给client容器也安装一个vim
vi etc/krb5.conf
把这个配置文件修改为以下内容
注意: 172.17.0.2是Kerberos管理端容器的IP
[libdefaults]
default_realm = LAN
# The following krb5.conf variables are only for MIT Kerberos.
kdc_timesync = 1
ccache_type = 4
forwardable = true
proxiable = true
rdns = false
ticket_lifetime=24h
dns_lookup_kdc=false
dns_lookup_realm=false
# The following libdefaults parameters are only for Heimdal Kerberos.
fcc-mit-ticketflags = true
[realms]
LAN = {
kdc = 172.17.0.2
admin_server = 172.17.0.2
}
ATHENA.MIT.EDU = {
kdc = kerberos.mit.edu
kdc = kerberos-1.mit.edu
kdc = kerberos-2.mit.edu:88
admin_server = kerberos.mit.edu
default_domain = mit.edu
}
ZONE.MIT.EDU = {
kdc = casio.mit.edu
kdc = seiko.mit.edu
admin_server = casio.mit.edu
}
CSAIL.MIT.EDU = {
admin_server = kerberos.csail.mit.edu
default_domain = csail.mit.edu
}
IHTFP.ORG = {
kdc = kerberos.ihtfp.org
admin_server = kerberos.ihtfp.org
}
1TS.ORG = {
kdc = kerberos.1ts.org
admin_server = kerberos.1ts.org
}
ANDREW.CMU.EDU = {
admin_server = kerberos.andrew.cmu.edu
default_domain = andrew.cmu.edu
}
CS.CMU.EDU = {
kdc = kerberos-1.srv.cs.cmu.edu
kdc = kerberos-2.srv.cs.cmu.edu
kdc = kerberos-3.srv.cs.cmu.edu
admin_server = kerberos.cs.cmu.edu
}
DEMENTIA.ORG = {
kdc = kerberos.dementix.org
kdc = kerberos2.dementix.org
admin_server = kerberos.dementix.org
}
stanford.edu = {
kdc = krb5auth1.stanford.edu
kdc = krb5auth2.stanford.edu
kdc = krb5auth3.stanford.edu
master_kdc = krb5auth1.stanford.edu
admin_server = krb5-admin.stanford.edu
default_domain = stanford.edu
}
UTORONTO.CA = {
kdc = kerberos1.utoronto.ca
kdc = kerberos2.utoronto.ca
kdc = kerberos3.utoronto.ca
admin_server = kerberos1.utoronto.ca
default_domain = utoronto.ca
}
[domain_realm]
.mit.edu = ATHENA.MIT.EDU
mit.edu = ATHENA.MIT.EDU
.media.mit.edu = MEDIA-LAB.MIT.EDU
media.mit.edu = MEDIA-LAB.MIT.EDU
.csail.mit.edu = CSAIL.MIT.EDU
csail.mit.edu = CSAIL.MIT.EDU
.whoi.edu = ATHENA.MIT.EDU
whoi.edu = ATHENA.MIT.EDU
.stanford.edu = stanford.edu
.slac.stanford.edu = SLAC.STANFORD.EDU
.toronto.edu = UTORONTO.CA
.utoronto.ca = UTORONTO.CA
.lan=LAN
lan=LAN
[logging]
kdc=FILE:/var/log/krb5kdc.log
admin_server=FILE:/var/log/kadmin.log
default=FILE:/var/log/krb5lib.log
和默认配置文件相比主要增加的内容有以下几点:
- libdefaults
ticket_lifetime=24h
dns_lookup_kdc=false
dns_lookup_realm=false
- domain_realm
LAN = {
kdc = 172.17.0.2
admin_server = 172.17.0.2
}
.lan=LAN
lan=LAN
- logging(这个模块是新加的用于日志打印)
[logging]
kdc=FILE:/var/log/krb5kdc.log
admin_server=FILE:/var/log/kadmin.log
default=FILE:/var/log/krb5lib.log
设置完之后咱们再去把存储日志的文件夹建一下
mkdir -p /var/log/kerberos
授权
chmod 750 /var/log/kerberos

配置完成之后执行,获取票据
票据获取
kinit root/admin
执行完之后查看票据
klist

出现以上内容就是票据获取成功了,这里因为我们配置文件里设置的过期时间是24小时所有Expires时间就到明天去了。
验证票据
执行以下脚本
curl -v --negotiate -u : http://172.17.0.2:6380/
返回以下内容则说明成功了;kerberos票据校验通过了

返回 200 且响应头里可见 WWW-Authenticate: Negotiate → Kerberos 认证成功。
返回 401 且无 Negotiate → 模块没启或 keytab 无效。
返回 502/504 → 认证已通过,但后端 proxy_pass 地址不通。
都这里我们的环境搭建就结束了,该开始写.net 的票据续期功能了。
.net6 实现redis票据认证
using Kerberos.NET.Client;
using Kerberos.NET.Credentials;
using Kerberos.NET.Crypto;
using System.Net.Sockets;
using System.Text;
namespace RedisKerberosTest
{
internal class Program
{
// ====================================
private static async Task Main()
{
try
{
//这部分要更换,根据自己的业务需求替换
string RedisHost = "172.17.0.2";
int RedisPort = 6379;
string RedisPrincipal = "redis/172.17.0.2@HADOOP.COM";
string Ktb_path = "/opt/test/user.keytab";
string username = "redis_server";
Console.WriteLine("请输入用户名称(默认直接回车):");
string? R_username = Console.ReadLine()?.Trim();
if (!string.IsNullOrWhiteSpace(R_username))
{
username = R_username;
}
Console.WriteLine("请输入主体(默认直接回车):");
string? R_principal = Console.ReadLine()?.Trim();
if (!string.IsNullOrWhiteSpace(R_principal))
{
RedisPrincipal = R_principal;
}
Console.WriteLine("请输入ktb文件路径(默认直接回车):");
string? R_ktb_path = Console.ReadLine()?.Trim();
if (!string.IsNullOrWhiteSpace(R_ktb_path))
{
Ktb_path = R_ktb_path;
}
KeyTable keyTable = new KeyTable(File.ReadAllBytes(Ktb_path));
var kerbCred = new KeytabCredential(username, keyTable);
Console.WriteLine("解析票据数据");
using var kerbClient = new KerberosClient();
await kerbClient.Authenticate(kerbCred);
var ticket = await kerbClient.GetServiceTicket(RedisPrincipal);
Console.WriteLine("开始尝试建立 TCP 连接");
// 2. 建立 TCP 连接
using var tcp = new TcpClient();
await tcp.ConnectAsync(RedisHost, RedisPort);
using var ns = tcp.GetStream();
Console.WriteLine("发送请求");
// 3. 发送 AUTH GSSAPI <base64>
var tokenB64 = Convert.ToBase64String(ticket.EncodeApplication().ToArray());
await SendRawAsync(ns, $"AUTH GSSAPI {tokenB64}\r\n");
var resp = await ReadLineAsync(ns);
if (!resp.StartsWith("+OK"))
throw new Exception("AUTH failed: " + resp);
Console.WriteLine("✅ Kerberos 认证通过");
// 4. 发送正常 Redis 命令
await SendRawAsync(ns, "PING\r\n");
resp = await ReadLineAsync(ns);
Console.WriteLine("PING 结果: " + resp);
await SendRawAsync(ns, "SET mykey \"Hello Kerberos\"\r\n");
resp = await ReadLineAsync(ns);
Console.WriteLine("SET 结果: " + resp);
await SendRawAsync(ns, "GET mykey\r\n");
resp = await ReadLineAsync(ns);
Console.WriteLine("GET 结果: " + resp);
Console.ReadKey();
}
catch (Exception ex)
{
Console.WriteLine("执行发生错误:{0}", ex.Message);
}
}
private static async Task SendRawAsync(NetworkStream ns, string cmd)
{
var buf = Encoding.ASCII.GetBytes(cmd);
await ns.WriteAsync(buf);
await ns.FlushAsync();
}
private static async Task<string> ReadLineAsync(NetworkStream ns)
{
var sb = new StringBuilder();
byte[] b = new byte[1];
while (true)
{
await ns.ReadAsync(b, 0, 1);
if (b[0] == '\n') break;
if (b[0] != '\r') sb.Append((char)b[0]);
}
return sb.ToString();
}
}
}
编译Linux可执行文件
在vs控制台输入以下命令即可
dotnet publish -c Release -r linux-x64 --self-contained true -p:PublishSingleFile=true -o ../out
执行之后数据的文件路径在你项目的bin/Relsase/net6.0/linux-x64文件夹下
小结
自此通过票据认证方式连接redis教程结束
227

被折叠的 条评论
为什么被折叠?



