mosquitto 开启 TLS 问题总结

正文

在使用 mosquitto 对 MQTT 开启 TLS 进行测试时,经常会遇到各种神奇的错误,但是 mosquitto 的日志却少的可怜,服务端能看到的日志大约就这几种:

SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca
SSL routines:ssl3_read_bytes:ssl handshake failure
Socket error on client <unknown>, disconnecting.

客户端能看到的日志也少得可怜:

Error: A TLS error occurred.

下面总结几种常见的错误:

  • 使用自签名证书时,CA证书 和 server证书 的 Comon Name 使用了相同的内容;这样会导致 OpenSSL 校验证书时失败,将 CA证书 和 server证书的 Comon Name 改成不同的内容即可;
  • 使用自签名证书时,server证书 的 Comon Name 与域名不相符,默认情况下客户端会连接错误,这时在连接时加入 --insecure 参数即可;
  • 使用自签名证书时,如果CA是单个文件,将 --cafile 参数错写成 --capath
  • 服务端开启双向认证 require_certificate true , 连接时没有传入客户端的证书和密钥;
  • 服务端与客户端的 TLS 版本不一致,服务端配置参数为 tls_version ,客户端配置参数为 --tls-version

当然,mosquitto 的日志不详细时,需要使用其他更有效的方式来诊断问题,这里提供一种有效的方式,使用 wireshark 来过滤底层通信数据,下面是使用 wireshark 的截图:
在这里插入图片描述
TLS Record 有四种类型:

  • change_cipher_spec (20)
  • alert (21)
  • handshake (22)
  • application_data (23)

通常在出现错误时都会通过 alert 消息来返回错误信息,所以可以通过 Alert 消息来诊断问题。上图中的 Alert 消息可以看出是CA证书 出了问题,这时可以检查 CA证书是否一致,是否加载成功等,然后找到问题并解决。

RFC5246 对 Alert 定义

/* https://tools.ietf.org/html/rfc5246#page-28 */

enum { warning(1), fatal(2), (255) } AlertLevel;

enum {
    close_notify(0),
    unexpected_message(10),
    bad_record_mac(20),
    decryption_failed_RESERVED(21),
    record_overflow(22),
    decompression_failure(30),
    handshake_failure(40),
    no_certificate_RESERVED(41),
    bad_certificate(42),
    unsupported_certificate(43),
    certificate_revoked(44),
    certificate_expired(45),
    certificate_unknown(46),
    illegal_parameter(47),
    unknown_ca(48),
    access_denied(49),
    decode_error(50),
    decrypt_error(51),
    export_restriction_RESERVED(60),
    protocol_version(70),
    insufficient_security(71),
    internal_error(80),
    user_canceled(90),
    no_renegotiation(100),
    unsupported_extension(110),
    (255)
} AlertDescription;

struct {
    AlertLevel level;
    AlertDescription description;
} Alert;

生成证书脚本

#!/usr/bin/env bash
# When OpenSSL prompts you for the Common Name for each certificate, use different names.

# CA key
openssl genrsa -out ca.key 2048
# CA csr
openssl req -new -subj "/CN=ca" -key ca.key -out ca.csr
# CA crt
openssl x509 -req -in ca.csr -out ca.crt -signkey ca.key -days 3650

# server key
openssl genrsa -out server.key 2048
# server.csr
openssl req -new -subj "/CN=server" -key server.key -out server.csr
# server.crt
openssl x509 -req -in server.csr -out server.crt -CA ca.crt -CAkey ca.key \
-CAcreateserial -days 3650
# server.crt verify
openssl verify -CAfile ca.crt  server.crt

# client key
openssl genrsa -out client.key 2048
# client.csr
openssl req -new -subj "/CN=client" -key client.key -out client.csr
# client.crt
openssl x509 -req -in client.csr -out client.crt -CA ca.crt -CAkey ca.key \
-CAcreateserial -days 3650
# client.crt verify
openssl verify -CAfile ca.crt  client.crt

配置文件

# Place your local configuration in /etc/mosquitto/conf.d/
#
# A full description of the configuration file is at
# /usr/share/doc/mosquitto/examples/mosquitto.conf.example

pid_file /var/run/mosquitto.pid

port 1883

persistence true
persistence_location /var/lib/mosquitto/

log_dest file /var/log/mosquitto/mosquitto.log

allow_anonymous false

password_file /root/mosquitto/pwfile
# acl_file /root/mosquitto/aclfile

listener 8883
cafile ca.crt
certfile server.crt
keyfile server.key

# one-way or two-way authentication
require_certificate true

生成用户名密码配置文件

# create pwfile and add user
mosquitto_passwd -c pwfile admin
# add user on pwfile with password
mosquitto_passwd -b pwfile admin admin
# add user on pwfile
mosquitto_passwd pwfile admin

测试命令

# insecure sub
mosquitto_sub -d \
    -k 30 \
    -h localhost -p 1883 \
    -t gateway/test0 \
    -u admin -P admin

# insecure pub
mosquitto_pub -d \
    -h localhost -p 1883 \
    -t gateway/test0 \
    -u admin -P admin \
    -m {"message":"THIS_IS_A_TEST_MESSAGE"}

# secure pub one-way and no-check CA common name
mosquitto_pub -d \
    -h localhost -p 8883 \
    -t gateway/test0 \
    -u admin -P admin \
    --cafile ca.crt \
    --insecure \
    -m {"message":"THIS_IS_A_TEST_MESSAGE"}

# secure pub two-way
mosquitto_pub -d \
    -h localhost -p 8883 \
    -t gateway/test0 \
    -u admin -P admin \
    --cafile ca.crt \
    --cert client.crt --key client.key \
    -m {"message":"THIS_IS_A_TEST_MESSAGE"}
    

参考文档:

  1. mosquitto.conf man page
  2. RFC 5246: The Transport Layer Security (TLS) Protocol
  3. Mosquitto SSL Configuration -MQTT TLS Security
  4. mosquitto日志报错SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca
发布了105 篇原创文章 · 获赞 230 · 访问量 36万+

猜你喜欢

转载自blog.csdn.net/aggresss/article/details/90380721
TLS