Hive VS Paho,Android 客户端。蚊子经纪人的 SSL 问题

问题描述 投票:0回答:1

我在通过 SSL 连接到我的 mosquitto 代理时遇到问题。我已经正确配置了代理,因为它使用 lwIP mqtt 客户端服务可以很好地连接到我的嵌入式设备。可悲的是,我不能在我的安卓设备上使用相同的代码。

我开始钻进兔子洞……

调查安卓应用的潜在客户; Paho 客户端似乎是合理的应用程序软件,因为它是 eclipse 套件的一部分;蚊子经纪人也是如此。我在 paho 申请上花了很多时间,但我遇到了无法克服的障碍;回购协议只是没有与新的 androidX 平台保持同步,客户端会自行断开连接,我会获得适当的认证和连接;客户端将连接到代理(是!)但随后 Android 将断开连接并吐出以下错误;

com.example.pahoclient: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.

我调查过这个;事实证明这并不容易解决,因为库的源代码不容易修改。 (至少不是像我这样缺乏 Java 经验的人。)在放弃之前,我尝试了很多“解决方案”。

然后我决定尝试 android 的 HiveMQ 客户端。虽然这看起来更加最新和活跃,但我无法让我的经纪人收到 SSL 证书。它是相同的证书文件,但使用的功能略有修改。我将在这里概述这两个代码,从成功的客户端 + 代理连接开始。

我的mosquitto broker设置如下;

listener 8883
#listener 1883
cafile certs/ca.crt
certfile certs/server.crt
keyfile certs/server.key
protocol mqtt
tls_version tlsv1.2


require_certificate false
allow_anonymous false
password_file certs/password
max_keepalive 5000

我只在客户端加载 CA 证书。硬编码如下;

package com.example.pahoclient

//import info.mqtt.android.service.MqttAndroidClient;
import android.app.Notification
import android.content.Context
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import org.eclipse.paho.android.service.MqttAndroidClient
import org.eclipse.paho.android.service.MqttService
import org.eclipse.paho.client.mqttv3.*
import java.security.KeyStore
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManagerFactory


class MQTTClient(context: Context,
                 serverURI: String = "ssl://example.com:8883",
                 clientID: String = "nonNull") {
    companion object {
        private const val TAG = "MQTTClient"
        private val certString: String = "-----BEGIN CERTIFICATE-----\n" +
                ...
                "rtVtZNE+luuMaDyGQYkNt3d1S3TWFVgd\n" +
                "-----END CERTIFICATE-----\n"

        private fun createSSLSocketFactory(): SSLSocketFactory? {
            val cf = CertificateFactory.getInstance("X.509")
            val cert = cf.generateCertificate(certString.byteInputStream()) as X509Certificate

            val ks = KeyStore.getInstance(KeyStore.getDefaultType())
            ks.load(null, null)
            ks.setCertificateEntry("ca", cert)

            val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
            tmf.init(ks)

            val sslContext = SSLContext.getInstance("TLS")
            sslContext.init(null, tmf.trustManagers, null)
            return sslContext.socketFactory
        }
    }

    private var mqttClient = MqttAndroidClient(context, serverURI, clientID)

    fun connect(username:   String               = "...",
                password:   String               = "...",
                cbConnect:  IMqttActionListener  = defaultCbConnect,
                cbClient:   MqttCallback         = defaultCbClient

    ) {

        mqttClient.setCallback(cbClient)

        val options = MqttConnectOptions()
        options.userName = username
        options.password = password.toCharArray()
        options.isCleanSession = false
        options.socketFactory = createSSLSocketFactory()
        options.keepAliveInterval = 20


        try {
            mqttClient.connect(options, null, cbConnect)
        } catch (e: MqttException) {
            e.printStackTrace()
        }
    }

没有使用客户端证书。 这对我的嵌入式设备+lwIP 来说已经足够了;但是,在尝试使用 android 设备时,我会从 mosquitto 代理获得以下输出;

1676858808: mosquitto version 2.0.15 running
1676858841: New connection from 207.216.33.43:54808 on port 8883.
<Client disconnected>...

这伴随着 FLAG_MUTABLE... 我的 android 控制台中的错误..

com.example.pahoclient: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.

这告诉我证书已正确解析和转发,但是当我尝试对 HiveMQ 客户端使用类似的设置时,证书无法通过,我在控制台中得到以下输出;

1676863126: New connection from 207.216.33.43:54922 on port 8883.
1676863126: OpenSSL Error[0]: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown
1676863126: Client <unknown> disconnected: Protocol error.

这里是HiveMQ代码;


package com.example.pahoclient


import android.R.attr.password
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.hivemq.client.mqtt.MqttClient
import com.hivemq.client.mqtt.mqtt3.Mqtt3AsyncClient
import java.security.KeyStore
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
import javax.net.ssl.KeyManagerFactory
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManagerFactory


private val certString: String = "-----BEGIN CERTIFICATE-----\n"+
...
"-----END CERTIFICATE-----"

class MainActivity : AppCompatActivity() {

    private var client: Mqtt3AsyncClient? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

/**Call the socket factory**/

        //CA stuff
        val cf = CertificateFactory.getInstance("X.509")
        val cert = cf.generateCertificate(certString.byteInputStream()) as X509Certificate

        val ks = KeyStore.getInstance(KeyStore.getDefaultType())
        ks.load(null, null)
        ks.setCertificateEntry("ca", cert)

        val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
        tmf.init(ks)

        client = MqttClient.builder()
            .useMqttVersion3()
            .identifier("my-mqtt-client-id")
            .serverHost("******.com")
            .serverPort(8883)
            .sslConfig()
                .keyManagerFactory(null)
                .trustManagerFactory(tmf)
                 .applySslConfig()
            .buildAsync()

        client?.connectWith()
            ?.simpleAuth()
            ?.username("******")
            ?.password("*****".toByteArray())
            ?.applySimpleAuth()
            ?.send()
            ?.whenComplete { connAck, throwable ->
                if (throwable != null) {
                    // handle failure
                } else {
                    // setup subscribes or start publishing
                }
            }
    }

}

为什么我的证书会因一种实施而不是另一种实施而失败? HiveMQ 是否需要客户端证书?

paho 和 hiveMQ 都使用 SSlSocketFactory,但 HiveMQ 对 KeyManagerFactory 有要求,我已将其设置为 null。

我还需要提供客户证书吗?我确实创建了它们,但不确定我将如何实施它。

有什么建议吗?

我尝试了 2 个不同的客户端,HiveMQ 和 Paho。 我尝试将 HiveMQ 连接到已加载的 CA 证书以及已加载的客户端证书。

android mqtt mosquitto paho hivemq
1个回答
0
投票

@terminalObserver, 如何连接到 HiveMQ 代理取决于其配置。如果您使用的是 HiveMQ 云代理(您可以在 http://cloud.hivemq.com 免费注册),那么要连接,您需要将 CAfile 添加到客户端的信任库(以建立 SSL 连接)和提供 MQTT 凭据用户名和密码(以进行身份验证)。 如果您在本地托管 HiveMQ 代理,那么您连接的方式实际上取决于代理的配置。 我鼓励您在 HiveMQ 社区论坛 中提问,并提供您的代理配置详细信息,例如

/opt/hivemq/conf/config.xml
文件。

致以诚挚的问候, 来自 HiveMQ 团队的 Dasha

© www.soinside.com 2019 - 2024. All rights reserved.