ESP8266 mqtt 通过tls单向认证连接到mosquitto mqtt broker
标签(空格分隔): mqtt esp8266 tls mosquitto 单向认证
最近需要使用esp8266作为mqtt client,broker暂时使用mosquitto mqtt在linux上运行。连接采用tls加密,client单向认证server。该过程有一些问题需要注意,在此列出。
期间参阅了很多大神们的博客,一并整理列出。
本文分为三部分,linux下esp8266的编译环境搭建,mosquitto的配置以及esp8266 mqttclient的证书制作。
ubuntu下esp8266编译环境搭建
该部分网上有成熟的教程,如果您是一个全新的ubuntu,搭建esp8266环境时会遇到很多问题,我参考了以下这几篇文章,足够解决问题了。
首先是git上的教程,这个教程很完整。只是会在执行一些步骤时出现各种各样的问题,如libtool
版本过低的问题,参见ESP8266 Linux开发环境搭建,另外,在执行apt-get install
安装及更新各种库时,git上的教程有些问题(我是17的ubuntu版本),还是按照博客ESP8266 Linux开发环境搭建中的apt-get
即可解决问题。
在执行./ct-ng build
时可能会遇到很多错误,这时参考:
crosstool-ng常见问题及解决办法,这里可以解决你的大部分问题。
最后的gdb编译错误,百度一下就能找到解决方法,不解决也没有关系。
在ubuntu下编译自己的esp8266 mqtt工程
搭建好编译环境后,就可以开始编译自己的esp8266工程了。以编译esp8266的mqtt工程为例进行说明:
- 工程下载:ESP8266 NONOS V2.0.0(刚看了一下,乐鑫已经又更新了2.1版本了。。。。)。
我的工程目录在/mnt/hgfs/workspaceAbleCloud/WiFi/ESP/ESP8266_NONOS_SDK
。
将example目录中的esp_mqtt_proj
直接拷贝到example的同级目录。然后cd到esp_mqtt_proj
,make clean, ./gen_misc.sh
,注意,不要用make(make用的是xt-cc)。 - 更改配置项
编译时需要修改esp_mqtt_proj中的部分文件,首先是配置文件mqtt_config.h
,这个我是参考的博客 esp8266与mosquitto的mqtt的ssl通讯实现(一)以及里面连接的文章。
需要注意的是,esp8266的mqtt默认没有开启tls的认证,这样也是能够连接broker并且对报文进行加密的。 - 开启TLS单向认证
我们需要tls单向认证,还需要修改:
(1)mqtt_config.h
文件中的宏MQTT_SSL_ENABLE
打开,宏DEFAULT_SECURITY
改为1
(2)user_config.h
中的宏CLIENT_SSL_ENABLE
打开
(3)在user_init函数中添加使能CA认证的函数espconn_secure_ca_enable(0x01, 0x7c);
(注意,入参开发者需要自己填写,参见乐鑫ssl说明文档《5A-ESP8266__SDK__SSL_User_Manual__CN_v1.4.pdf》
) - 编译
编译时会遇到许多头文件的错误(string.h等),解决方法是将上面ubuntu下esp8266编译环境搭建
中的/opt/Espressif/ESP8266_SDK/include
中的相关头文件(缺什么copy什么)拷贝到esp_mqtt_proj/include
中,还要将/opt/Espressif/ESP8266_SDK/lib
中的库libc.a
和libhal.a
拷贝到esp_mqtt_proj
的同级目录中的lib中。
开启mosquitto mqtt broker
首先在ubuntu上使用源码安装mosquitto mqtt。
从官网下载最新版本的mosquitto mqtt源码(我的是1.4.11版本),直接编译安装。mosquitto mqtt的编译安装网上有丰富的教程,有问题直接百度。
安装完后,需要修改mosquitto.conf
文件以开启tls单向认证:
- 端口改为8883
- 设置ca路径(路径改为开发者自己的CA证书以及server的证书和key的路径)
- 设置server的ca路径
- 设置server的key路径
开启mqtt broker(mosquitto.conf改为开发者自己的路径):
mosquitto -v -c mosquitto.conf
证书制作
使用openssl字签证书。
参考文档
附上我的证书制作脚本:
# Generate the openssl configuration files.
cat > ca_cert.conf << EOF
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = AC
OU = AC
C = CN
ST = PK
L = PK
CN = ablecloud.cn
EOF
cat > certs.conf << EOF
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = AC
OU = AC
C = CN
ST = PK
L = PK
CN = 192.168.31.127
EOF
# private key generation
openssl genrsa -out ca.key 1024
openssl req -new -x509 -key ca.key -out ca.crt -days 3650 -config ca_cert.conf
openssl genrsa -out server.key 1024
openssl req -new -key server.key -out server.csr -config certs.conf
openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key -days 3650
openssl x509 -in ca.crt -outform DER -out TLS.ca_x509.cer
其他问题
- esp8266显示证书过期
esp8266上显示证书已经过期,改原因有两个:
(1)esp8266没有开启sntp服务,导致本机时间与ntp时间不同步。需要在进行证书验证之前开启sntp服务,参考乐鑫文档,示例如下:
sntp_setservername(0,"us.pool.ntp.org"); // set server 0 by domain name
sntp_setservername(1,"ntp.sjtu.edu.cn"); // set server 1 by domain name
ipaddr_aton("210.72.145.44",addr);
sntp_setserver(2,addr); // set server 2 by IP address
sntp_init();
os_printf("sntp init6\r\n");
os_free(addr);
(2)有效期过长。我之前签了一个100年的证书,结果esp8266报证书有效期失效,之后将有效期改为10年,问题消失
2. esp8266显示证书认证失败
log如下:
几种可能:
(1)自签证书与esp8266要求的证书格式不同。前面脚本中生成的证书时pem格式的,而esp8266要求的证书时DER格式的,所以需要将openssl生成的证书转为DER格式的。之前在网上查看.crt转为.cer格式的证书,很多人说直接改后缀名就可以,实际上是不行的。(esp8266)这里的.cer证书要求的是DER格式,所以需要用openssl命令转:
openssl x509 -in ca.crt -outform DER -out TLS.ca_x509.cer
(2)CA证书与使用CA签发的证书的CN名字相同
(3)mosquitto broker的证书中的CN与实际mosquitto broker部署的机器的IP不相同