分类 OpenSSL 下的文章

“OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包来进行安全通信,避免窃听,同时确认另一端连线者的身份。这个包广泛被应用在互联网的网页服务器上。 其主要库是以C语言所写成,实现了基本的加密功能,实现了SSL与TLS协议。”

安装软件

sudo apt install mosquitto

生成CA密钥

openssl genrsa -des3 -out ca.key 2048

签发CA证书/根证书

openssl req -new -x509 -days 3650 -key ca.key -out ca.crt

生成服务端密钥

openssl genrsa -out server.key 2048

生成证书签名请求

openssl req -new -out server.csr -key server.key

让CA签发证书

openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 360

修改mosquitto.conf内容
listener 8883
cafile /etc/mosquitto/ca_certificates/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
tls_version tlsv1.2

mqtt broker运行测试

mosquitto -c etc/mosquitto.conf 

1626408211: mosquitto version 2.0.11 starting
1626408211: Config loaded from etc/mosquitto.conf.
1626408211: Opening ipv4 listen socket on port 8883.

发布消息

mosquitto_pub -d -h localhost -t "topic/test" -m "hello world" --cafile /etc/mosquitto/ca_certificates/ca.crt -p 8883

订阅消息

mosquitto_sub -d -h localhost -t "topic/test" --cafile /etc/mosquitto/ca_certificates/ca.crt -p 8883

双向认证测试(需要根证书,客户证书,服务器证书以及各自的私钥)

可以使用test.mosquitto.org服务器来测试

测试命令:

openssl s_client -connect test.mosquitto.org:8884 -key test/mosquitto-client.key -cert test/mosquitto-client.crt -CAfile mosquitto.org.crt -showcerts

其中mosquitto-client.key 自己生成,mosquitto-client.crt在mosquitto的网站上签发. 可以参考这篇文章https://const.net.cn/151.html

运行结果:
Acceptable client certificate CA names
C = GB, ST = United Kingdom, L = Derby, O = Mosquitto, OU = CA, CN = mosquitto.org, emailAddress = roger@atchoo.org
Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:RSA+SHA224
Shared Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
...
SSL handshake has read 2741 bytes and written 2690 bytes
Verification: OK
...
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
SSL-Session:
Protocol : TLSv1.3
Cipher : TLS_AES_256_GCM_SHA384
Session-ID: 904A1381D17A1C4432A0DE5EE0D7564C1E4AD4A3E46B7EE173E61B1034A95EB1
Session-ID-ctx:
Resumption PSK: AC27C990D68B5EE27235A5A659EA25CD2D4DE28D233175DFD7ECD09A6FFB4BE418B8C4F1FB87DDF6E666E82EC2A0BC0A
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 7200 (seconds)
TLS session ticket:
0000 - eb 13 3c cb 1b 08 5a 65-79 37 75 92 30 fd 47 46 ..<...Zey7u.0.GF
0010 - e8 09 6a 31 83 91 16 f8-29 9c a8 cc d3 e6 00 ad ..j1....).......

Start Time: 1626417683
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: no
Max Early Data: 0
使用自签名证书,自己搭建服务器的话

openssl s_server -accept 8888 -key server.key -cert server.crt -CAfile ca.crt -Verify 1

verify depth is 1, must return a certificate
Using default temp DH parameters

openssl s_client -connect localhost:8883 -key client.key -cert client.crt -CAfile ca.crt

...
Start Time: 1626418308
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: no
Max Early Data: 0
...

使用mqtts的时候,连接提示错误:

mosquitto_sub -L mqtts://124.71.233.xx:8883/ -t "command///req/#" --cert cert.pem --key key.pem --cafile ../trusted-certs.pem -q 1

Unable to connect (A TLS error occurred.).

加上调试信息打印

mosquitto_sub -L mqtts://124.71.233.xx:8883/ -t "command///req/#" --cert cert.pem --key key.pem --cafile ../trusted-certs.pem -q 1 -d

Error: Unable to load client certificate "cert.pem".
OpenSSL Error[0]: error:140AB18E:SSL routines:SSL_CTX_use_certificate:ca md too weak
Unable to connect (A TLS error occurred.).

查看openssl软件版本
openssl
OpenSSL> version
OpenSSL 1.1.1f 31 Mar 2020
OpenSSL> quit

使用openssl s_client 测试

openssl s_client -connect 124.71.233.xx:8883 -cert cert.pem -key key.pem -CAfile ../trusted-certs.pem -showcerts

error setting certificate
140341384697152:error:140AB18E:SSL routines:SSL_CTX_use_certificate:ca md too weak:../ssl/ssl_rsa.c:310:
出现同样的错误。

查看证书信息

openssl x509 -text -in cert.pem

Signature Algorithm: sha1WithRSAEncryption

众所周知,sha1算法很弱且已过时。应该就是这个原因了。
解决办法:

openssl s_client -cipher @SECLEVEL=0:ALL -connect 124.71.233.xx:8883 -cert cert.pem -key key.pem -CAfile ../trusted-certs.pem -showcerts

要确认就是sha1的问题,只需要这样就可以

openssl s_client -cipher @SECLEVEL=0:SHA1 -connect 124.71.233.62:8883 -cert cert.pem -key key.pem -CAfile ../trusted-certs.pem -showcerts

mqtt在编译openssl的时候,使用DOPENSSL_TLS_SECURITY_LEVEL=0就可以了。

还有一个修改配置文件的方法,
修改/etc/ssl/openssl.cnf文件
在文件开头加上

openssl_conf = default_conf

在文件结尾加上

[ default_conf ]

ssl_conf = ssl_sect

[ssl_sect]

system_default = ssl_default_sect

[ssl_default_sect]
MinProtocol = TLSv1.2
CipherString = DEFAULT:@SECLEVEL=0

验证测试:

openssl s_client  -connect 124.71.233.62:8883 -cert cert.pem -key key.pem -CAfile ../trusted-certs.pem -showcerts

CONNECTED(00000003)
...
verify return:1
这个方法来源于:https://askubuntu.com/questions/1231799/certificate-error-after-upgrade-to-20-04
原文:

I found a solution, according to the accepted answer of this question:
Ubuntu 20.04 - how to set lower SSL security level?

In particular, the openSSL configuration file /etc/ssl/openssl.cnf
shall be modified in the following way.

At the beginning, add openssl_conf = default_conf

At the end, add

[ default_conf ]

ssl_conf = ssl_sect

[ssl_sect]

system_default = ssl_default_sect

[ssl_default_sect] MinProtocol = TLSv1.2 CipherString =
DEFAULT:@SECLEVEL=0 After this modification, the certificate is
recognized without security errors.

https://www.openssl.org/docs/man1.1.0/man3/SSL_CTX_set_security_level.html

WARNING at this time setting the security level higher than 1 for
general internet use is likely to cause considerable interoperability
issues and is not recommended. This is because the SHA1 algorithm is
very widely used in certificates and will be rejected at levels higher
than 1 because it only offers 80 bits of security.

The default security level can be configured when OpenSSL is compiled
by setting -DOPENSSL_TLS_SECURITY_LEVEL=level. If not set then 1 is
used.

https://github.com/drwetter/testssl.sh/issues/1433

OpenSSL 1.1.0 introduced the ability to specify a security level:
https://github.com/openssl/openssl/blob/master/doc/man3/SSL_CTX_set_security_level.pod.
By default the security level is set to 1 unless a compile-time option
is used to set the default a different value. The security level may
also be set by the command line, e.g.,

openssl s_client -cipher @SECLEVEL=0:ALL -connect 127.0.0.1:443 At the
moment, testssl.sh does not use the @SECLEVEL=n directive, but we may
want to look into using s_client_options() to add it in some
circumstances.

使用mosquitto订阅消息的时候,出现host name verification failed错误。

mosquitto_sub -L mqtts://124.71.233.xx:8883/ -t topic --cert cert.pem --key key.pem --cafile ../trusted-certs.pem -q 1 -d 

Client (null) sending CONNECT
Error: host name verification failed.
OpenSSL Error[0]: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed
Error: A TLS error occurred.

使用openssl s_client验证tls本身没有问题,问题应该出在mqtt的处理上面。

查看mosquitto 的源码。
在mosquitto-2.0.11/lib/tls_mosq.c中,看到如下实现。

if(mosq->tls_insecure == false
#ifndef WITH_BROKER
                        && mosq->port != 0 /* no hostname checking for unix sockets */
#endif
)
...
return preverify_ok;
}

直接设置mosq->tls_insecure为true就不进行这个判断了。
修改后如下:

mosquitto_sub -L mqtts://124.71.233.xx:8883/ -t topic --cert cert.pem --key key.pem --cafile ../trusted-certs.pem -q 1 -d --insecure

使用openssl为ssl证书增加“使用者备用名称(DNS)
主要修改在openssl.cnf

确保req下存在以下2行(默认第一行是有的,第2行被注释了)

[ req ]
distinguished_name = req_distinguished_name
req_extensions = v3_req

确保req_distinguished_name下没有 0.xxx 的标签,有的话把0.xxx的0. 去掉

[ req_distinguished_name ]
countryName              = Country Name (2 letter code)
countryName_default = CN
stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default = ShangHai
localityName              = Locality Name (eg, city)
localityName_default = ShangHai
organizationalUnitName             = Organizational Unit Name (eg, section)
organizationalUnitName_default = Domain Control Validated
commonName         = Internet Widgits Ltd
commonName_max = 64

新增最后一行内容 subjectAltName = @alt_names(前2行默认存在)

[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names

新增 alt_names,注意括号前后的空格,DNS.x 的数量可以自己加

[ alt_names ]
DNS.1 = abc.example.com
DNS.2 = dfe.example.org
DNS.3 = ex.abcexpale.net

Referenced from:https://blog.51cto.com/colinzhouyj/1566438