zoukankan      html  css  js  c++  java
  • MQTT研究之EMQ:【wireshark抓包分析】

    基于上篇博文【SSL双向验证】的环境基础,进行消息的具体梳理.

    环境基础信息:

    1. 单台Linux CentOS7.2系统,安装一个EMQTTD的实例broker。
    2. emq的版本2.3.113. 客户端分为mosquitto_pub,以及MQTT.fx 1.7.1的subscriber。
    4. 证书是通过openssl(version:1.0.2k-fips)生成的,rootCA是自签名的,subscriber和publisher的证书是通过rootCA签署的。
    5. 抓包工具wireshark(version: 2.6.6,下载地址https://www.wireshark.org/download/win64/),分析SSL/TLS通信的消息流.

    第一步:通过wireshark抓取SSL双向验证的消息

    下面是我测试过程中,得到的消息流程,我的测试环境,在TLS的两层消息结构(record layer,handshake layer)中的握手协议环节,得到的cipher suite的值是:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384

    先简单介绍下,这个cipher suite的含义,这个应该是SSL/TLS协议中比较难以理解的一个概念。这个说简单点,就是秘钥协商(Key agreement)的顶层设计,后续的消息流程都是密切的基于这个cipher suite的值而有较大的不同,准确的说,秘钥交换(Key exchange)和上诉红色部分关系最为密切.

    1、秘钥协商和秘钥交换这两个概念,看到很多地方的讨论和描述中,似乎没有区分的很明确,依据我的理解,秘钥协商和秘钥交换,确实有很大的关联性,不可能完全割裂或者分离关系,只是两个概念描述的侧重点不同,秘钥协商更多表述怎么做这个逻辑,而秘钥交换,更多侧重怎么做的实际动作或者流程

    2、cipher suite的简单介绍

    就拿我这个测试的cipher suite值说明吧。

    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384

            键值交换签名协议       数据加密算法       信息认证码算法

    更详细的介绍,可以对照下面这个图:

    秘钥协商/交换,是为了在握手的过程中,基于给定的cipher suite完成shared secret的生成过程,这个秘钥就是用来为后续数据传输的时候对称加密用的密码信息验证码协议,是为了保证数据传输的时候的数据一致性或者完整性的。

    在我们这个测试中,基于上述cipher suite得到的消息流如下:

    C->S: Client Hello
    S->C: Server Hello
    S->C: Certificate,Server Key Exchange, Certificate Request, Server Hello Done
    C->S: Certificate, Client Key Exchange
    C->S: Certificate Verify,Change Cipher Spec,Encrypted Handshake Message
    S->C: Change Cipher Spec,Encrypted Handshake Message
    C->S: Application Data
    S->C: Application Data

    a. C->S: Client Hello

    b. S->C: Server Hello

    c. S->C: Certificate,Server Key Exchange, Certificate Request, Server Hello Done (这里的Certificate Request,就是服务端要求客户端上报证书

    d. C->S: Certificate, Client Key Exchange (这个环节很重要,体现了双向SSL验证的特征了,服务端要求的身份验证,即希望校验客户端的证书的过程)

    e. C->S: Certificate Verify,Change Cipher Spec,Encrypted Handshake Message

    这个消息,其实理解起来似乎有点不好理解。为何客户端要上报Certificate Verify呢

    1). certificate Verify消息必须在client key exchange后面由客户端发出去给服务器端。
    2). 这个消息,是客户端构建的,内容是客户端收发的所有的handshake消息(不含当前这个Verify的消息)拼接后的内容进行hash,然后用证书对应的私钥进行签名后所得的内容S1。
    3). 这个消息,服务端会进行验证。验证的逻辑,通过对服务端缓存的客户端消息,以及服务端发送的所有handshake消息,同样进行拼接然后计算hash值h2,用客户端的证书中的公钥解析Verify中的签名S1得到对应的hash值h1,对比h1和和
    ,若相同,则验证通过,否则失败。

    可以参考这个链接中的内容,其实,他的解释或者介绍,也是基于RFC文档中的内容进行的,只是比较白话了,相对好懂些。

    f. S->C: Change Cipher Spec,Encrypted Handshake Message

    g.C->S: Application Data

    第二步:单向SSL验证(客户端验证服务端的合法性)

    1. 配合broker

    ## Path to the file containing the user's private PEM-encoded key.
    ##
    ## See: http://erlang.org/doc/man/ssl.html
    ##
    ## Value: File
    #listener.ssl.external.keyfile = /etc/emqttd/certs/key.pem
    listener.ssl.external.keyfile = /opt/certs/server.key
    
    ## 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_none    #主要是在双向验证的基础上将此配置改为verify_none
    
    ## 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

    2. 通过wireshark抓取SSL消息流

    具体的通过wireshark抓取SSL消息流

    C->S: Client Hello
    S->C: Server Hello
    S->C: Certificate, Server Key Exchange, Server Hello Done
    C->S: Client Key Exchange
    C->S: Change Cipher Spec, Encrypted Handshake Message
    S->C: Change Cipher Spec, Encrypted Handshake Message
    C->S: Application Data
    S->C: Application Data
    ......
    S->C: Encrypted Alert
    C->S: Encrypted Alert

    最后,补充一下,关于DH秘钥交换的流程图,ECDH交换和DH交换流程逻辑相同,只是算法中交换的参数计算逻辑不同而已,从DH升级到ECDH是可以平滑做到的。

    ECDH秘钥交换说明

    假设密钥交换双方为Alice、Bob,其有共享曲线参数(椭圆曲线E、阶N、基点G),对于于上图中的common paint黄色信息,是大家共有的,只是每次协商时,值不同,但是双方都是知道的

    1.Alice生成随机整数a (对应上图中的orange,计算A=a*G(这个A,对应上图中orange-tan)。Bob生成随机整数b(对应上图中的blue-green,计算B=b*G(这个B,对应上图中的light-blue)。

    2.Alice将A传递给Bob。A的传递可以公开,即攻击者可以获取A。由于椭圆曲线的离散对数问题是难题,所以攻击者不可以通过A、G计算出a。Bob将B传递给Alice。同理,B的传递可以公开。

    3.Bob收到Alice传递的A,计算Q=b*A 这里的Q,对应上图中yellow-brown

    4.Alice收到Bob传递的B,计算Q‘=a*B这里的Q‘,对应上图中yellow-brown

    Alice、Bob双方即得Q=b*A=b*(a*G)=(b*a)*G=(a*b)*G=a*(b*G)=a*B=Q' (交换律和结合律),即双方得到一致的密钥Q。

    到此,整个秘钥交换为核心的SSL消息流,大体就算是弄清楚了。

  • 相关阅读:
    在Ubuntu上安装Hadoop(集群模式)
    Node.js v0.10.8 发布
    设置 Sublime Text 的 Python 开发环境
    jQuery 1.10.0 和 2.0.1 发布
    openSUSE 13.1 Milestone 2 发布
    mochad 0.1.6 发布,TCP 网关守护进程
    JPPF 3.3.2 发布,Java 并行处理框架
    PyCharm 又一强大Python IDE
    AntiXSS 支持Html同时防止XSS攻击
    (原创)攻击方式学习系列(总)
  • 原文地址:https://www.cnblogs.com/shihuc/p/10307305.html
Copyright © 2011-2022 走看看