• MQTT研究之EMQ:【SSL双向验证】


    EMQ是当前MQTT中,用于物联网领域中比较出色的一个broker,今天我这里要记录和分享的是关于SSL安全通信的配置和注意细节。

    环境:

    1. 单台Linux CentOS7.2系统,安装一个EMQTTD的实例broker。

    2. emq的版本2.3.11。

    3. 客户端分为mosquitto_pub,以及MQTT.fx 1.7.1的subscriber。

    4. 证书是通过openssl(version:1.0.2k-fips)生成的,rootCA是自签名的,subscriber和publisher的证书是通过rootCA签署的。

    1、CA根证书的生成

    [root@ws3 certs]# openssl req -x509 -new -days 3650 -keyout ca.key -out rootCA.crt -nodes
    Generating a 2048 bit RSA private key
    .....................+++
    .........................................................................................................................+++
    writing new private key to 'ca.key'
    -----
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [XX]:CN  
    State or Province Name (full name) []:Hubei
    Locality Name (eg, city) [Default City]:Wuhan
    Organization Name (eg, company) [Default Company Ltd]:abcdefg
    Organizational Unit Name (eg, section) []:Tkcloud
    Common Name (eg, your name or your server's hostname) []:10.95.197.3
    Email Address []:

    2、为server端生成证书

    a. 生成私有秘钥

    [root@ws3 certs]# openssl genrsa -out server.key 2048
    Generating RSA private key, 2048 bit long modulus
    ...................................................+++
    ............+++
    e is 65537 (0x10001)

    b. 生成证书请求csr文件

    [root@ws3 certs]# openssl req -new -key server.key -out server.csr
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [XX]:CN
    State or Province Name (full name) []:Hubei
    Locality Name (eg, city) [Default City]:Wuhan
    Organization Name (eg, company) [Default Company Ltd]:abcdefg
    Organizational Unit Name (eg, section) []:Cloud
    Common Name (eg, your name or your server's hostname) []:10.95.197.3
    Email Address []:
    
    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:
    An optional company name []:

    c. 生成证书

    [root@ws3 certs]# openssl ca -in server.csr -out server.crt -cert rootCA.crt -keyfile ca.key -days 3650
    Using configuration from /etc/pki/tls/openssl.cnf
    /etc/pki/CA/index.txt: No such file or directory
    unable to open '/etc/pki/CA/index.txt'
    140188069304208:error:02001002:system library:fopen:No such file or directory:bss_file.c:402:fopen('/etc/pki/CA/index.txt','r')
    140188069304208:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:404:

    错误分析:
    缺乏/etc/pki/CA/index.txt,对应的创建一个空文件即可

    再次执行证书生成过程:

    [root@ws3 certs]# openssl ca -in server.csr -out server.crt -cert rootCA.crt -keyfile ca.key -days 3650           
    Using configuration from /etc/pki/tls/openssl.cnf
    /etc/pki/CA/serial: No such file or directory
    error while loading serial number
    140539902367632:error:02001002:system library:fopen:No such file or directory:bss_file.c:402:fopen('/etc/pki/CA/serial','r')
    140539902367632:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:404:

    错误分析:
    缺乏/etc/pki/CA/serial文件,对应的创建这个文件
    再次执行上述生成指令:

    [root@ws3 certs]# openssl ca -in server.csr -out server.crt -cert rootCA.crt -keyfile ca.key -days 3650
    Using configuration from /etc/pki/tls/openssl.cnf
    unable to load number from /etc/pki/CA/serial
    error while loading serial number
    140553210034064:error:0D066096:asn1 encoding routines:a2i_ASN1_INTEGER:short line:f_int.c:210:

    错误分析:
    缺乏序号数据,是没有序号数据。写入1,保存后,继续执行上述过程

    [root@ws3 certs]# openssl ca -in server.csr -out server.crt -cert rootCA.crt -keyfile ca.key -days 3650
    Using configuration from /etc/pki/tls/openssl.cnf
    unable to load number from /etc/pki/CA/serial
    error while loading serial number
    139880943351696:error:0D066096:asn1 encoding routines:a2i_ASN1_INTEGER:short line:f_int.c:210:

    错误分析:
    写的数据格式不对,需要写入两位的01格式,保存后继续运行。

    [root@ws3 certs]# openssl ca -in server.csr -out server.crt -cert rootCA.crt -keyfile ca.key -days 3650
    Using configuration from /etc/pki/tls/openssl.cnf
    Check that the request matches the signature
    Signature ok
    Certificate Details:
            Serial Number: 1 (0x1)
            Validity
                Not Before: Jan 17 14:38:42 2019 GMT
                Not After : Jan 14 14:38:42 2029 GMT
            Subject:
                countryName               = CN
                stateOrProvinceName       = Hubei
                organizationName          = abcdefg
                organizationalUnitName    = Cloud
                commonName                = 10.95.197.3
            X509v3 extensions:
                X509v3 Basic Constraints: 
                    CA:FALSE
                Netscape Comment: 
                    OpenSSL Generated Certificate
                X509v3 Subject Key Identifier: 
                    90:F2:F6:57:31:DB:1A:81:B7:11:08:12:46:A0:FE:DB:6F:84:A9:DE
                X509v3 Authority Key Identifier: 
                    keyid:DF:2F:DC:D6:75:2A:06:C0:D0:39:6C:32:11:A8:60:72:F4:9B:EB:DD
    
    Certificate is to be certified until Jan 14 14:38:42 2029 GMT (3650 days)
    Sign the certificate? [y/n]:y
    
    
    1 out of 1 certificate requests certified, commit? [y/n]y
    Write out database with 1 new entries
    Data Base Updated

    CA这个信息为FALSE,表明这个证书不是根证书

    上面的rootCA.crt是根证书,看看内容:

    [root@ws3 certs]# openssl x509 -text -in rootCA.crt -noout   
    Certificate:
        Data:
            Version: 3 (0x2)
            Serial Number:
                db:61:ba:05:39:42:54:21
        Signature Algorithm: sha256WithRSAEncryption
            Issuer: C=CN, ST=Hubei, L=Wuhan, O=abcdefg, OU=Tkcloud, CN=10.95.197.3
            Validity
                Not Before: Jan 17 15:20:50 2019 GMT
                Not After : Dec 24 15:20:50 2118 GMT
            Subject: C=CN, ST=Hubei, L=Wuhan, O=abcdefg, OU=Tkcloud, CN=10.95.197.3
            Subject Public Key Info:
                Public Key Algorithm: rsaEncryption
                    Public-Key: (2048 bit)
                    Modulus:
                        00:95:b4:50:75:5b:c6:23:b4:67:1c:5f:89:25:b8:
                        bf:8a:9b:e1:fa:95:81:81:87:71:2b:6e:16:b9:07:
                        a2:1c:67:76:35:da:fb:5b:25:6b:db:bd:29:cd:55:
                        98:ca:95:3e:2f:bb:c3:b5:61:4d:c9:d6:9c:1b:b9:
                        06:59:24:e8:ed:5a:d9:ca:84:07:4e:7d:e6:42:8f:
                        7e:98:25:48:17:9c:18:d4:ff:26:c4:aa:dc:dd:de:
                        91:78:33:e2:9c:3d:95:56:4d:d1:5a:78:ea:b8:49:
                        38:1e:b8:89:a3:6f:79:ba:b2:97:02:81:5c:8b:0b:
                        d3:45:be:a1:49:e6:64:26:59:cf:86:18:14:3a:31:
                        f0:e1:c8:04:52:1e:cf:fb:4a:ee:5a:a9:7d:bc:63:
                        d2:fe:2c:f5:8f:a4:b2:cc:52:92:d2:9d:a0:d2:2e:
                        4e:4f:e7:77:6c:0d:81:59:42:13:b6:7c:19:45:f6:
                        e9:c6:33:5e:21:ea:01:02:61:2d:53:e2:f2:bf:06:
                        59:63:7e:37:cf:bd:2a:44:63:77:c1:8f:c5:56:9e:
                        35:f8:26:17:08:79:75:c3:05:2f:b4:fc:d2:95:96:
                        cb:0c:dd:6f:ef:9f:5d:57:48:4e:78:2b:75:2e:3a:
                        37:8e:c9:95:f0:7c:92:80:a3:ac:f7:66:9d:16:59:
                        e7:f9
                    Exponent: 65537 (0x10001)
            X509v3 extensions:
                X509v3 Subject Key Identifier: 
                    AB:2E:65:BE:15:CB:A1:29:A4:09:97:A8:CB:39:2A:3F:ED:4C:1E:16
                X509v3 Authority Key Identifier: 
                    keyid:AB:2E:65:BE:15:CB:A1:29:A4:09:97:A8:CB:39:2A:3F:ED:4C:1E:16
    
                X509v3 Basic Constraints: 
                    CA:TRUE
        Signature Algorithm: sha256WithRSAEncryption
             4c:35:ad:41:4f:9d:e6:c3:f2:87:08:50:70:4f:81:09:da:1c:
             c4:d7:25:60:0f:1a:d6:2b:e8:8e:9d:45:6e:47:13:ee:b0:c2:
             21:96:2e:e2:eb:2e:c0:a7:60:ba:00:dc:b6:94:45:f9:7d:ff:
             97:dc:dc:92:d3:aa:85:2a:fe:f4:91:c7:0e:f8:2e:de:2d:28:
             a0:a1:f5:74:f1:cc:8f:2f:00:fe:0c:35:6d:de:00:ff:46:8c:
             22:21:53:22:ea:2b:b1:7d:ac:e4:b4:c0:e7:91:95:40:96:da:
             93:48:57:91:88:0a:6d:3d:a5:de:65:9b:be:72:ef:d0:f4:2a:
             a0:db:47:6e:6c:bf:f6:fb:a7:3f:1c:4b:bd:c6:6c:9f:62:3b:
             d3:d3:b3:7f:ce:b8:83:86:20:c1:28:8e:42:c2:60:d1:26:ee:
             33:27:e2:78:a7:0c:26:3a:b9:94:01:c6:11:19:56:77:76:e7:
             ed:06:fc:76:d9:7e:06:f8:a3:15:8a:a2:89:33:b5:e0:0e:9d:
             4d:3a:b6:15:33:40:0d:26:ac:67:92:0b:96:17:13:66:93:c8:
             0d:ea:ed:68:e9:ff:4a:3e:e5:27:53:71:e2:53:82:83:f1:68:
             01:d9:6b:5b:51:bf:84:7f:ad:0d:2f:98:d6:fb:04:a4:e5:78:
             1c:82:94:de

    证书生成完毕后,查看上面创建的index.txt以及serial文件:

    [root@ws3 certs]# vi /etc/pki/CA/index.txt
    V       290114143842Z           01      unknown /C=CN/ST=Hubei/O=abcdefg/OU=Cloud/CN=10.95.197.3
    [root@ws3 certs]# vi /etc/pki/CA/serial
    02

    注意:起初index.txt是空的,证书创建成功后,写入了一条记录。serial文件,起初是01,然而,现在变成了02.

    3. 为客户端生成证书

    这里,省略生成私钥,以及证书请求的过程,重点关注基于根证书rootCA.crt生成证书的过程。

    [root@ws3 certs]# openssl ca -in client.csr -out client.crt -cert rootCA.crt -keyfile ca.key 
    Using configuration from /etc/pki/tls/openssl.cnf
    Check that the request matches the signature
    Signature ok
    Certificate Details:
            Serial Number: 2 (0x2)
            Validity
                Not Before: Jan 17 14:56:37 2019 GMT
                Not After : Jan 17 14:56:37 2020 GMT
            Subject:
                countryName               = CN
                stateOrProvinceName       = Hubei
                organizationName          = abcdefg
                organizationalUnitName    = cloud
                commonName                = client
            X509v3 extensions:
                X509v3 Basic Constraints: 
                    CA:FALSE
                Netscape Comment: 
                    OpenSSL Generated Certificate
                X509v3 Subject Key Identifier: 
                    D7:A0:13:02:40:47:1F:E1:89:71:EA:60:31:57:3A:A5:50:7D:5B:43
                X509v3 Authority Key Identifier: 
                    keyid:DF:2F:DC:D6:75:2A:06:C0:D0:39:6C:32:11:A8:60:72:F4:9B:EB:DD
    
    Certificate is to be certified until Jan 17 14:56:37 2020 GMT (365 days)
    Sign the certificate? [y/n]:y
    
    
    1 out of 1 certificate requests certified, commit? [y/n]y
    Write out database with 1 new entries
    Data Base Updated

    客户证书只有1年(不加参数-days的话,默认是1年),而服务端证书时候10年的有效期

    4. 验证双向SSL的通信过程。

    1). 配置emqtt

    ## Path to a file containing the user certificate.
    ##
    ## See: http://erlang.org/doc/man/ssl.html
    ##
    ## Value: File
    #listener.ssl.external.certfile = /etc/emqttd/certs/cert.pem
    listener.ssl.external.certfile = /opt/certs/server.crt
    
    ## Path to the file containing PEM-encoded CA certificates. The CA certificates
    ## are used during server authentication and when building the client certificate chain.
    ##
    ## Value: File
    ## listener.ssl.external.cacertfile = /etc/emqttd/certs/cacert.pem
    listener.ssl.external.cacertfile = /opt/certs/rootCA.crt
    
    ## The Ephemeral Diffie-Helman key exchange is a very effective way of
    ## ensuring Forward Secrecy by exchanging a set of keys that never hit
    ## the wire. Since the DH key is effectively signed by the private key,
    ## it needs to be at least as strong as the private key. In addition,
    ## the default DH groups that most of the OpenSSL installations have
    ## are only a handful (since they are distributed with the OpenSSL
    ## package that has been built for the operating system it’s running on)
    ## and hence predictable (not to mention, 1024 bits only).
    ## In order to escape this situation, first we need to generate a fresh,
    ## strong DH group, store it in a file and then use the option above,
    ## to force our SSL application to use the new DH group. Fortunately,
    ## OpenSSL provides us with a tool to do that. Simply run:
    ## openssl dhparam -out dh-params.pem 2048
    ##
    ## Value: File
    ## listener.ssl.external.dhfile = /etc/emqttd/certs/dh-params.pem
    
    ## A server only does x509-path validation in mode verify_peer,
    ## as it then sends a certificate request to the client (this
    ## message is not sent if the verify option is verify_none).
    ## You can then also want to specify option fail_if_no_peer_cert.
    ## More information at: http://erlang.org/doc/man/ssl.html
    ##
    ## Value: verify_peer | verify_none
    listener.ssl.external.verify = verify_peer
    
    ## Used together with {verify, verify_peer} by an SSL server. If set to true,
    ## the server fails if the client does not have a certificate to send, that is,
    ## sends an empty certificate.
    ##
    ## Value: true | false
    listener.ssl.external.fail_if_no_peer_cert = true

    上述几个红色的部分,是涉及SSL通信要用到的。单双向验证的核心参数是listener.ssl.external.verify = verify_peer,这里是双向验证,即服务端要向客户端发起身份验证工作。verify_none表示服务端不对客户端进行身份验证

    2). 这里消费者客户端使用的是MQTT.fx客户端工具(1.7.1),跑在windows机器上。

    a. 按照下面的config.jpg图片显示内容,配置好相关信息。

    emqtt配置了用户身份认证,是通过用户名和密码做的。必须输入上述参数

    上图中配置的证书相关的参数对应的文件,就是前面生成的证书相关文件,copy到了MQTT.fx所在的windows机器上了


    b. 按照图connection.jpg点击connect即可,如图所示表示连接成功。


    c. 按照图片subscribe.jpg所示,进行订阅。

    3). 消息生产者跑在Linux机器上,通过mosquitto_pub实现。

    [root@ws3 certs]# mosquitto_pub -h 10.95.197.3 -t taikang/rulee --cafile /opt/certs/rootCA.crt --cert /opt/certs/client.crt --key /opt/certs/client.key -u water -P water -m "hellooooo my iot platform"

    此时,MQTT.fx客户端上收到了刚才发送的数据,结果如下图.

    4). 这里,基于上面listener.ssl.external.verify = verify_peer (broker要验证client的身份)做些方向测试验证,主要验证是不是双向验证逻辑

    a. MQTT.fx上,将证书中client.key换成其他的key,和client.crt不配对的,看能否建立连接。效果如图下图. 而且,配置中根证书,客户证书,客户私钥,这三个任何一个配置不匹配,会出现不同的错误信息,自行尝试验证。

    b. Mosquitto_pub端,选择将cert的参数选成另外一个证书,和上述的client.key不匹配即可,错误如下:

    [root@ws3 certs]# mosquitto_pub -h 10.95.197.3 -t taikang/rulee --cafile /opt/certs/rootCA.crt --cert /etc/emqttd/certs/client-cert.pem --key /opt/certs/client.key -u water -P water -m "hellooooo5" -d                 
    Error: Unable to load client key file "/opt/certs/client.key".
    OpenSSL Error: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch
    Unable to connect (A TLS error occurred.).

    从上面a和b两边的测试验证,说明自行生成的客户端和服务端证书,在emqtt配置成双向验证的情况下,工作是符合设定的业务逻辑的。

    下一篇博文,将从wireshark抓包的角度分析SSL通信模式下,单向验证和双向验证,在SSL/TLS消息流上的差异。

  • 相关阅读:
    ECMAScript——引用数据类型之date
    ECMAScript——引用数据类型之RegExp
    ECMAScript——引用数据类型之array
    ECMAScript——引用数据类型之object
    ECMAScript——基本数据类型之null和undefined
    ECMAScript——基本数据类型之boolean
    ECMAScript——基本数据类型之string
    ECMAScript——基本数据类型之number
    libgdx 3D Bullet 碰撞检测二
    libgdx 3D Bullet 碰撞检测一
  • 原文地址:https://www.cnblogs.com/shihuc/p/10285836.html
Copyright © 2020-2023  润新知