天天看点

CentOS8下Mosquitto安装使用指南

这里写自定义目录标题

    • 环境准备
      • 关闭linuxse
      • 打开防火墙端口
      • 配置dnf
      • 安装wget
      • 安装tar
      • 安装make
      • 安装g++
      • 安装openssl开发工具包
    • 安装Mosquitto
      • 下载编译
      • 配置启动
      • 设置开机启动
      • 测试
    • 安装mosquitto-go-auth
      • 安装go环境
      • 下载编译mosquitto-go-auth
      • 准备MySQL
        • 安装启动MySQL
        • 修改root密码
        • 准备数据库和表结构
        • 准备测试账号
      • 配置运行mosquitto-go-auth
        • 关闭匿名访问
        • 创建日志目录和配置日志设置
        • 配置mosquitto-go-auth插件相关设置
      • 测试一下
    • 配置TLS
      • 机器准备和命名
      • 使用openssl生成相关证书
        • 准备/etc/mosquitto/certs目录
        • Certificate Authority
        • Server
        • Client
      • TLS单向认证
        • 修改配置
        • 测试
        • TLS单向认证下的多个broker桥接
      • TLS双向认证
        • 修改配置
        • 测试
        • TLS双向认证下的多个broker桥接

环境准备

查看系统版本

cat /etc/redhat-release
           

CentOS Linux release 8.2.2004 (Core)

关闭linuxse

临时关闭:

setenforce 0

永久关闭:修改/etc/selinux/config 文件将SELINUX=enforcing改为SELINUX=disabled,然后重启

查看状态:

getenforce

打开防火墙端口

firewall-cmd --zone=public --add-port=1883/tcp --permanent
firewall-cmd --zone=public --add-port=8883/tcp --permanent
firewall-cmd --reload
           

配置dnf

vi /etc/dnf/dnf.conf
           

再最下方加入一行

fastestmirror=True
           

保存退出之后执行:

dnf clean all
dnf makecache
           

安装wget

dnf install wget -y

安装tar

dnf install tar -y

安装make

dnf install make -y

安装g++

dnf install gcc-c++ -y

安装openssl开发工具包

dnf install openssl-devel -y

安装Mosquitto

下载编译

wget https://mosquitto.org/files/source/mosquitto-1.6.10.tar.gz
tar -zxvf mosquitto-1.6.10.tar.gz
cd mosquitto-1.6.10
make
make install
           

配置启动

cd /etc/mosquitto/
mv mosquitto.conf.example  mosquitto.conf
mosquitto -c /etc/mosquitto/mosquitto.conf
           

出现如下错误:

1596531761: Error: Invalid user 'mosquitto'.
           

为解决此问题,需要给系统创建mosquitto用户和组:

groupadd mosquitto
useradd -g mosquitto mosquitto

chown -R mosquitto:mosquitto /etc/mosquitto/
           

创建完之后再次尝试启动,应该就能成功启动了。

如果要后台运行,则加入-d参数,完整命令如下:

mosquitto -c /etc/mosquitto/mosquitto.conf  -d
           

-c参数是指定配置文件,-d参数是指定后台运行

设置开机启动

便携启动文件

vi /usr/lib/systemd/system/mosquittod.service
           

脚本内容如下

[Unit]
Description=Mosquitto 1.6.10 mqtt server
After=network.target

[Service]
Type=forking
User=mosquitto
Group=mosquitto

ExecStart=/usr/local/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf  -d

# Give a reasonable amount of time for the server to start up/shut down
TimeoutSec=300

# Place temp files in a secure directory, not /tmp
PrivateTmp=true

[Install]
WantedBy=multi-user.target
           

修改文件权限:

chmod 644 /usr/lib/systemd/system/mosquittod.service
           

使配置生效:

systemctl daemon-reload
           

设为开机启动:

systemctl enable mosquittod.service
           

测试

订阅一个主题,如test:

出现如下错误:

mosquitto_sub: error while loading shared libraries: libmosquitto.so.1: cannot open shared object file: No such file or directory
           

解决办法,是创建一个符号链接:

ln -s /usr/local/lib/libmosquitto.so.1  /usr/lib/libmosquitto.so.1
ldconfig
           

然后再次执行

mosquitto_sub -t test

订阅test主题,应该就可以成功了。

再开一个终端窗口给test主题发布一条消息:

订阅的窗口将打印

hello

安装mosquitto-go-auth

安装go环境

dnf install golang -y
           

下载编译mosquitto-go-auth

wget https://github.com/iegomez/mosquitto-go-auth/archive/1.0.0.tar.gz -O ./mosquitto-go-auth-1.0.0.tar.gz
tar -zxvf mosquitto-go-auth-1.0.0.tar.gz
cd mosquitto-go-auth-1.0.0
export CGO_CFLAGS="-I/usr/local/include -fPIC"
export CGO_LDFLAGS="-shared"
make
           

make的时候可能出现如下这样的一个错:

go: github.com/brocaar/[email protected]+incompatible: Get https://proxy.golang.org/github.com/brocaar/lora-app-server/@v/v2.5.1+incompatible.mod: dial tcp 34.64.4.81:443: i/o timeout
make: *** [Makefile:2: all] Error 1
           

解决办法是设置代理

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
make
           

准备MySQL

安装启动MySQL

wget https://dev.mysql.com/get/mysql80-community-release-el8-1.noarch.rpm
yum install mysql80-community-release-el8-1.noarch.rpm
yum install mysql-server
service mysqld start
           

修改root密码

登录MySQL并修改密码,刚刚安装好的是没有密码的,直接回车即可登录进去

mysql -uroot -p
ALTER USER 'root'@'localhost' IDENTIFIED BY '1234';
           

准备数据库和表结构

CREATE SCHEMA `mosquitto` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin ;

use mosquitto;

create table mosquitto_user(
id mediumint not null auto_increment,
username varchar(100) not null,
password_hash varchar(200) not null,
is_admin boolean not null,
primary key(id)
);

create table mosquitto_acl(
id mediumint not null auto_increment,
mosquitto_user_id mediumint not null,
topic varchar(200) not null,
rw int not null COMMENT '1:readonly, 2:writeonly ,3:readwrite ,4:subscribe ',
primary key(id),
foreign key(mosquitto_user_id) references mosquitto_user(id)
ON DELETE CASCADE
ON UPDATE CASCADE
);

insert into mosquitto_user(username, password_hash,is_admin) values('admin','',1);
           

准备测试账号

使用mosquitto-go-auth编译出来的pw命令生成pbkdf2的密码,

cd ~/mosquitto-go-auth-1.0.0
./pw -l 64 -p 123456
           

生成的如下的字符串可以作为mosquitto用户的密码

PBKDF2$sha512$100000$ooBf5L/ANImpDrhOCiAMpg==$BzO004Rc5bT44/E/PMQluJ7Bobf7ffixw/Z3b9iB55No6c/QGy4VgQMBzsLOU9XTJx93qxd/1nKhdCa+HJm1Tw==
           

登录MySQL,创建测试用户

mysql -uroot -p1234
           
-- 插入一个管理员账号和两个普通账号
insert into mosquitto_user(username, password_hash,is_admin) values('admin','PBKDF2$sha512$100000$ooBf5L/ANImpDrhOCiAMpg==$BzO004Rc5bT44/E/PMQluJ7Bobf7ffixw/Z3b9iB55No6c/QGy4VgQMBzsLOU9XTJx93qxd/1nKhdCa+HJm1Tw==',1),('yuanpan1','PBKDF2$sha512$100000$ooBf5L/ANImpDrhOCiAMpg==$BzO004Rc5bT44/E/PMQluJ7Bobf7ffixw/Z3b9iB55No6c/QGy4VgQMBzsLOU9XTJx93qxd/1nKhdCa+HJm1Tw==',0),('yuanpan2','PBKDF2$sha512$100000$ooBf5L/ANImpDrhOCiAMpg==$BzO004Rc5bT44/E/PMQluJ7Bobf7ffixw/Z3b9iB55No6c/QGy4VgQMBzsLOU9XTJx93qxd/1nKhdCa+HJm1Tw==',0);

--  给两个普通账号插入权限控制数据,管理员账号不需要插入
insert into mosquitto_acl(mosquitto_user_id, topic, rw) values(2,'/test/#',1),(2,'/test/#',2),(2,'/test/#',3),(2,'/test/#',4),(3,'/test/#',1),(3,'/test/#',2),(3,'/test/#',3),(3,'/test/#',4);
           

配置运行mosquitto-go-auth

关闭匿名访问

vi /etc/mosquitto/mosquitto.conf
# 将如下配置设置为false
allow_anonymous false 
           

创建日志目录和配置日志设置

cd /var/log
mkdir mosquitto
chown -R mosquitto:mosquitto /var/log/mosquitto/


vi /etc/mosquitto/mosquitto.conf
# 将log_dest,log_type,connection_messages做如下设置
log_dest file /var/log/mosquitto/mosquitto.log
log_type all
connection_messages true
           

配置mosquitto-go-auth插件相关设置

cd /etc/mosquitto/
vi mosquitto.conf 
# 到文件末尾配置
include_dir /etc/mosquitto/conf.d


mkdir plugins
cd plugins
cp ~/mosquitto-go-auth-1.0.0/go-auth.so .


cd ..
mkdir conf.d
vi mosquitto-go-auth.conf
# 写入如下数据到mosquitto-go-auth.conf文件
auth_plugin /etc/mosquitto/plugins/go-auth.so

auth_opt_backends mysql

# Cache
#auth_opt_cache true
#auth_opt_cache_type redis
#auth_opt_cache_reset true

#auth_opt_auth_cache_seconds 30
#auth_opt_acl_cache_seconds 30

#auth_opt_cache_host localhost
#auth_opt_cache_port 6379
#auth_opt_cache_password pwd
#auth_opt_cache_db 3

#Logging
auth_opt_log_level debug
auth_opt_log_dest file
auth_opt_log_file /var/log/mosquitto/mosquitto-go-auth.log


# Hashing
auth_opt_hasher pbkdf2
auth_opt_hasher_salt_size 16                 # salt bytes length
auth_opt_hasher_iterations 100000            # number of iterations
auth_opt_hasher_keylen 64                    # key length
auth_opt_hasher_algorithm sha512             # hashing algorithm, either sha512 (default) or sha256
auth_opt_hasher_salt_encoding base64         # salt encoding, either base64 (default) or utf-8

# MySQL
auth_opt_mysql_host localhost
auth_opt_mysql_port 3306
auth_opt_mysql_dbname mosquitto
auth_opt_mysql_user root
auth_opt_mysql_password 1234
auth_opt_mysql_allow_native_passwords true
auth_opt_mysql_userquery SELECT password_hash FROM mosquitto_user WHERE username = ? limit 1
auth_opt_mysql_superquery SELECT COUNT(1) FROM mosquitto_user WHERE username = ? AND is_admin = 1 LIMIT 1
auth_opt_mysql_aclquery SELECT topic FROM mosquitto_acl acl  inner join mosquitto_user user on acl.mosquitto_user_id = user.id WHERE user.username = ? AND acl.rw = ?

           

以上配置完之后,运行下mosquitto试试

mosquitto -c /etc/mosquitto/mosquitto.conf
           

测试一下

订阅/test/1主题

mosquitto_sub  -t /test/1 -u yuanpan1 -P 123456
           

给/test/1主题发送一个hello消息

mosquitto_pub  -t /test/1 -m "hello" -u yuanpan2 -P 123456
           

配置TLS

机器准备和命名

这部分的内容将和mosquitto的桥接一起来写,准备3台虚拟机,配置其 /etc/hosts文件,来为虚拟机命名

192.168.20.200 server.mosquitto1.vm client.mosquitto1.vm ca.mosquitto1.vm
192.168.20.201 server.mosquitto2.vm client.mosquitto2.vm
192.168.20.202 server.mosquitto3.vm client.mosquitto3.vm
           

使用openssl生成相关证书

准备/etc/mosquitto/certs目录

在第一台虚拟机

server.mosquitto1.vm

上执行如下:

cd /etc/mosquitto/
mkdir certs
cd certs
           

Certificate Authority

Generate a certificate authority certificate and key.

openssl req -new -x509 -days 3650 -extensions v3_ca -keyout ca.key -out ca.crt
           

先输入两遍密码,剩下的可以参考如下:

Country Name : CN

State or Province Name : HuBei

Locality Name (eg, city) : WuHan

Organization Name (eg, company) : Test

Organizational Unit Name (eg, section) : CA

Common Name (eg, your name or your server’s hostname) : ca.mosquitto1.vm

Email Address : [email protected]

这里注意,Common Name 是ca.mosquitto1.vm

Server

Generate a server key.

openssl genrsa -out server.key 2048
           

Generate a certificate signing request to send to the CA.

openssl req -out server.csr -key server.key -new
           

先输入两遍密码,剩下的可以参考如下:

Country Name : CN

State or Province Name : HuBei

Locality Name (eg, city) : WuHan

Organization Name (eg, company) : Test

Organizational Unit Name (eg, section) : Server

Common Name (eg, your name or your server’s hostname) : server.mosquitto1.vm

Email Address : [email protected]

这里注意,Common Name,在第一台机器,填server.mosquitto1.vm,在第二台机器填server.mosquitto2.vm,第三台机器填server.mosquitto3.vm

Send the CSR to the CA, or sign it with your CA key:

openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 3650
           

将虚拟机的证书放到

/ect/mosquitto/certs/server.mosquitto1.vm

目录下

mkdir server.mosquitto1.vm
mv server.crt server.mosquitto1.vm/
mv server.csr server.mosquitto1.vm/
mv server.key server.mosquitto1.vm/
           
继续执行上面生成Server证书的步骤来生成server.mosquitto2.vm的Server证书,并放入到

/ect/mosquitto/certs/server.mosquitto1.vm

目录下;生成server.mosquitto3.vm的Server证书,并放入到

/ect/mosquitto/certs/server.mosquitto3.vm

目录下
mkdir server.mosquitto2.vm
mv server.crt server.mosquitto2.vm/
mv server.csr server.mosquitto2.vm/
mv server.key server.mosquitto2.vm/

mkdir server.mosquitto3.vm
mv server.crt server.mosquitto3.vm/
mv server.csr server.mosquitto3.vm/
mv server.key server.mosquitto3.vm/
           

Client

Generate a client key.

openssl genrsa -out client.key 2048
           

Generate a certificate signing request to send to the CA.

openssl req -out client.csr -key client.key -new
           

Country Name : CN

State or Province Name : HuBei

Locality Name (eg, city) : WuHan

Organization Name (eg, company) : Test

Organizational Unit Name (eg, section) : Client

Common Name (eg, your name or your server’s hostname) : client.mosquitto1.vm

Email Address : [email protected]

这里注意,Common Name,在第一台机器,填client.mosquitto1.vm,在第二台机器填client.mosquitto2.vm,第三台机器填client.mosquitto3.vm

Send the CSR to the CA, or sign it with your CA key:

openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 3650
           

将虚拟机的证书放到

/ect/mosquitto/certs/client.mosquitto1.vm

目录下

mkdir client.mosquitto1.vm
mv client.crt client.mosquitto1.vm/
mv client.csr client.mosquitto1.vm/
mv client.key client.mosquitto1.vm/
           
继续执行上面生成Server证书的步骤来生成server.mosquitto2.vm的Server证书,并放入到

/ect/mosquitto/certs/server.mosquitto1.vm

目录下;生成server.mosquitto3.vm的Server证书,并放入到

/ect/mosquitto/certs/server.mosquitto3.vm

目录下
mkdir client.mosquitto2.vm
mv client.crt client.mosquitto2.vm/
mv client.csr client.mosquitto2.vm/
mv client.key client.mosquitto2.vm/

mkdir client.mosquitto3.vm
mv client.crt client.mosquitto3.vm/
mv client.csr client.mosquitto3.vm/
mv client.key client.mosquitto3.vm/
           

TLS单向认证

修改配置

vi /etc/mosquitto/mosquitto.conf

# 修改如下配置
port 8883
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.mosquitto1.vm/server.crt
keyfile /etc/mosquitto/certs/server.mosquitto1.vm/server.key
require_certificate false
tls_version tlsv1.2
           
上面是虚拟机1的配置,在配置虚拟机2和3的时候注意修改证书文件路径

单向认证和双向认证的区别在于

require_certificate

这个配置项

配置完成之后三台机器都启动好mosquitto

测试

开启了TLS之后我用

mosquitto_sub

mosquitto_sub

命令都得到一个错误

Error: A TLS error occurred.

但是如果是使用工具,如MQTT.fx就没问题

这个问题弄清楚了,是因为证书的Common Name导致的。需要在mosquitto_sub命令的参数中指定

-h

参数跟证书的Common Name一致就可以了。

下面开始在第一台虚拟机上测试,先订阅一个

/test/1

的主题

mosquitto_sub -u yuanpan1 -P 123456 -t "/test/1" -p 8883 -h server.mosquitto1.vm --cafile "/etc/mosquitto/certs/ca.crt" --tls-version tlsv1.2
           

再向这个主题发布一个消息

mosquitto_pub -u yuanpan1 -P 123456 -t "/test/1" -m "hello" -p 8883 -h server.mosquitto1.vm --cafile "/etc/mosquitto/certs/ca.crt" --tls-version tlsv1.2
           

可以看到订阅的地方能收到hello的消息

如果是使用MQTT.fx工具测试,在SSL/TLS中选择CA certificate file ,选择ca.crt文件

TLS单向认证下的多个broker桥接

在server.mosquitto1.vm机器上配置

/etc/mosquitto/mosquitto.conf

,配置如下的内容:

connection bridge1
cleansession true
address server.mosquitto2.vm:8883
topic # both 0
bridge_cafile /etc/mosquitto/certs/ca.crt
remote_username admin
remote_password 123456

connection bridge2
cleansession true
address server.mosquitto3.vm:8883
topic # both 0
bridge_cafile /etc/mosquitto/certs/ca.crt
remote_username admin
remote_password 123456

           
注意cleansession的设置,如果设置为true,那么在桥接断开的时候,远程代理上订阅和主题会被清除,如果设置为false则不会清除。

配置玩之后重启虚拟机1上的mosquitto

测试的话,可以在任意两台机器上订阅一个主题如/test/1,然后在第三台机器上发布一个消息到这个主题

在虚拟机1和虚拟机2上订阅

mosquitto_sub -u yuanpan1 -P 123456 -t "/test/1" -p 8883 -h server.mosquitto1.vm --cafile "/etc/mosquitto/certs/ca.crt"  --tls-version tlsv1.2

mosquitto_sub -u yuanpan1 -P 123456 -t "/test/1" -p 8883 -h server.mosquitto2.vm --cafile "/etc/mosquitto/certs/ca.crt"  --tls-version tlsv1.2
           

在虚拟机3上发布:

mosquitto_pub -u yuanpan1 -P 123456 -t "/test/1" -m "单向TLS测试" -p 8883 -h server.mosquitto3.vm --cafile "/etc/mosquitto/certs/ca.crt" --tls-version tlsv1.2
           

在虚拟机1和2上都可以看到订阅的消息:单向TLS测试

TLS双向认证

单向认证和双向认证的区别在于

require_certificate

这个配置项
如果是一路走过来的,那么可以先将上面讲到的的桥接部分的配置在虚拟机1上先注释掉,再往下看。

修改配置

vi /etc/mosquitto/mosquitto.conf

# 修改如下配置
port 8883
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.mosquitto1.vm/server.crt
keyfile /etc/mosquitto/certs/server.mosquitto1.vm/server.key
require_certificate true
tls_version tlsv1.2
use_identity_as_username true
           

注意

use_identity_as_username

这个配置项,如果这个配置成了

true

,那么在认证的时候,会将客户端证书中的

Common Name

作为用户名来校验,当然,这个配置项是可以配置成

false

的。

测试

下面开始在第一台虚拟机上测试,先订阅一个

/test/1

的主题

mosquitto_sub -u yuanpan1 -P 123456 -t "/test/1" -p 8883 -h server.mosquitto1.vm --cafile "/etc/mosquitto/certs/ca.crt" --cert "/etc/mosquitto/certs/client.mosquitto1.vm/client.crt" --key "/etc/mosquitto/certs/client.mosquitto1.vm/client.key" --tls-version tlsv1.2
           

再向这个主题发布一个消息

mosquitto_pub -u yuanpan1 -P 123456 -t "/test/1" -m "双向TLS测试" -p 8883 -h server.mosquitto1.vm --cafile "/etc/mosquitto/certs/ca.crt" --cert "/etc/mosquitto/certs/client.mosquitto1.vm/client.crt" --key "/etc/mosquitto/certs/client.mosquitto1.vm/client.key" --tls-version tlsv1.2
           

可以看到订阅的地方能收到双向TLS测试的消息

如果是使用MQTT.fx工具测试,在SSL/TLS中选择Self signed certificates。

在CA File中选择ca.crt文件

在Client Certificate File中选择client.crt文件

在Client Key File中选择client.key文件

在Client Key Password中填写生成客户端证书时候的密码

勾选PEM Formatted

TLS双向认证下的多个broker桥接

在server.mosquitto1.vm机器上配置

/etc/mosquitto/mosquitto.conf

,配置如下的内容:

connection bridge1
cleansession true
address server.mosquitto2.vm:8883
topic # both 0
bridge_cafile /etc/mosquitto/certs/ca.crt
remote_username admin
remote_password 123456

connection bridge2
cleansession true
address server.mosquitto3.vm:8883
topic # both 0
bridge_cafile /etc/mosquitto/certs/ca.crt
remote_username admin
remote_password 123456

           

测试的话,可以在任意两台机器上订阅一个主题如/test/1,然后在第三台机器上发布一个消息到这个主题

在虚拟机1和虚拟机2上订阅

mosquitto_sub -u yuanpan1 -P 123456 -t "/test/1" -p 8883 -h server.mosquitto1.vm --cafile "/etc/mosquitto/certs/ca.crt" --cert "/etc/mosquitto/certs/client.mosquitto1.vm/client.crt" --key "/etc/mosquitto/certs/client.mosquitto1.vm/client.key" --tls-version tlsv1.2

mosquitto_sub -u yuanpan1 -P 123456 -t "/test/1" -p 8883 -h server.mosquitto2.vm --cafile "/etc/mosquitto/certs/ca.crt" --cert "/etc/mosquitto/certs/client.mosquitto2.vm/client.crt" --key "/etc/mosquitto/certs/client.mosquitto2.vm/client.key" --tls-version tlsv1.2
           

在虚拟机3上发布:

mosquitto_pub -u yuanpan1 -P 123456 -t "/test/1" -m "双向TLS测试" -p 8883 -h server.mosquitto3.vm --cafile "/etc/mosquitto/certs/ca.crt" --cert "/etc/mosquitto/certs/client.mosquitto3.vm/client.crt" --key "/etc/mosquitto/certs/client.mosquitto3.vm/client.key" --tls-version tlsv1.2
           

在虚拟机1和2上都可以看到订阅的消息:双向TLS测试

继续阅读