這裡寫自定義目錄标題
-
- 環境準備
-
- 關閉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證書,并放入到目錄下;生成server.mosquitto3.vm的Server證書,并放入到
/ect/mosquitto/certs/server.mosquitto1.vm
目錄下
/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證書,并放入到目錄下;生成server.mosquitto3.vm的Server證書,并放入到
/ect/mosquitto/certs/server.mosquitto1.vm
目錄下
/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測試