MQTT mosquitto

#背景
Mosquitto是一个开源(BSD许可证)的消息代理,实现MQTT(消息队列遥测传输)协议版本3.1。

MQTT(MQ Telemetry Transport),消息队列遥测传输协议,轻量级的发布/订阅协议,适用于一些条件比较苛刻的环境,进行低带宽、不可靠或间歇性的通信。值得一提的是mqtt提供三种不同质量的消息服务:

“至多一次”,消息发布完全依赖底层 TCP/IP 网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。
“至少一次”,确保消息到达,但消息重复可能会发生。
“只有一次”,确保消息到达一次。这一级别可用于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果。

 

#安装

## 下载源代码包

wget http://mosquitto.org/files/source/mosquitto-1.5.tar.gz

## 解压

tar zxfv mosquitto-1.5.tar.gz

## 进入目录

cd mosquitto-1.5

## 编译

make

## 安装

sudo make install

 

#安装及使用过程的错误

##编译找不到openssl/ssl.h

sudo apt-get install libssl-dev

##编译过程找不到ares.h

sudo apt-get install libc-ares-dev

##编译过程找不到uuid/uuid.h

sudo apt-get install uuid-dev

##使用过程中找不到libmosquitto.so.1

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

解决方法修改libmosquitto.so位置

###创建链接

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

### 更新动态链接库

sudo ldconfig

 

#简单测试

MQTT mosquitto_第1张图片

一个完整的MQTT示例包括一个代理器,一个发布者和一个订阅者。测试分为以下几个步骤:

注:在本次测试中,发布者、代理和订阅者均在一台主机上,启用3个终端窗口完成测试。

##启动服务mosquitto。

mosquitto -v

【-v】打印更多的调试信息

##订阅者通过mosquitto_sub订阅指定主题的消息。

mosquitto_sub -v -t test

【-t】指定主题,此处为test【-v】打印更多的调试信息

##发布者通过mosquitto_pub发布指定主题的消息。

mosquitto_pub -t test -m hello

【-t】指定主题 【-m】指定消息内容

##代理服务器把该主题的消息推送到订阅者。


 

#mosquitto_pub 用法详解

用法:
mosquitto_pub [-d] [-h hostname] [-i client_id] [-I client id prefix] [-p port number] [-q message QoS] [–quiet] [-r] { -f file | -l | -m message | -n | -s} [-u username [-P password] ] [ –will-topic topic [–will-payload payload] [–will-qos qos] [–will-retain] ] -t message-topic
选项:
-d, –debug
开启debug选项
-f, –file
把一个文件的内容做为消息的内容发送。经测试,支持txt文件,不支持doc等其他形式文件。
-h, –host
说明所连接到的域名,默认是localhost
-i, –id
客户端的ID号,如果没有指定,默认是mosquitto_pub_加上客户端的进程id,不能和–id_prefix同时使用。
-I, –id-prefix
指定客户端ID的前缀,与客户端的进程ID连接组成客户端的ID,不能喝–id同时使用。
-l, –stdin-line
从总段读取输入发送消息,一行为一条消息,空白行不会被发送。
-m, –message
从命令行发送一条消息,-m后面跟发送的消息内容。
-n, –null-message
发送一条空消息。
-p, –port
连接的端口号,默认是1883.
-P, –pw
指定密码用于代理认证,使用此选项时必须有有效的用户名。
-q, –qos
指定消息的服务质量,可以为0,1,2,默认是0.
–quiet
如果指定该选项,则不会有任何错误被打印,当然,这排除了无效的用户输入所引起的错误消息。
-r, –retain
如果指定该选项,该条消息将被保留做为最后一条收到的消息。下一个订阅消息者将能至少收到该条消息。
-s, –stdin-file
从标准输入接收传输的消息内容,所有输入做为一条消息发送。
-t, –topic
指定消息所发布到哪个主题。
-u, –username
指定用户名用于代理认证。
–will-payload
如果指定该选项,则万一客户端意外和代理服务器断开,则该消息将被保留在服务端并发送出去,该选项必须同时用–will-topic指定主题。
–will-qos
指定Will的服务质量,默认是0.必须和选项 –will-topic同时使用.
–will-retain
如果指定该选项,则万一客户端意外断开,已被发送的消息将被当做retained消息。必须和选项 –will-topic同时使用.
–will-topic
指定客户端意外断开时,Will消息发送到的主题。

 

#mosquitto_sub 用法详解

用法:
mosquitto_sub [-c] [-d] [-h hostname] [-i client_id] [-I client id prefix] [-k keepalive time] [-p port number] [-q message QoS] [–quiet] [-v] [ -u username [-Ppassword] ] [ –will-topic topic [–will-payload payload] [–will-qos qos] [–will-retain] ] -t message topic …
选项:
-c, –disable-clean-session
禁止’clean session’选项,即如果客户端断开连接,这个订阅仍然保留来接收随后到的QoS为1和2的消息,当改客户端重新连接之后,它将接收到已排在队列中的消息。建议使用此选项时,客户端id选项设为–id
If using this option, it is recommended that the client id is set manually with –id
-d, –debug
开启debug选项
-h, –host
说明所连接到的域名,默认是localhost
-i, –id
客户端的ID号,如果没有指定,默认是mosquitto_pub_加上客户端的进程id,不能和–id_prefix同时使用。
-I, –id-prefix
指定客户端ID的前缀,与客户端的进程ID连接组成客户端的ID,不能喝–id同时使用。
-k, –keepalive
给代理发送PING命令(目的在于告知代理该客户端连接保持且在正常工作)的间隔时间,默认是60s
-p, –port
说明客户端连接到的端口,默认是1883
-P, –pw
指定密码用于代理认证,使用此选项时必须有有效的用户名。
-q, –qos
指定消息的服务质量,可以为0,1,2,默认是0.
–quiet
如果指定该选项,则不会有任何错误被打印,当然,这排除了无效的用户输入所引起的错误消息。
-t, –topic
指定订阅的消息主题,允许同时订阅到多个主题
-u, –username
指定用户名用于代理认证。
-v, –verbose
冗长地打印收到的消息。若指定该选项,打印消息时前面会打印主题名——“主题 消息内容”,否则,只打印消息内容
–will-payload
如果指定该选项,则万一客户端意外和代理服务器断开,则该消息将被保留在服务端并发送出去,该选项必须同时用–will-topic指定主题。
–will-qos
指定Will的服务质量,默认是0.必须和选项 –will-topic同时使用.
–will-retain
如果指定该选项,则万一客户端意外断开,已被发送的消息将被当做retained消息。必须和选项 –will-topic同时使用.
–will-topic
指定客户端意外断开时,Will消息发送到的主题。

 

#mosquitto 用户配置

mosquitto中可以添加多个用户,只有使用用户名和密码才能登陆服务器进行订阅与发布操作。可以说用户机制是mosquitto重要的安全机制,增强服务器的安全性。

##添加用户步骤

1.打开mosquitto.conf文件,找到allow_anonymous节点,这个节点作用是,是否开启匿名用户登录,默认是true,改为false。

allow_anonymous false

2.找到password_file节点,这个节点是告诉服务器你要配置的用户将存放在哪里。打开此配置并指定pwfile.example文件路劲(注意是绝对路劲)

password_file /etc/mosquitto/pwfile.example

3.创建用户名和密码、打开命令窗口 键入如下命令:

sudo mosquitto_passwd /etc/mosquitto/pwfile.example mosquitto

提示连续两次输入密码、创建成功。/etc/mosquitto/pwfile.example 是将用户创建到 pwfile.example文件中、mosquitto是用户名。

 

#Mosquitto 单向SSL配置

##生成CA证书

创建generate-CA.sh脚本,贴入以下代码:

#!/bin/sh
#(@)generate-CA.sh - Create CA key-pair and server key-pair signed by CA

# Copyright (c) 2013 Jan-Piet Mens 
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 
# 1. Redistributions of source code must retain the above copyright notice,
#    this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. Neither the name of mosquitto nor the names of its
#    contributors may be used to endorse or promote products derived from
#    this software without specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

set -e

DIR=${TARGET:='.'}
# A space-separated list of alternate hostnames (subjAltName)
# may be empty ""
ALTHOSTNAMES="broker.example.com foo.example.de"
CA_ORG='/O=MQTTitude.org/[email protected]'
CA_DN="/CN=An MQTT broker${CA_ORG}"
CACERT=${DIR}/ca
SERVER=${DIR}/server
SERVER_DN="/CN=$(hostname -f)$CA_ORG"
keybits=2048
openssl=$(which openssl)

function maxdays() {
	nowyear=$(date +%Y)
	years=$(expr 2032 - $nowyear)
	days=$(expr $years '*' 365)

	echo $days
}

function getipaddresses() {
	/sbin/ifconfig |
		sed -En '/inet6? /p' |
		sed -Ee 's/inet6? (addr:)?//' |
		awk '{print $1;}' |
		sed -e 's/[%/].*//' |
		egrep -v '(::1|127\.0\.0\.1)'	# omit loopback to add it later
}


function addresslist() {

	ALIST=""
	for a in $(getipaddresses); do
		ALIST="${ALIST}IP:$a,"
	done
	ALIST="${ALIST}IP:127.0.0.1,IP:::1,"

	for h in $(echo ${ALTHOSTNAMES}); do
		ALIST="${ALIST}DNS:$h,"
	done
	ALIST="${ALIST}DNS:localhost"
	echo $ALIST

}

days=$(maxdays)

if [ -n "$CAKILLFILES" ]; then
	rm -f $CACERT.??? $SERVER.??? $CACERT.srl
fi

if [ ! -f $CACERT.crt ]; then
	# Create un-encrypted (!) key
	$openssl req -newkey rsa:${keybits} -x509 -nodes -days $days -extensions v3_ca -keyout $CACERT.key -out $CACERT.crt -subj "${CA_DN}"
	echo "Created CA certificate in $CACERT.crt"
	$openssl x509 -in $CACERT.crt -nameopt multiline -subject -noout

	chmod 400 $CACERT.key
	chmod 444 $CACERT.crt
fi

if [ ! -f $SERVER.key ]; then
	echo "--- Creating server key and signing request"
	$openssl genrsa -out $SERVER.key $keybits
	$openssl req -new \
		-out $SERVER.csr \
		-key $SERVER.key \
		-subj "${SERVER_DN}"
	chmod 400 $SERVER.key
fi

if [ -f $SERVER.csr -a ! -f $SERVER.crt ]; then

	# There's no way to pass subjAltName on the CLI so
	# create a cnf file and use that.

	CNF=`mktemp /tmp/cacnf.XXXXXXXX` || { echo "$0: can't create temp file" >&2; exit 1; }
	sed -e 's/^.*%%% //' > $CNF <<\!ENDconfig
	%%% [ JPMextensions ]
	%%% basicConstraints        = critical,CA:false
	%%% nsCertType              = server
	%%% keyUsage                = nonRepudiation, digitalSignature, keyEncipherment
	%%% nsComment               = "Broker Certificate"
	%%% subjectKeyIdentifier    = hash
	%%% authorityKeyIdentifier  = keyid,issuer:always
	%%% subjectAltName          = $ENV::SUBJALTNAME
	%%% # issuerAltName           = issuer:copy
	%%% nsCaRevocationUrl       = http://mqttitude.org/carev/
	%%% nsRevocationUrl         = http://mqttitude.org/carev/
!ENDconfig

	SUBJALTNAME="$(addresslist)"
	export SUBJALTNAME		# Use environment. Because I can. ;-)

	echo "--- Creating and signing server certificate"
	$openssl x509 -req \
		-in $SERVER.csr \
		-CA $CACERT.crt \
		-CAkey $CACERT.key \
		-CAcreateserial \
		-CAserial "${DIR}/ca.srl" \
		-out $SERVER.crt \
		-days $days \
		-extfile ${CNF} \
		-extensions JPMextensions

	rm -f $CNF
	chmod 444 $SERVER.crt
fi

直接执行这段shell

执行完成后可生成 ca.crt  ca.key  ca.srl  server.crt  server.key  server.csr

##配置mosquitto 配置文件

###进入配置文件

sudo vim /etc/mosquitto/mosquitto.conf

###找到 Default listener,在该栏下进行端口配置

MQTT mosquitto_第2张图片

###再找到Certificate based SSL/TLS support字段,进行白色字体的配置。

MQTT mosquitto_第3张图片

##重启服务

mosquitto -c /etc/mosquitto/mosquitto.conf

##验证

###终端一订阅

 mosquitto_sub -h 192.168.8.19 -p 8883 -u mosquitto -P 123456 --cafile ./ca.crt -t test
###终端二发布

mosquitto_pub -h 192.168.8.19 -p 8883 -u mosquitto -P 123456 --cafile ./ca.crt -t test -m hello
 

你可能感兴趣的:(物联网)