跳至正文
老丹的足迹 —— 代码写给机器,游记写给自己,感悟写给时间
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面

Mosquitto TLS/SSL 加密配置完全指南

摘要

TLS/SSL 是为 Mosquitto MQTT Broker 提供传输层加密和安全认证的核心技术。本文从 TLS 的基本原理出发,系统性地介绍证书体系、生成步骤、配置方法、客户端集成以及运维管理,帮助读者在生产环境中部署安全的 MQTT 加密通信。

第一部分:TLS 概述

1.1 什么是 TLS

TLS(Transport Layer Security,传输层安全协议)是 SSL(Secure Sockets Layer)的继任者,为网络通信提供加密、认证和数据完整性保护。

在 Mosquitto 中,TLS 可以实现:

功能说明
传输加密所有 MQTT 消息加密传输,防止网络窃听
服务器身份认证客户端验证 Broker 是否可信(防止中间人攻击)
客户端身份认证可选的双向 TLS,Broker 验证客户端身份

1.2 为什么需要 TLS

1.3 密码认证 vs TLS 加密

对比维度密码认证TLS 加密
作用验证客户端身份(你是谁)加密传输内容(防窃听)
解决什么问题防止非法设备接入防止密码被截获、消息泄露
是否加密数据❌ 不加密✅ 全链路加密
能否单独使用✅ 可以(但不安全)⚠️ 可以(但无法认证身份)
标准端口1883(明文)8883(加密)

结论:密码认证 + TLS 加密 = 既验证身份,又加密传输。生产环境必须同时使用。

第二部分:证书体系

2.1 证书信任链

TLS 依赖一套证书信任链来建立信任关系:

2.2 证书文件说明

文件用途权限持有方
ca.crtCA 根证书,验证服务器身份644Broker + 所有客户端
ca.keyCA 私钥,签发证书用600仅证书管理员(Broker 不需要)
server.crt服务器证书,证明 Broker 身份644Broker
server.key服务器私钥,TLS 握手用600Broker
client.crt客户端证书(双向 TLS)644客户端
client.key客户端私钥(双向 TLS)600客户端

2.3 TLS 模式对比

模式服务器提供证书客户端提供证书适用场景
无 TLS❌❌内网测试(不安全)
单向 TLS✅❌公网部署,客户端只需验证服务器
双向 TLS (mTLS)✅✅高安全环境,服务器也验证客户端

第三部分:证书生成

3.1 生成 CA 根证书

# 创建证书目录
sudo mkdir -p /etc/mosquitto/certs
cd /etc/mosquitto/certs

# 生成 CA 私钥
sudo openssl genrsa -out ca.key 2048

# 生成 CA 根证书(有效期 10 年)
sudo openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/CN=MQTT-CA"

# 查看证书内容
openssl x509 -in ca.crt -text -noout

参数说明:

参数含义说明
genrsa生成 RSA 私钥非对称加密算法
-out输出文件指定私钥文件路径
2048密钥长度安全要求至少 2048 位
req证书请求工具创建证书签名请求或自签名证书
-new新建证书生成新证书
-x509自签名证书输出根证书(不是 CSR)
-days有效期单位:天
-key使用的私钥指定私钥文件
-subj证书主体信息见下方详解

-subj 参数详解:

/C=CN          Country(国家)            → 2位字母
/ST=Beijing    State/Province(省份)     → 省/州
/L=Beijing     Locality(城市)           → 城市
/O=MyCompany   Organization(组织)       → 公司名
/CN=MQTT-CA    Common Name(通用名称)    → 唯一标识(CA 名称)

3.2 生成服务器证书

# 生成服务器私钥
sudo openssl genrsa -out server.key 2048

# 生成证书签名请求
sudo openssl req -new -key server.key -out server.csr \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/CN=mqtt.example.com"

# 使用 CA 签发服务器证书
sudo openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -out server.crt -days 365

# 设置权限
sudo chmod 600 server.key

关键点:

CN 字段必须填写 Broker 的域名或 IP 地址

  • 使用域名:/CN=mqtt.example.com
  • 使用 IP:/CN=192.168.1.10

如果 CN 不匹配,客户端连接会报证书验证失败。

3.3 生成客户端证书(双向 TLS)

# 生成客户端私钥
sudo openssl genrsa -out client.key 2048

# 生成客户端证书签名请求
sudo openssl req -new -key client.key -out client.csr \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/CN=device_001"

# 使用 CA 签发客户端证书
sudo openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -out client.crt -days 365

# 设置权限
sudo chmod 600 client.key

3.4 生成脚本(一键生成所有证书)

#!/bin/bash
# generate-certs.sh - 一键生成所有证书

set -e

CERT_DIR="/etc/mosquitto/certs"
SERVER_CN="mqtt.example.com"  # 修改为你的域名或 IP

echo "=== 开始生成 TLS 证书 ==="

# 创建目录
sudo mkdir -p $CERT_DIR
cd $CERT_DIR

# 1. 生成 CA
echo "1. 生成 CA 根证书..."
sudo openssl genrsa -out ca.key 2048
sudo openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/CN=MQTT-CA"

# 2. 生成服务器证书
echo "2. 生成服务器证书 (CN=$SERVER_CN)..."
sudo openssl genrsa -out server.key 2048
sudo openssl req -new -key server.key -out server.csr \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/CN=$SERVER_CN"
sudo openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -out server.crt -days 365

# 3. 设置权限
echo "3. 设置权限..."
sudo chmod 600 ca.key server.key
sudo chown -R mosquitto:mosquitto $CERT_DIR

echo "✅ 证书生成完成!"
echo "📁 证书目录: $CERT_DIR"
echo "📋 文件清单:"
ls -la $CERT_DIR

第四部分:Mosquitto TLS 配置

4.1 单向 TLS 配置

sudo tee /etc/mosquitto/conf.d/tls.conf << 'EOF'
# ================================================================
#                    TLS/SSL 加密配置(单向 TLS)
# ================================================================

# TLS 加密监听端口
listener 8883 0.0.0.0

# 服务器证书和私钥
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key

# CA 证书(客户端用它验证服务器)
cafile /etc/mosquitto/certs/ca.crt

# TLS 版本(推荐 tlsv1.2 或 tlsv1.3)
tls_version tlsv1.2

# 加密套件(推荐安全套件)
ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256
EOF

4.2 双向 TLS 配置(mTLS)

sudo tee /etc/mosquitto/conf.d/tls-mtls.conf << 'EOF'
# ================================================================
#                    TLS/SSL 加密配置(双向 TLS)
# ================================================================

listener 8883 0.0.0.0

# 服务器证书
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
cafile /etc/mosquitto/certs/ca.crt

# 强制客户端提供证书
require_certificate true

# 使用证书 CN 作为用户名(简化 ACL 配置)
use_identity_as_username true

tls_version tlsv1.2
EOF

4.3 完整安全配置(密码 + TLS + ACL)

sudo tee /etc/mosquitto/conf.d/security.conf << 'EOF'
# ================================================================
#                    完整安全配置
# ================================================================

# ---------- 监听器 ----------
listener 1883 192.168.1.10    # 内网明文(仅内网访问)
listener 8883 0.0.0.0         # 公网 TLS

# ---------- TLS ----------
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
cafile /etc/mosquitto/certs/ca.crt
tls_version tlsv1.2

# ---------- 认证 ----------
allow_anonymous false
password_file /etc/mosquitto/passwd

# ---------- 授权 ----------
acl_file /etc/mosquitto/aclfile
EOF

第五部分:客户端 TLS 连接

5.1 命令行客户端

单向 TLS

# 订阅
mosquitto_sub -h mqtt.example.com -p 8883 \
  -t "test" \
  --cafile /etc/mosquitto/certs/ca.crt \
  -u admin -P 密码 -v

# 发布
mosquitto_pub -h mqtt.example.com -p 8883 \
  -t "test" -m "hello" \
  --cafile /etc/mosquitto/certs/ca.crt \
  -u admin -P 密码

双向 TLS

# 双向 TLS 连接
mosquitto_sub -h mqtt.example.com -p 8883 \
  -t "devices/device_001/command/+" \
  --cafile /etc/mosquitto/certs/ca.crt \
  --cert /etc/mosquitto/certs/client.crt \
  --key /etc/mosquitto/certs/client.key \
  -v

5.2 Python (paho-mqtt)

import paho.mqtt.client as mqtt

# ================================================================
# 单向 TLS
# ================================================================
client = mqtt.Client()
client.tls_set(
    ca_certs="/path/to/ca.crt",        # CA 证书(必需)
    cert_reqs=mqtt.ssl.CERT_REQUIRED,  # 要求服务器提供证书
    tls_version=mqtt.ssl.PROTOCOL_TLSv1_2
)
client.username_pw_set("sensor_001", "password")
client.connect("mqtt.example.com", 8883, 60)
client.loop_forever()

# ================================================================
# 双向 TLS
# ================================================================
client.tls_set(
    ca_certs="/path/to/ca.crt",
    certfile="/path/to/client.crt",    # 客户端证书
    keyfile="/path/to/client.key",     # 客户端私钥
    cert_reqs=mqtt.ssl.CERT_REQUIRED,
    tls_version=mqtt.ssl.PROTOCOL_TLSv1_2
)

5.3 Node.js (mqtt.js)

const mqtt = require('mqtt')
const fs = require('fs')

// 单向 TLS
const client = mqtt.connect('mqtts://mqtt.example.com:8883', {
  ca: fs.readFileSync('/path/to/ca.crt'),
  username: 'sensor_001',
  password: 'password',
  rejectUnauthorized: true,
  protocol: 'mqtts'
})

// 双向 TLS
const client2 = mqtt.connect('mqtts://mqtt.example.com:8883', {
  ca: fs.readFileSync('/path/to/ca.crt'),
  cert: fs.readFileSync('/path/to/client.crt'),
  key: fs.readFileSync('/path/to/client.key'),
  username: 'sensor_001',
  password: 'password',
  rejectUnauthorized: true,
  protocol: 'mqtts'
})

5.4 证书在项目中的存放

项目目录/
├── certs/
│   ├── ca.crt              # CA 证书(所有客户端都需要)
│   ├── client_001.crt      # 每个客户端独立证书
│   ├── client_001.key      # 客户端私钥(需严格保密)
│   └── client_002.crt
│   └── client_002.key
├── src/
│   ├── main.py
│   └── ...
└── config/
    └── config.json         # 配置中引用证书路径
// config.json
{
  "mqtt": {
    "broker": "mqtt.example.com",
    "port": 8883,
    "tls": {
      "ca_cert": "certs/ca.crt",
      "client_cert": "certs/client_001.crt",
      "client_key": "certs/client_001.key"
    },
    "username": "sensor_001",
    "password": "password"
  }
}

第六部分:运维管理

6.1 证书有效期管理

# 查看证书有效期
openssl x509 -in /etc/mosquitto/certs/server.crt -noout -dates

# 输出示例:
# notBefore=Jan 15 00:00:00 2024 GMT
# notAfter=Jan 15 00:00:00 2025 GMT

6.2 证书续期检查脚本

#!/bin/bash
# check-cert-expiry.sh - 检查证书过期时间

DAYS_WARNING=30
CERT_DIR="/etc/mosquitto/certs"

echo "=== 证书有效期检查 ==="

for cert in $CERT_DIR/*.crt; do
    if [ -f "$cert" ]; then
        END_DATE=$(openssl x509 -in "$cert" -noout -enddate | cut -d= -f2)
        END_EPOCH=$(date -d "$END_DATE" +%s)
        NOW_EPOCH=$(date +%s)
        DAYS_LEFT=$(( ($END_EPOCH - $NOW_EPOCH) / 86400 ))

        if [ $DAYS_LEFT -lt 0 ]; then
            echo "❌ $cert 已过期!"
        elif [ $DAYS_LEFT -lt $DAYS_WARNING ]; then
            echo "⚠️  $cert 将在 $DAYS_LEFT 天后过期"
        else
            echo "✅ $cert 还有 $DAYS_LEFT 天有效期"
        fi
    fi
done

6.3 证书续期步骤

# 1. 备份旧证书
sudo cp /etc/mosquitto/certs/server.crt /etc/mosquitto/certs/server.crt.bak
sudo cp /etc/mosquitto/certs/server.key /etc/mosquitto/certs/server.key.bak

# 2. 生成新服务器证书
cd /etc/mosquitto/certs
sudo openssl req -new -key server.key -out server.csr \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/CN=mqtt.example.com"
sudo openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -out server.crt -days 365

# 3. 重启 Mosquitto
sudo systemctl restart mosquitto

# 4. 验证新证书
openssl x509 -in server.crt -noout -dates

第七部分:故障排除

7.1 常见问题

问题可能原因解决方案
SSL_ERROR证书路径错误或权限不足检查文件路径和权限:ls -la /etc/mosquitto/certs/
Certificate verify failed客户端未信任 CA检查 --cafile 是否正确
Hostname mismatch证书 CN 与域名不匹配重新生成证书,CN 使用正确域名
SSL certificate expired证书过期重新签发证书
Connection refused端口未监听或防火墙拦截sudo ss -tlnp | grep 8883
no CA certificate客户端缺少 CA 证书确保 ca.crt 已拷贝到客户端

7.2 调试命令

# 1. 检查端口监听
sudo ss -tlnp | grep 8883

# 2. 测试 TLS 连接
openssl s_client -connect mqtt.example.com:8883 -CAfile ca.crt

# 3. 查看证书详情
openssl x509 -in server.crt -text -noout

# 4. 检查 Mosquitto 日志
sudo journalctl -u mosquitto -f

# 5. 前台调试模式
sudo systemctl stop mosquitto
sudo mosquitto -c /etc/mosquitto/mosquitto.conf -v

7.3 防火墙配置

# Ubuntu UFW
sudo ufw allow 8883/tcp

# CentOS/RHEL Firewalld
sudo firewall-cmd --permanent --add-port=8883/tcp
sudo firewall-cmd --reload

第八部分:最佳实践总结

8.1 安全配置检查清单

检查项状态
密码认证 (allow_anonymous false)✅
TLS 加密(端口 8883)✅
私钥权限 600✅
证书有效期 < 365 天✅
使用安全 TLS 版本(1.2 或 1.3)✅
使用安全加密套件✅
客户端验证服务器证书✅
定期检查证书有效期⚠️ 需计划

8.2 环境区分建议

环境TLS 配置密码认证
开发测试自签名证书,单向 TLS允许匿名或弱密码
预发布自签名或正式证书强密码
生产环境正式 CA 签发证书强密码 + 双向 TLS

8.3 证书管理原则

原则说明
私钥保密*.key 文件绝对不要上传到代码仓库
定期续期设置日历提醒,证书有效期通常 1 年
最小权限私钥文件仅 mosquitto 用户可读
审计日志记录证书签发和使用情况

结语

TLS 是 Mosquitto 公网部署的安全基石。它解决了明文传输的所有安全问题:

  1. 加密:保护消息内容不被窃听
  2. 认证:确保客户端连接到正确的服务器
  3. 完整性:防止消息在传输过程中被篡改

核心要点速记:

要点命令/配置
生成 CAopenssl req -new -x509 -key ca.key -out ca.crt
签发服务器证书openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key
Mosquitto 配置listener 8883 + certfile + keyfile
客户端连接--cafile ca.crt
检查证书openssl x509 -in server.crt -noout -dates
作者

老丹

关注我
其他文章
上一个

Mosquitto 完整安全配置指南

下一个

SOCKS5完全指南:从概念原理到协议细节的深度解读

关于博主

    老丹是一名C/C++后台开发工程师,信奉“无抽象不设计,无性能不生产”。

  • 技术栈:Modern C++、Linux环境编程、多线程/并发、网络编程等。
  • 信条:能用constexpr解决的问题绝不拖到运行时,能靠RAII避免的泄漏绝不写析构。
  • 正在填坑:从解封装到渲染的C++全链路实现,正在驯服FFmpeg与H.264/H.265。
  • 输出原则:这里的每一段代码都经过-Wall -Wextra -Werror -O2的洗礼。

近期文章

  • Linux系统的安全基石:深入理解可插拔认证模块(PAM) 2026年7月27日
  • vsftpd 完全指南:从核心原理到Docker容器化部署 2026年7月27日
  • 互联网的”导航”安全卫士:深入解读DNSSEC 2026年7月27日
  • Ubuntu DNS 配置完全指南 2026年7月27日
  • 在 Ubuntu 中使用 Certbot 的操作指南 2026年7月27日

文章分类

  • C/C++开发 (13)
  • Docker容器 (3)
  • Linux工具包 (10)
  • Linux服务配置 (33)
  • Linux系统 (10)
  • OpenWrt路由 (2)
  • Shell脚本 (3)
  • 安防技术 (4)
  • 数据安全 (30)
  • 网络协议 (17)
  • 计算机理论 (22)
联系我们:📍 地址:中国·广东省深圳市   |   ✉️ 邮箱:support@tanglinux.com   |   💬 QQ:870866607
版权所有:老丹的足迹粤ICP备2026061170号-1       公安备案图标 粤公网安备44030002013274号