MQTT协议TLS/SSL部分测试双向验证出现的问题

Mosquitto官方提供了一个测试地址供我们使用。其中8883和8884端口是支持TLS/SSL的。区别在于端口8883只需要客户端验证服务端的链接即可,端口8884需要双向验证客户端也需要向服务器上传证书。

两个端口的测试代码我在之前的文章iOS开发中MQTTKit的TLS/SSL支持方案已经提供。关于客户端证书,我们需要向Generate a TLS client certificate for test.mosquitto.org请求。根据官网的提示,我们可以借助openssl来实现。

  • 生成密钥
    openssl genrsa -out client.key
  • 生成CSR文件
    openssl req -out client.csr -key client.key -new

执行完这两个命令之后终端当前所在路径下会生成两个文件

文件.png

用记事本将csr文件的内容拷贝进Generate a TLS client certificate for test.mosquitto.org的输入框,验证合法之后就会自动下载生成的客户端证书client.crt。我们将client.keyclient.crt导入工程,可是一直验证的结果是身份验证失败。但是端口8883是没有问题成功建立连接的。

先简单捋一下TLS/SSL的流程

TLS:SSL流程.jpg

双向验证多出的部分就在于对客户端证书的请求和验证。我们首先应该排除密钥和证书不匹配的问题,因为在SSL_Connect()之前配置客户端密钥和证书的时候我们已经通过SSL_CTX_check_private_key验证过了。那么客户端证书和密钥没有问题的情况下,链接究竟是被谁主动断开的?

  • 服务端断开
    最大的可能是客户端证书验证不通过
  • 客户端断开
    配置代码出现问题/服务端证书验证不过/参数设置出错/openssl的问题...

这个时候我们可以借助一下Wireshark来帮助我们查看一下客户端和服务端之间通讯的情况究竟是怎样。首先我们查看一下连接成功的端口8883整个通讯过程

端口8883.png

我们简单分析一下。No.73之后的报文是PINGREQ和PINGRES的过程,查看Time也可以发现No.72和No.73两个报文之间间隔了60s的实现,这一部分我们不需要关心。No.34 - No.72是TCP的三次握手,TLS/SSL连接验证,MQTT协议CONNECT和ACK的整个流程。
以下是作者手画的流程,已经过滤了TCP的三次握手

MQTT Port 8883.JPG

图中标示的包的大小包含了IP首部和TCP首部,所以不是MQTT协议报文的真实大小,为了大家对比方便我就按照Wireshark显示的大小来标注了。这个流程对比上面标准的TLS/SSL流程少了很多的步骤。报文中我们可以看到PSH这个标志位,这是告诉当前网络立刻将当前的数据发送出去,其中一些步骤可能合并成一个报文发出。因为TCP协议本身有一个特性是ACK捎带,所以报文看起来比较混杂而不是清清楚楚的Request和ACK一一对应。MQTT协议本身的内容因为被加密无法被Wireshark识别出来,所以识别成了TCP报文。

分析完端口8883,让我们看一下端口8884的通讯情况


端口8884.png

这个看起来就简单多了。

  1. TCP三次握手
  2. 大小为359的报文发出,这是Client Hello
  3. 1480是Server Hello的部分
  4. 再往下看就和端口8883不一样了,之前端口8883服务端发送了大小为976的报文,但是端口8884发送的报文大小是1018。为什么报文的大小不一样呢?因为双向验证中服务器会多发送Cerificate Request的部分,这对于单向验证的端口8883是可选略过的。
  5. No.25是No.24的确认,No.26客户端发送给服务端的报文FIN置1了。

也就是说连接是在客户端接收了服务端证书和请求之后,被客户端主动关闭的。我尝试在源码添加了打印信息,着重在证书验证的部分,在对服务端证书验证的回调int _mosquitto_server_certificate_verify(int preverify_ok, X509_STORE_CTX *ctx)里我找到了一个返回错误码的地方。

return _mosquitto_verify_certificate_hostname(cert, mosq->host);

作者在这添加了一个FIXME,提示我们如果你的openssl版本足够新的话(>=1.1.x),这里请使用X509_check_host()。在修改代码之后这一部分验证成功,但是...
客户端还是发送了一个FIN关闭了连接。 = 。=

因为Client Hello是成功发送并接收到Server Hello的,这说明SSL这一部分的代码,SSL_Connect()之前配置的部分是没有问题的。我尝试打印了SSL_Connect()的返回码,果然出现了问题,返回了SSL_ERROR_SSL = 1。我获取了具体出错的原因

char msg[1024];
ERR_error_string_n(ERR_get_error(), msg, sizeof(msg));
_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "SSL Connect Error: %s", msg);

rsa routines:RSA_sign:digest too big for rsa key"

这里有一个具体的讨论OpenSSL - What is the reason for error "SSL negotiation failed: error:04075070:rsa routines:RSA_sign:digest too big for rsa key"。如果你有兴趣可以自行查看一下讨论,我在这里简单总结一下。

记得Mosquitto测试地址提示我们可以使用Openssl来生成私钥,使用的Command是openssl genrsa -out client.key。缺省情况下生成的是RSA-512。但是

Or use another hash type for signature which can produce not more than 53 bytes of hashed data. (i.e MD5, SHA1, SHA256, SHA384) while using 512-bit keys. OpenSSL by default uses SHA512 hash for signature. Change the code to use any other hash.
512 bit(64 byte) RSA key can only encrypt 53 bytes at max. 64 - 11 byte padding and SHA512 produces 64 bytes of hashed data.

Openssl默认使用的是SHA512来签名。RSA-512包含64个字节,移除了padding部分能够编码的最大长度是64 - 11 = 53个字节,但是SHA512生成了64个字节。我们可以使用其它的哈希类型来签名比如说(MD5, SHA1, SHA256, SHA384) ,或者使用RSA-1024及其它更长的密钥。

所以我们生成证书的时候后面要添加一个长度参数

openssl genrsa -out client.key 1024

重新生成客户端密钥和证书以后,端口8884的测试顺利通过了 :)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,529评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,015评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,409评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,385评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,387评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,466评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,880评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,528评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,727评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,528评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,602评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,302评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,873评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,890评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,132评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,777评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,310评论 2 342

推荐阅读更多精彩内容