TLS (v1.2) 客户端证书只是有时需要。为什么?

TLS (v1.2) client certificate only sometimes required. Why?

我已经设置了一个 mosquitto MQTT 服务器并创建了所有内容来加密通信。证书是使用此脚本创建的 here。一切正常。证书通过 openssl verify -CAfile ca.crt cool-server.crt 检查为“正常”。

但是我不明白为什么在不同的客户端上会有不同。

代理在 Ubuntu 18 服务器上运行。此处配置:

root@cool-server:~# cat /etc/mosquitto/conf.d/default.conf 
allow_anonymous false
password_file /etc/mosquitto/passwd

listener 1883 localhost

listener 8883

cafile /etc/mosquitto/ca_certificates/ca.crt
certfile /etc/mosquitto/certs/cool-server.crt
keyfile /etc/mosquitto/certs/cool-server.key

require_certificate true
#require_certificate false # tried this too

tls_version tlsv1.2

root@cool-server:~# cat /etc/mosquitto/mosquitto.conf 
# Place your local configuration in /etc/mosquitto/conf.d/
#
# A full description of the configuration file is at
# /usr/share/doc/mosquitto/examples/mosquitto.conf.example

pid_file /var/run/mosquitto.pid

persistence true
persistence_location /var/lib/mosquitto/

log_type all
log_dest file /var/log/mosquitto/mosquitto.log

include_dir /etc/mosquitto/conf.d

我可以通过

连接到它

问题是:

1.为什么有的客户需要指纹证明,有的客户不需要?

据我所知,TLS/SSL 可以在服务器端仅使用证书保护连接,但我不确定。 Android 应用程序无需任何证书或指纹即可连接到我的代理,而 mosquitto_pub 仅适用于 cacert。即使我用 require_certificate false 配置代理,客户端仍然需要指定 cacert。 --insecure 没有解决这个问题。另一方面,我的ESP8266只需要一个短指纹。

2。我所有的连接(尤其是 Android 连接)都是 secure/encrypted 吗?

ESP8266/Arduino

const uint8_t mqttCertFingerprint[] = {0xA6, 0x4D, 0x9F, 0x43B, 0x80, 0xB7, 0xB2, 0x9A, 0x9D, 0xCB, 0xC9, 0xF7, 0xAA, 0xCC, 0x30, 0xEF, 0xF4, 0xFC, 0xD3, 0x31};
mqttClient_.setSecure(true);
mqttClient_.addServerFingerprint(mqttCertFingerprint);

Bash

mosquitto_pub -h cool-server.com -p 8883 -u user -P Password -t "topic/name" -m "hello" --cafile path/to/ca.crt

Android

       if (serverUri.contains("ssl")) {
        class TrustEveryoneManager implements X509TrustManager {
            public void checkClientTrusted(X509Certificate[] arg0, String arg1){}
            public void checkServerTrusted(X509Certificate[] arg0, String arg1){}
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        }

        SSLContext sslContext = SSLContext.getInstance("tls");
        sslContext.init(null, new TrustManager[]{new TrustEveryoneManager()}, new SecureRandom());

        mqttConnectOptions.setSocketFactory(sslContext.getSocketFactory());
    }

假设您没有使用自签名证书。

mosquitto_pub/sub 和 PubSubClient 库都需要 CA 证书,因为它们没有包含来自证书颁发机构的受信任证书列表的内置信任库。

在 Android 上有一个烘焙的 Trust Store。

在 Linux 上,您通常可以将 mosquitto 工具指向 /etc/ssl/certs/ 以使用随 OS.

一起提供的 Trust Store CA 证书

更新:

  1. 证书指纹足以验证代理证书,只要代理在客户端连接时提供完整的证书链。客户端可以检查代理证书是否由 CA 证书签名,以及 CA 证书指纹是否与提供的指纹匹配。

  2. 不,您 Android 客户端不安全。您已明确告诉 Android 信任代理提供的任何证书,这意味着任何人都可以 运行 中间人攻击您的 android 应用程序,而您永远无法分辨.