emqx SSL自签证书问题,并且开启证书认证,不用证书可以连接

docker版本的emqx4.3.10

问题描述

按照社区的文章自签SSL证书,无法连接

配置文件及日志

listener.ssl.external.keyfile = etc/certs/emqx.key.pem
listener.ssl.external.certfile = etc/certs/emqx.pem
listener.ssl.external.cacertfile = etc/certs/ca.pem
listener.ssl.external.verify = verify_peer
listener.ssl.external.fail_if_no_peer_cert = true

以下是证书生成过程

  1. 生成CA私钥,私钥中包含了公钥
    openssl genrsa -out ca.key 2048
    
  2. 生成CA自签名证书请求文件
    openssl req -new -key ca.key -out ca.csr -subj "/C=CN/ST=Jiangxi/L=Nanchang/O=zlang/OU=EMQX/CN=*.xxx.net/emailAddress=xxx@sohu.com"
    
  3. 生成CA自签名证书
    openssl x509 -req -days 3650 -in ca.csr -signkey ca.key -CAcreateserial -out ca.pem
    
  4. 生成服务器私钥
    openssl genrsa -out emqx.key 2048
    
  5. 从私钥中提取出公钥
    openssl rsa -in emqx.key -pubout -out server_public.key
    
  6. 生成服务器证书请求文件
    openssl req -new -key emqx.key -out server_req.csr -subj "/C=CN/ST=Jiangxi/L=Nanchang/O=zlang/OU=EMQX/CN=*.xxx.net/emailAddress=xxx@sohu.com"
    
  7. 生成服务器证书
    openssl x509 -req -days 3650 -in server_req.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out emqx.pem
    
  8. 生成客户端私钥
    openssl genrsa -out client.key 2048
    
  9. 从私钥中提取出公钥
    openssl rsa -in client.key -pubout -out client_public.key
    
  10. 生成客户端证书请求文件
    openssl req -new -key client.key -out client_req.csr -subj "/C=CN/ST=Jiangxi/L=Nanchang/O=zlang/OU=EMQX/CN=*.xxx.net/emailAddress=xxxx@sohu.com"
    
  11. 生成客户端证书
    openssl x509 -req -days 3650 -in client_req.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out client.pem
    openssl s_client -connect localhost:2020 -cert client.pem -key client.key.pem
    openssl s_server -accept 2020 -key emqx.key.pem -cert emqx.pem
    

证书通过上述方法可以验证

    Start Time: 1637651645
    Timeout   : 7200 (sec)
    Verify return code: 18 (self signed certificate)
    Extended master secret: no
    Max Early Data: 0

MQTTX连接的报错日志:

[2021-11-23 14:27:07] [ERROR] Connect fail, MQTT.js onError trigger, Error: self signed certificate
    at TLSSocket.onConnectSecure (_tls_wrap.js:1501:34)
    at TLSSocket.emit (events.js:315:20)
    at TLSSocket._finishInit (_tls_wrap.js:936:8)
    at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:710:12)
[2021-11-23 14:27:07] [INFO] Connect close, MQTT.js onClose trigger
[2021-11-23 14:50:26] [INFO] Connect client, MQTT/SSL connection: mqtts://192.168.1.13:8883
[2021-11-23 14:50:26] [INFO] MQTTX client with ID 8af17255-e0ff-4568-94ad-b824dcc3b3bd assigned
[2021-11-23 14:50:26] [ERROR] Connect fail, MQTT.js onError trigger, Error: self signed certificate
    at TLSSocket.onConnectSecure (_tls_wrap.js:1501:34)
    at TLSSocket.emit (events.js:315:20)
    at TLSSocket._finishInit (_tls_wrap.js:936:8)
    at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:710:12)
[2021-11-23 14:50:26] [INFO] Connect close, MQTT.js onClose trigger
[2021-11-23 14:56:55] [INFO] Connect client, MQTT/SSL connection: mqtts://xxx.xxxx.net:8883
[2021-11-23 14:56:55] [INFO] MQTTX client with ID 8af17255-e0ff-4568-94ad-b824dcc3b3bd assigned
[2021-11-23 14:56:55] [ERROR] Connect fail, MQTT.js onError trigger, Error: self signed certificate
    at TLSSocket.onConnectSecure (_tls_wrap.js:1501:34)
    at TLSSocket.emit (events.js:315:20)
    at TLSSocket._finishInit (_tls_wrap.js:936:8)
    at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:710:12)

MQTT.fx的报错日志

2021-11-23 14:51:44,130  INFO --- ScriptsController              : Clear console.
2021-11-23 14:51:44,130 ERROR --- BrokerConnectService           : MqttException
2021-11-23 14:56:29,455  INFO --- BrokerConnectorController      : onConnect
2021-11-23 14:56:29,457  INFO --- ScriptsController              : Clear console.
2021-11-23 14:56:29,458  INFO --- MqttFX ClientModel             : MqttClient with ID 9a2dd7021eee43389d99c0572c1443fa assigned.
2021-11-23 14:56:29,508 ERROR --- MqttFX ClientModel             : Error when connecting
org.eclipse.paho.client.mqttv3.MqttException: MqttException
	at org.eclipse.paho.client.mqttv3.internal.ExceptionHelper.createMqttException(ExceptionHelper.java:38) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:715) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_181]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[?:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[?:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_181]
	at java.lang.Thread.run(Thread.java:748) [?:1.8.0_181]
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) ~[?:1.8.0_181]
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:154) ~[?:1.8.0_181]
	at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2038) ~[?:1.8.0_181]
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1135) ~[?:1.8.0_181]
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385) ~[?:1.8.0_181]
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413) ~[?:1.8.0_181]
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397) ~[?:1.8.0_181]
	at org.eclipse.paho.client.mqttv3.internal.SSLNetworkModule.start(SSLNetworkModule.java:108) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:701) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	... 7 more
2021-11-23 14:56:29,509 ERROR --- MqttFX ClientModel             : Please verify your Settings (e.g. Broker Address, Broker Port & Client ID) and the user credentials!
org.eclipse.paho.client.mqttv3.MqttException: MqttException
	at org.eclipse.paho.client.mqttv3.internal.ExceptionHelper.createMqttException(ExceptionHelper.java:38) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:715) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_181]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[?:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[?:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_181]
	at java.lang.Thread.run(Thread.java:748) [?:1.8.0_181]
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) ~[?:1.8.0_181]
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:154) ~[?:1.8.0_181]
	at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2038) ~[?:1.8.0_181]
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1135) ~[?:1.8.0_181]
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385) ~[?:1.8.0_181]
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413) ~[?:1.8.0_181]
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397) ~[?:1.8.0_181]
	at org.eclipse.paho.client.mqttv3.internal.SSLNetworkModule.start(SSLNetworkModule.java:108) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:701) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	... 7 more
2021-11-23 14:56:29,512  INFO --- ScriptsController              : Clear console.
2021-11-23 14:56:29,512 ERROR --- BrokerConnectService           : MqttException

MQTT.fx的连接设置截图

另外,按照配置,我应该是开启了证书认证吧,但是用证书是无法连接的,不用证书反而连接上了。
在 emqx 的 docker 里面 log 的文件夹下面没有日志文件产生。
通过 docker logs 命令,得到如下日志:

Starting emqx on node b220f1fadae3@172.17.0.2
Start mqtt:tcp:internal listener on 127.0.0.1:11883 successfully.
Start mqtt:tcp:external listener on 0.0.0.0:1883 successfully.
Start mqtt:ws:external listener on 0.0.0.0:8083 successfully.
Start mqtt:ssl:external listener on 0.0.0.0:8883 successfully.
Start mqtt:wss:external listener on 0.0.0.0:8084 successfully.
Start http:management listener on 8081 successfully.
Start http:dashboard listener on 18083 successfully.
EMQ X Broker 4.3.10 is running now!
2021-11-23T14:51:07.238304+08:00 [error] supervisor: 'esockd_connection_sup - <0.1816.0>', errorContext: connection_shutdown, reason: {ssl_error,{tls_alert,{bad_certificate,"TLS server: In state certify at ssl_handshake.erl:1885 generated SERVER ALERT: Fatal - Bad Certificate\n"}}}, offender: [{pid,<0.2377.0>},{name,connection},{mfargs,{emqx_connection,start_link,[[{deflate_options,[]},{max_conn_rate,500},{active_n,100},{zone,external},{proxy_address_header,<<>>},{proxy_port_header,<<>>},{supported_subprotocols,[]}]]}}]
2021-11-23T14:51:07.253390+08:00 [error] supervisor: 'esockd_connection_sup - <0.1816.0>', errorContext: connection_shutdown, reason: {ssl_error,{tls_alert,{bad_certificate,"TLS server: In state certify at ssl_handshake.erl:1885 generated SERVER ALERT: Fatal - Bad Certificate\n"}}}, offender: [{pid,<0.2381.0>},{name,connection},{mfargs,{emqx_connection,start_link,[[{deflate_options,[]},{max_conn_rate,500},{active_n,100},{zone,external},{proxy_address_header,<<>>},{proxy_port_header,<<>>},{supported_subprotocols,[]}]]}}]
2021-11-23T14:51:44.208547+08:00 [error] supervisor: 'esockd_connection_sup - <0.1816.0>', errorContext: connection_shutdown, reason: {ssl_error,{tls_alert,{bad_certificate,"TLS server: In state certify at ssl_handshake.erl:1885 generated SERVER ALERT: Fatal - Bad Certificate\n"}}}, offender: [{pid,<0.2397.0>},{name,connection},{mfargs,{emqx_connection,start_link,[[{deflate_options,[]},{max_conn_rate,500},{active_n,100},{zone,external},{proxy_address_header,<<>>},{proxy_port_header,<<>>},{supported_subprotocols,[]}]]}}]
2021-11-23T14:56:29.592960+08:00 [error] supervisor: 'esockd_connection_sup - <0.1816.0>', errorContext: connection_shutdown, reason: {ssl_error,{tls_alert,{bad_certificate,"TLS server: In state certify at ssl_handshake.erl:1885 generated SERVER ALERT: Fatal - Bad Certificate\n"}}}, offender: [{pid,<0.2496.0>},{name,connection},{mfargs,{emqx_connection,start_link,[[{deflate_options,[]},{max_conn_rate,500},{active_n,100},{zone,external},{proxy_address_header,<<>>},{proxy_port_header,<<>>},{supported_subprotocols,[]}]]}}]
2021-11-23T14:57:35.769483+08:00 [error] supervisor: 'esockd_connection_sup - <0.1816.0>', errorContext: connection_shutdown, reason: {ssl_error,{tls_alert,{bad_certificate,"TLS server: In state wait_cert at ssl_handshake.erl:1885 generated SERVER ALERT: Fatal - Bad Certificate\n"}}}, offender: [{pid,<0.2512.0>},{name,connection},{mfargs,{emqx_connection,start_link,[[{deflate_options,[]},{max_conn_rate,500},{active_n,100},{zone,external},{proxy_address_header,<<>>},{proxy_port_header,<<>>},{supported_subprotocols,[]}]]}}]
2021-11-23T14:57:38.889707+08:00 [error] supervisor: 'esockd_connection_sup - <0.1816.0>', errorContext: connection_shutdown, reason: {ssl_error,{tls_alert,{bad_certificate,"TLS server: In state wait_cert at ssl_handshake.erl:1885 generated SERVER ALERT: Fatal - Bad Certificate\n"}}}, offender: [{pid,<0.2515.0>},{name,connection},{mfargs,{emqx_connection,start_link,[[{deflate_options,[]},{max_conn_rate,500},{active_n,100},{zone,external},{proxy_address_header,<<>>},{proxy_port_header,<<>>},{supported_subprotocols,[]}]]}}]
2021-11-23T14:57:39.661654+08:00 [error] supervisor: 'esockd_connection_sup - <0.1816.0>', errorContext: connection_shutdown, reason: {ssl_error,{tls_alert,{bad_certificate,"TLS server: In state wait_cert at ssl_handshake.erl:1885 generated SERVER ALERT: Fatal - Bad Certificate\n"}}}, offender: [{pid,<0.2518.0>},{name,connection},{mfargs,{emqx_connection,start_link,[[{deflate_options,[]},{max_conn_rate,500},{active_n,100},{zone,external},{proxy_address_header,<<>>},{proxy_port_header,<<>>},{supported_subprotocols,[]}]]}}]

是mqtts://192.168.1.13:8883?不是该ssl://**? 可以参考一下这个:EMQ X 启用双向 SSL/TLS 安全连接 | EMQ

MQTT.fx等客户端没有SSL://的选项。MQTT+SSL就是mqtts://

我一开始参考您给的链接做的,也是不成功,而且通过openssl命令验证证书的时候会有报错。

百度了很久,生成的证书才不报错。

证书通过后,目前问题解了吗

没啊,就是因为没解决我才发帖的。
我还有个let’s encrypt的证书。
放上去也不行。如果我用域名来访问emqx,报错是这样的

[2021-11-23 19:21:51] [ERROR] Connect fail, MQTT.js onError trigger, Error: write EPROTO 140367868525848:error:100000f7:SSL routines:OPENSSL_internal:WRONG_VERSION_NUMBER:../../third_party/boringssl/src/ssl/tls_record.cc:242:

    at WriteWrap.onWriteComplete [as oncomplete] (internal/stream_base_commons.js:92:16)
[2021-11-23 19:21:51] [INFO] Connect close, MQTT.js onClose trigger

如果不用域名,用emqx所在机器的内网ip访问,报错是这样的:

[2021-11-23 19:23:04] [ERROR] Connect fail, MQTT.js onError trigger, Error: certificate has expired
    at TLSSocket.onConnectSecure (_tls_wrap.js:1501:34)
    at TLSSocket.emit (events.js:315:20)
    at TLSSocket._finishInit (_tls_wrap.js:936:8)
    at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:710:12)
[2021-11-23 19:23:04] [INFO] Connect close, MQTT.js onClose trigger

刚刚两次访问emqx console的日志是这样的:

EMQ X Broker 4.3.10 is running now!
2021-11-23T19:11:13.952378+08:00 [error] supervisor: 'esockd_connection_sup - <0.1816.0>', errorContext: connection_shutdown, reason: {ssl_error,{tls_alert,{certificate_required,"TLS server: In state wait_cert at tls_handshake_1_3.erl:1366 generated SERVER ALERT: Fatal - Certificate required\n certificate_required"}}}, offender: [{pid,<0.2011.0>},{name,connection},{mfargs,{emqx_connection,start_link,[[{deflate_options,[]},{max_conn_rate,500},{active_n,100},{zone,external},{proxy_address_header,<<>>},{proxy_port_header,<<>>},{supported_subprotocols,[]}]]}}]
2021-11-23T19:12:56.415361+08:00 [error] supervisor: 'esockd_connection_sup - <0.1816.0>', errorContext: connection_shutdown, reason: {ssl_error,{tls_alert,{handshake_failure,"TLS server: In state certify at tls_dtls_connection.erl:314 generated SERVER ALERT: Fatal - Handshake Failure\n no_client_certificate_provided"}}}, offender: [{pid,<0.2035.0>},{name,connection},{mfargs,{emqx_connection,start_link,[[{deflate_options,[]},{max_conn_rate,500},{active_n,100},{zone,external},{proxy_address_header,<<>>},{proxy_port_header,<<>>},{supported_subprotocols,[]}]]}}]
2021-11-23T19:12:56.451434+08:00 [error] supervisor: 'esockd_connection_sup - <0.1816.0>', errorContext: connection_shutdown, reason: {ssl_error,{tls_alert,{handshake_failure,"TLS server: In state certify at tls_dtls_connection.erl:314 generated SERVER ALERT: Fatal - Handshake Failure\n no_client_certificate_provided"}}}, offender: [{pid,<0.2039.0>},{name,connection},{mfargs,{emqx_connection,start_link,[[{deflate_options,[]},{max_conn_rate,500},{active_n,100},{zone,external},{proxy_address_header,<<>>},{proxy_port_header,<<>>},{supported_subprotocols,[]}]]}}]

这个证书的问题,搞了我3天了,不明白问题出在哪里?我看了那么多配置方法,没觉得我哪里配置有问题啊。

这里是证书的过期了。控制台中日值原因也是ssl握手失败。整体看来是你证书感觉有问题,你要不根据上面博客的链接,自己生成一个证书进行测试一下。

证书没过期。

no_client_certificate_provided ,还是证书方面的问题;要么是使用证书方式不对。你先抛开你的证书,按照博客上的双向证书进行操作一遍看看。其实目前跟emqx本身没多少关系,还处在ssl连接握手就有问题

[EMQ X 启用双向 SSL/TLS 安全连接]
根据您给的这个链接做的证书,在emqx无法开启ssl,会报证书错误。

百度了这个方法

#/bin/sh
# 生成自签名的CA key和证书
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -subj "/CN=xxx.xxx.net" -out ca.pem

# 生成服务器端的key和证书
openssl genrsa -out server.key 2048
openssl req -new -key ./server.key -out server.csr -subj "/CN=0.0.0.0"
openssl x509 -req -in ./server.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out server.pem -days 3650 -sha256

# 生成客户端key和证书
openssl genrsa -out client.key 2048
openssl req -new -key ./client.key -out client.csr -subj "/CN=0.0.0.0"
openssl x509 -req -in ./client.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out client.pem -days 3650 -sha256

用这个方法的证书,可以开启SSL,并连上。需要注意的是:CN=xxx.xxx.netCN=0.0.0.0 两个需要匹配,否则会报 onnect fail, MQTT.js onError trigger, Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate's altnames: Host: xxx.xxx.net. is not cert's CN: 0.0.0.0

另外,借帖子咨询您两个问题:

  1. 我开启了证书,1883还种不安全的连接还是能连上,我是不是要注释掉1883端口?
  2. 请问下 let‘sencrypt 证书如何应用在emqx上。我现在没有固定的公网ip,现在和几个朋友研究下emqx,为了方便他们连接,用 let’sencrypt 证书比自签证书方便很多。
  1. emqx 有4个服务针对不同方式:

    • tcp:1883
    • ssl:8883
    • ws:8083
    • wss:8084
      如果不想启动监听某个端口,可以直接注释掉listeners.conf中相关的监听项。
  2. 没有固定的话,申请域名进行解决你的公网问题,证书里是地址是可以支持域名的。

域名我是有的,只是百度出来的都是emqx使用自签证书的使用方式。对于用let’s encrypt这种证书的案例几乎没有,能找到的都是emqx2.x的教程,而且不完整。

我目前也还没接触过这种证书,抱歉。给你另外一种实现建议:使用nginx 代理进行证书卸载。然后nginx到emqx之间使用tcp 连接