Kafka Python SSL配置报错:主机名不匹配,证书无效求助
问题分析与解决方案
核心问题
出现Hostname mismatch错误的根本原因:
- Kafka服务器证书的主机名(CN/SAN)未包含客户端连接时使用的
kafka-1主机名 - Kafka内部通信监听器配置冲突
- Python客户端误用了CA证书而非专属客户端证书
具体修正步骤
1. 修正Kafka配置
修改docker-compose-kafka.env文件:
- 移除
KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181(与docker-compose中zookeeper:32181的配置冲突,以docker-compose设置为准) - 将
KAFKA_INTER_BROKER_LISTENER_NAME=EXTERNAL改为KAFKA_INTER_BROKER_LISTENER_NAME=INTERNAL(内部broker通信使用PLAINTEXT协议的INTERNAL监听器,避免不必要的SSL握手问题) - (可选)将
KAFKA_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM=改为KAFKA_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM=HTTPS,确保主机名验证机制生效
确认docker-compose.yml监听器逻辑:
当前KAFKA_ADVERTISED_LISTENERS配置合理,对应两种访问场景:
INTERNAL://kafka-1:29092:Docker网络内的PLAINTEXT协议访问EXTERNAL://localhost:9092:宿主机外部的SSL协议访问
若需要Docker内客户端也用SSL访问,可新增SSL监听端口:
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka-1:29092,EXTERNAL://localhost:9092,INTERNAL_SSL://kafka-1:9093 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:SSL,INTERNAL_SSL:SSL
后续py-app客户端可连接kafka-1:9093
2. 重新生成包含正确主机名的Kafka服务器证书
服务器证书需同时支持kafka-1和localhost两个主机名,覆盖Docker内部与外部访问场景:
- 创建证书配置文件
server-cert.cnf:
[req] distinguished_name = req_distinguished_name req_extensions = v3_req prompt = no [req_distinguished_name] CN = kafka-1 [v3_req] keyUsage = keyEncipherment, dataEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names [alt_names] DNS.1 = kafka-1 DNS.2 = localhost
- 重新生成服务器密钥库与证书请求:
# 删除旧密钥库(若存在) rm kafka.server.keystore.jks # 生成服务器密钥库 keytool -keystore kafka.server.keystore.jks -alias kafka-1 -keyalg RSA -validity 365 -genkey -storepass 123456 -keypass 123456 -dname "CN=kafka-1, OU=Dev, O=Example, L=City, ST=State, C=CN" # 生成带SAN扩展的证书请求 keytool -keystore kafka.server.keystore.jks -alias kafka-1 -certreq -file cert-file -storepass 123456 -keypass 123456 -ext SAN=dns:kafka-1,dns:localhost
- 用CA签名证书请求:
openssl x509 -req -CA ca-cert -CAkey ca-key -in cert-file -out cert-signed -days 365 -CAcreateserial -passin pass:123456 -extfile server-cert.cnf -extensions v3_req
- 导入CA证书与签名后的证书到服务器密钥库:
keytool -keystore kafka.server.keystore.jks -alias CARoot -importcert -file ca-cert -storepass 123456 -noprompt keytool -keystore kafka.server.keystore.jks -alias kafka-1 -importcert -file cert-signed -storepass 123456 -noprompt
- 重新导出CA的PEM文件(若需要):
keytool -exportcert -alias CARoot -keystore kafka.server.keystore.jks -rfc -file CARoot.pem -storepass 123456
3. 生成Python客户端双向认证证书
因Kafka配置了KAFKA_SSL_CLIENT_AUTH=required,客户端必须提供专属证书:
- 生成客户端密钥库:
keytool -keystore kafka.client.keystore.jks -alias kafka-client -keyalg RSA -validity 365 -genkey -storepass 123456 -keypass 123456 -dname "CN=kafka-client, OU=Dev, O=Example, L=City, ST=State, C=CN"
- 生成客户端证书请求并签名:
keytool -keystore kafka.client.keystore.jks -alias kafka-client -certreq -file client-cert-file -storepass 123456 -keypass 123456 openssl x509 -req -CA ca-cert -CAkey ca-key -in client-cert-file -out client-cert-signed -days 365 -CAcreateserial -passin pass:123456
- 导入CA证书与签名后的客户端证书到客户端密钥库:
keytool -keystore kafka.client.keystore.jks -alias CARoot -importcert -file ca-cert -storepass 123456 -noprompt keytool -keystore kafka.client.keystore.jks -alias kafka-client -importcert -file client-cert-signed -storepass 123456 -noprompt
- 导出客户端证书与密钥为PEM格式(适配Python Kafka库要求):
# 导出客户端证书 keytool -exportcert -alias kafka-client -keystore kafka.client.keystore.jks -rfc -file client-cert.pem -storepass 123456 # 导出客户端密钥并转换为PEM keytool -importkeystore -srckeystore kafka.client.keystore.jks -srcalias kafka-client -destkeystore client-key.p12 -deststoretype PKCS12 -srcstorepass 123456 -deststorepass 123456 openssl pkcs12 -in client-key.p12 -nocerts -out client-key.pem -passin pass:123456 -passout pass:123456
4. 修正Python客户端代码
替换为正确的客户端证书文件:
from kafka import KafkaProducer producer = KafkaProducer(bootstrap_servers='kafka-1:9092', security_protocol='SSL', ssl_check_hostname=True, ssl_cafile='/ssl2/py2/ca-cert', ssl_certfile='/ssl2/py2/client-cert.pem', ssl_keyfile='/ssl2/py2/client-key.pem', ssl_password='123456') producer.send("example", bytes('Hello Kafka!123','utf-8')) producer.flush()
5. 重启服务
清理旧容器并重新启动:
docker-compose down -v docker-compose up -d
内容的提问来源于stack exchange,提问作者bgr11n
相关产品推荐
相关产品推荐

