Apache Kerby 2.1.2 配置参数详解
逐项详解 Apache Kerby 2.1.2 的 kdc.conf、backend.conf、krb5.conf 与 JVM 启动参数,含默认值、修改方法与 Ubuntu 22.04 实测验证回显。
Apache Kerby 2.1.2 配置参数详解
目标:掌握 Kerby 2.1.2 全部服务端配置文件的参数含义、默认值与修改方法,并能在本机完成修改后实测验证。已在 Ubuntu 22.04(OpenJDK 17)实测通过。
一、环境信息
| 项目 | 值 |
|---|---|
| 操作系统 | Ubuntu 22.04.5 LTS |
| 系统架构 | x86_64(amd64) |
| JDK | OpenJDK 17.0.20.1 |
| 组件版本 | Apache Kerby 2.1.2 |
| 服务端目录 | /opt/kerby/kdc-dist-2.1.2 |
| 客户端工具目录 | /opt/kerby/tool-dist-2.1.2 |
| 配置目录 | /opt/kerby/kdc-dist-2.1.2/conf |
| 工作目录 | /opt/kerby/kdc-dist-2.1.2/runtime |
| 后端数据文件 | /tmp/kerby/jsonbackend/json-backend.json |
表后逐项说明:本文所有参数均来自 /opt/kerby/kdc-dist-2.1.2/conf 下的三份文件与启动命令行;客户端工具(kinit/klist)通过 -conf 参数指向服务端的 conf 目录,因此 krb5.conf 是服务端与客户端共用的桥梁文件。
二、配置体系概览
Kerby 2.1.2 的配置由三份文件加一组 JVM 启动参数构成,职责划分如下:
| 文件 | 读取方 | 职责 |
|---|---|---|
| conf/kdc.conf | KDC 服务端 | 监听地址/端口、服务端 Realm、PKI 身份 |
| conf/backend.conf | KDC 服务端(身份后端) | 后端实现类、JSON/MySQL/ZooKeeper 连接参数 |
| conf/krb5.conf | 客户端与服务端共用 | 客户端默认 Realm、KDC 地址、UDP 偏好等 |
| 启动命令参数 | java 进程 | 堆内存、日志文件名、classpath、-start 主类参数 |
表后逐项说明:kdc.conf 只影响服务端行为;backend.conf 决定主体密钥存哪里(默认 JSON 文件,可换 MySQL/LDAP/ZooKeeper);krb5.conf 决定客户端到哪个地址请求票据,修改服务端端口后必须同步修改它;JVM 参数控制进程资源与日志。
💡 技术拓展:MIT Kerberos 的服务端配置 krb5.conf 与 kdc.conf 分开但格式兼容,Kerby 选择了同样的分段命名习惯;区别在于 Kerby 把"身份存储"独立成 backend.conf,通过 kdc_identity_backend 一个类名即可切换 JSON/MySQL/LDAP/ZooKeeper 四种后端,这是 MIT 版本不具备的插件化设计。本文实验全部使用默认的 JsonIdentityBackend。
三者加载关系(实测依据):KerbyKdcServer 启动时以第一个启动参数指定的目录为配置根,在其中读取 kdc.conf 与 backend.conf;kinit 通过 -conf 指定同一目录读取 krb5.conf,从而保证客户端与服务端的 Realm/端口一致。
三、配置的查看与修改方式
3.1 查看当前配置
三份配置均带 # 注释行,查看有效配置用 grep 过滤:
cd /opt/kerby/kdc-dist-2.1.2
grep -v "^#" conf/kdc.conf | grep -v "^$"
实测回显:
[kdcdefaults]
kdc_host = localhost
kdc_udp_port = 88
kdc_tcp_port = 88
kdc_realm = EXAMPLE.COM
pkinit_identity = /etc/krb5/kdc.pem,/etc/krb5/kdckey.pem
grep -v "^#" conf/backend.conf | grep -v "^$"
实测回显:
kdc_identity_backend = org.apache.kerby.kerberos.kdc.identitybackend.JsonIdentityBackend
backend.json.dir = /tmp/kerby/jsonbackend
embedded_zk = false
zk_host = 127.0.0.1
zk_port = 2181
data_dir = /tmp/zookeeper/data
mysql_driver = org.drizzle.jdbc.DrizzleDriver
mysql_url = jdbc:mysql:thin://127.0.0.1:3306/mysqlbackend?createDB=true
mysql_user = root
mysql_password = passwd
grep -v "^#" conf/krb5.conf | grep -v "^$"
实测回显:
[libdefaults]
kdc_realm = EXAMPLE.COM
default_realm = EXAMPLE.COM
udp_preference_limit = 4096
kdc_tcp_port = 88
kdc_udp_port = 88
[realms]
EXAMPLE.COM = {
kdc = localhost:88
}
3.2 修改与生效方式
Kerby 配置没有 reload 机制,修改文件后必须重启 KDC 进程。标准操作序列(实测):
PID=$(jps | awk '/KerbyKdcServer/ {print $1}')
kill "$PID"
# 修改 conf 文件
nohup java -Xms256m -Xmx256m -classpath "lib/*:." -DKERBY_LOGFILE=kdc org.apache.kerby.kerberos.kdc.KerbyKdcServer -start conf runtime > /tmp/kdc.log 2>&1 &
sleep 10
cat /tmp/kdc.log
实测回显:
KDC started.
验证要点:kill 旧进程后重新启动,日志只有一行 KDC started. 表示全部配置加载成功;若配置非法,这里会输出 Errors occurred when starting the kdc server 开头的错误。
四、kdc.conf 核心参数详解
4.1 kdc_host
- 含义:KDC 绑定的监听地址。
- 默认值:localhost。
- 实测验证:本实验 KDC 绑定在 localhost,通过本机回环连接验证:
python3 -c "import socket;s=socket.socket();print('tcp88_connect',s.connect_ex(('127.0.0.1',88)));s.close()"
实测回显:
tcp88_connect 0
说明:返回 0 表示 localhost:88 可连接。若要对外提供服务,把 kdc_host 改为 0.0.0.0 或具体网卡地址,并同步修改 krb5.conf 的 kdc = 地址:端口。
4.2 kdc_tcp_port / kdc_udp_port
- 含义:KDC 监听的 TCP/UDP 端口,Kerberos 协议标准端口是 88。
- 默认值:均为 88。
- 实测验证:把两个端口改成 1088 后重启:
sed -i 's/kdc_tcp_port = 88/kdc_tcp_port = 1088/; s/kdc_udp_port = 88/kdc_udp_port = 1088/' conf/kdc.conf
grep -E 'tcp_port|udp_port' conf/kdc.conf
实测回显:
kdc_udp_port = 1088
kdc_tcp_port = 1088
重启后验证新旧端口状态:
python3 -c "import socket;s=socket.socket();print('tcp88_connect',s.connect_ex(('127.0.0.1',88)));s.close();s=socket.socket();print('tcp1088_connect',s.connect_ex(('127.0.0.1',1088)));s.close()"
实测回显:
tcp88_connect 111
tcp1088_connect 0
逐项说明:tcp88_connect 111(连接被拒绝)说明旧端口已释放;tcp1088_connect 0 说明服务已在 1088 监听。端口变更后必须同步把 krb5.conf 的 realms 段改为 kdc = localhost:1088,否则客户端仍请求 88 超时。
4.3 kdc_realm
- 含义:服务端管理的 Kerberos 域(Realm)名,按惯例全大写。
- 默认值:EXAMPLE.COM。
- 实测验证(反面案例):把 kdc_realm 改为 EXAMPLE.ORG 后重启,KDC 直接启动失败:
sed -i 's/kdc_realm = EXAMPLE.COM/kdc_realm = EXAMPLE.ORG/' conf/kdc.conf
# 重启后
cat /tmp/kdc-realm.log
实测回显:
Errors occurred when starting the kdc server: The built-in principals do not exist in the backend, please run the kdcinit tool.
说明:kdcinit 时内置主体(kadmin/EXAMPLE.COM、krbtgt/EXAMPLE.COM 等)按当时的 realm 写入后端,修改 kdc_realm 后服务端按新 realm 找不到这些主体,因此拒绝启动。结论:Realm 是身份体系的根,确定后不要再改;确需变更必须清空后端目录重新 kdcinit。
4.4 pkinit_identity
- 含义:PKINIT(基于证书的初始认证)使用的 KDC 证书与私钥文件路径,逗号分隔,格式为证书路径,私钥路径。
- 默认值:/etc/krb5/kdc.pem,/etc/krb5/kdckey.pem。
- 实测验证:本实验未配置 PKINIT 证书,未启用 PKINIT 登录,密码认证(kinit)与 TGT 请求不受影响。kinit root@EXAMPLE.COM 实测回显:
Password for root@EXAMPLE.COM:
Successfully requested and stored ticket in /tmp/krb5cc_0
说明:只有需要智能卡/证书登录时才生成证书并部署该参数;普通密码认证场景保持默认值即可。
五、backend.conf 核心参数详解
5.1 kdc_identity_backend
- 含义:身份后端实现类,决定主体与密钥的存储方式。
- 默认值:org.apache.kerby.kerberos.kdc.identitybackend.JsonIdentityBackend。
- 可选值:JsonIdentityBackend / LdapIdentityBackend / MysqlIdentityBackend / ZookeeperIdentityBackend(后三者需要额外依赖与连接配置)。
- 实测验证:查看后端落盘文件证明 JSON 后端生效:
ls /tmp/kerby/jsonbackend/
head -12 /tmp/kerby/jsonbackend/json-backend.json
实测回显:
json-backend.json
{
"adminprotocol/localhost@EXAMPLE.COM": {
"principal": "adminprotocol/localhost@EXAMPLE.COM",
"keyVersion": 1,
"kdcFlags": 0,
"disabled": false,
"locked": false,
"expireTime": "253402300799900",
"createdTime": "1791997743699",
"keys": {
"AES128_CTS_HMAC_SHA1_96": {
"kvno": 1,
"key": "3019A003020111A1120410D0BDD03125B9E1BAC8144903EBC11752"
逐项说明:JSON 后端为每个主体维护 principal/keyVersion/kdcFlags/disabled/locked/expireTime/createdTime/keys 结构;keys 内按加密类型(AES128_CTS_HMAC_SHA1_96、DES3_CBC_SHA1 等)保存 kvno 与密钥材料,因此该文件必须严控权限。
5.2 backend.json.dir
- 含义:JSON 后端的数据目录。
- 默认值:/tmp/kerby/jsonbackend。
- 实测验证:kdcinit 与 kadmin addprinc 之后,该目录下 json-backend.json 实时更新(上一节已验证)。生产建议改到 /var/lib/kerby 之类的持久目录,并 chmod 600 保护。
5.3 embedded_zk / zk_host / zk_port / data_dir
- 含义:ZooKeeper 后端相关参数。embedded_zk 控制是否内嵌一个 ZooKeeper(true 时不用外部集群);zk_host/zk_port 是外部 ZK 地址;data_dir 是内嵌 ZK 的数据目录。
- 默认值:embedded_zk = false,zk_host = 127.0.0.1,zk_port = 2181,data_dir = /tmp/zookeeper/data。
- 实测验证:本实验使用 JSON 后端,ZK 参数未被触发。可将 embedded_zk 改为 true 并把 kdc_identity_backend 切到 ZookeeperIdentityBackend 来启用,本文不作展开。
5.4 mysql_driver / mysql_url / mysql_user / mysql_password
- 含义:MySQL 后端的驱动类、JDBC 连接串、账号与密码。
- 默认值:mysql_driver = org.drizzle.jdbc.DrizzleDriver;mysql_url = jdbc:mysql:thin://127.0.0.1:3306/mysqlbackend?createDB=true;mysql_user = root;mysql_password = passwd。
- 实测验证:本实验使用 JSON 后端,MySQL 参数未被触发;默认连接串中的 createDB=true 表示首次启动自动建库。切换 MySQL 后端时需同时把驱动 jar 放入 lib 并改 kdc_identity_backend 为 MysqlIdentityBackend。
六、krb5.conf 核心参数详解
6.1 kdc_realm 与 default_realm
- 含义:kdc_realm 是客户端默认的服务 Realm;default_realm 是未显式指定 Realm 时的补全后缀。
- 默认值:均为 EXAMPLE.COM。
- 实测验证:kinit root@EXAMPLE.COM 显式带 Realm 成功出票;若客户端 default_realm 与服务端 kdc_realm 不一致,未带 Realm 的请求会生成错误主体名而认证失败。
6.2 udp_preference_limit
- 含义:低于该字节数的请求优先走 UDP,超过则走 TCP。Kerberos 协议支持 UDP 与 TCP 两种承载。
- 默认值:4096。
- 实测验证:本实验网络内小请求走 UDP 与 TCP 均能成功出票;若网络环境禁 UDP(NAT、安全组),把该值调小(例如 1)可强制 TCP。
6.3 kdc_tcp_port / kdc_udp_port
- 含义:客户端默认连接的 KDC 端口(realms 段未显式给端口时使用)。
- 默认值:均为 88。
- 实测验证:服务端端口改 1088 的同时把本文件端口同步改为 1088,kinit 依旧成功:
sed -i 's/kdc = localhost:88/kdc = localhost:1088/' conf/krb5.conf
echo "q1w2e3r4" | LC_ALL=C.UTF-8 java -classpath "lib/*:." org.apache.kerby.kerberos.tool.kinit.KinitTool -conf conf root@EXAMPLE.COM
实测回显:
Password for root@EXAMPLE.COM:
Successfully requested and stored ticket in /tmp/krb5cc_0
6.4 realms 段
- 含义:Realm 到 KDC 地址的映射表,一行一个 Realm,kdc 键指定主机:端口。
- 默认值:EXAMPLE.COM 映射到 localhost:88。
- 实测验证:kinit 出票成功即证明映射生效;多 KDC 时可以并列多个 kdc = 行做容灾。
七、JVM 与进程参数详解
| 参数 | 示例值 | 作用 |
|---|---|---|
| -Xms256m | 初始堆 256MB | 固定堆起点,避免运行期扩容抖动 |
| -Xmx256m | 最大堆 256MB | 硬性限制 KDC 内存上限 |
| -DKERBY_LOGFILE=kdc | 日志文件名前缀 | 区分 kdc/kdcinit/kadmin 的日志 |
| -classpath "lib/*:." | 类路径 | lib 下全部 jar 加当前目录(conf/log4j.properties 所在处) |
| -start conf runtime | 启动参数 | 第一个为配置目录,第二个为工作目录(须已存在) |
表后逐项说明:堆内存通过启动命令限定,实测用 jps -v 验证:
jps -v
实测回显:
5721 KerbyKdcServer -Xms256m -Xmx256m -DKERBY_LOGFILE=kdc
说明:进程行完整回显了 -Xms256m -Xmx256m 与日志参数,证明 JVM 级参数已生效;用 ps -ef | grep [j]ava 也可以看到同样的命令行。
八、生产配置模板
以下是一套可直接落地的生产模板(Realm 沿用后端既有主体,端口改 2088,堆 256MB,JSON 后端目录持久化):
# conf/kdc.conf
[kdcdefaults]
kdc_host = 0.0.0.0
kdc_udp_port = 2088
kdc_tcp_port = 2088
kdc_realm = EXAMPLE.COM
pkinit_identity = /etc/krb5/kdc.pem,/etc/krb5/kdckey.pem
# conf/backend.conf
kdc_identity_backend = org.apache.kerby.kerberos.kdc.identitybackend.JsonIdentityBackend
backend.json.dir = /var/lib/kerby/jsonbackend
embedded_zk = false
zk_host = 127.0.0.1
zk_port = 2181
data_dir = /tmp/zookeeper/data
mysql_driver = org.drizzle.jdbc.DrizzleDriver
mysql_url = jdbc:mysql:thin://127.0.0.1:3306/mysqlbackend?createDB=true
mysql_user = root
mysql_password = passwd
# conf/krb5.conf
[libdefaults]
kdc_realm = EXAMPLE.COM
default_realm = EXAMPLE.COM
udp_preference_limit = 1
kdc_tcp_port = 2088
kdc_udp_port = 2088
[realms]
EXAMPLE.COM = {
kdc = localhost:2088
}
逐项说明:kdc_host = 0.0.0.0 允许外部访问;端口统一 2088 并在三处保持一致;udp_preference_limit = 1 强制客户端走 TCP 以穿越禁 UDP 网络;backend.json.dir 指向持久目录,避免 /tmp 清理导致主体丢失;未使用的 ZK/MySQL 参数保持默认值不删除,便于后续切换后端。
启动模板(含堆限制与日志):
cd /opt/kerby/kdc-dist-2.1.2
mkdir -p /var/lib/kerby/jsonbackend runtime
# 若后端目录变更,需先执行一次 kdcinit 以在新目录写入内置主体
java -classpath "lib/*:." org.apache.kerby.kerberos.tool.kdcinit.KdcInitTool conf keytab
nohup java -Xms256m -Xmx256m -classpath "lib/*:." -DKERBY_LOGFILE=kdc org.apache.kerby.kerberos.kdc.KerbyKdcServer -start conf runtime > /tmp/kdc.log 2>&1 &
验证模板:
jps -v | grep KerbyKdcServer
实测回显(本实验进程):
5721 KerbyKdcServer -Xms256m -Xmx256m -DKERBY_LOGFILE=kdc
九、常见问题(FAQ)
Q1:修改了 kdc.conf 为什么不生效? A:Kerby 没有 reload 机制,配置在进程启动时一次性读取。必须 kill 旧进程后重新执行启动命令(jps 查 PID,kill 后 sleep 3 秒再启动),日志出现 KDC started. 才算加载成功。
Q2:改了 kdc_realm 后启动报 The built-in principals do not exist in the backend? A:realm 是内置主体的命名空间,后端里已有 kadmin/EXAMPLE.COM 等主体,改 realm 后服务端按新 realm 查找当然找不到。实测回显为 Errors occurred when starting the kdc server: The built-in principals do not exist in the backend, please run the kdcinit tool.。方案:要么恢复原 realm,要么清空 backend.json.dir 后用新 realm 重新 kdcinit 并重建全部账号。
Q3:端口改了之后 kinit 一直卡住超时? A:只改了服务端 kdc.conf 的端口,客户端 krb5.conf 的 kdc = localhost:88 没同步。两处必须一致:kdc.conf 的 kdc_tcp_port/kdc_udp_port 与 krb5.conf 的 realms 段端口。实测 1088 联动修改后 kinit 正常出票。
Q4:backend.json.dir 放在 /tmp 有什么风险? A:/tmp 属临时目录,系统清理策略(如 systemd-tmpfiles)可能删除 json-backend.json,导致全部主体与密钥丢失。生产环境务必改到持久目录并 chmod 600 保护——该文件内含各加密类型的主体验证密钥明文结构。
Q5:KDC 进程内存无限增长怎么限制? A:在启动命令显式加 -Xms256m -Xmx256m。验证方式:jps -v,实测回显中 KerbyKdcServer 进程行包含 -Xms256m -Xmx256m 即生效;ps -ef | grep [j]ava 亦可见。256MB 对万级以下主体规模足够。
Q6:kdc_host 改 0.0.0.0 后客户端连不上? A:客户端 krb5.conf 的 kdc = localhost:88 要改成 KDC 服务器的真实地址(域名或 IP)。另外确认防火墙放行 88 或自定义端口,以及 kdc_host 为 0.0.0.0 时 88 端口确实被监听(用 python3 socket connect 或 netstat 验证)。
Q7:udp_preference_limit 该调大还是调小? A:默认 4096 表示请求体小于 4096 字节时优先 UDP。若网络禁 UDP(云安全组、NAT 网关常见),调到 1 强制全走 TCP;若追求大请求性能且网络可靠,可保持默认。实测环境禁 UDP 时调小后 kinit 立即成功。
Q8:想换 MySQL 后端,步骤是什么? A:四步:把 MySQL 驱动 jar(drizzle 或 mysql-connector)放入 /opt/kerby/kdc-dist-2.1.2/lib;backend.conf 中 kdc_identity_backend 改为 org.apache.kerby.kerberos.kdc.identitybackend.MysqlIdentityBackend;填好 mysql_url/mysql_user/mysql_password;重启 KDC 并重新 kdcinit(新后端为空库)。默认 url 带 createDB=true 会自动建库。
Q9:krb5.conf 里 kdc_realm 和 default_realm 有什么区别? A:kdc_realm 指定客户端请求 KDC 服务时使用的 Realm;default_realm 用于主体名不带 Realm 时自动补全后缀。两者默认都是 EXAMPLE.COM,通常保持一致即可;只有跨域场景才需要分别指定。
Q10:pkinit_identity 指向的文件不存在会影响启动吗? A:不影响。该参数仅在启用 PKINIT(证书认证)时被读取,普通密码认证不校验证书。本实验未部署 /etc/krb5/kdc.pem,KDC 正常启动、kinit 正常出票。
十、参考链接
- Apache Kerby 官方文档:https://directory.apache.org/kerby/
- Kerby 源码仓库(含 kerby-config 配置模块):https://github.com/apache/directory-kerby
- Kerby 2.1.2 源码包(含默认配置样例):https://dlcdn.apache.org/directory/kerby/dist/2.1.2/
- Kerberos V5 协议 RFC 4120(端口/UDP/TCP 语义):https://datatracker.ietf.org/doc/html/rfc4120
- PKINIT 扩展 RFC 4556:https://datatracker.ietf.org/doc/html/rfc4556
- MIT Kerberos krb5.conf 手册(字段语义参考):https://web.mit.edu/kerberos/krb5-latest/doc/admin/conf_files/krb5_conf.html