AtherEnergy / rumqtt

Pure rust mqtt cilent
The Unlicense
203 stars 72 forks source link

TLS example doesn't work #181

Open GopherJ opened 4 years ago

GopherJ commented 4 years ago

Hello,

The tls example doesn't work for me, I tried the following code:

use rumqtt::{MqttClient, MqttOptions, QoS};
use std::{thread, time::Duration};

fn main() {
    pretty_env_logger::init();

    let client_id = "tls-test".to_owned();
    let ca = include_bytes!("path/to/cert.pem").to_vec();
    let client_cert = include_bytes!("path/to/client-cert.pem").to_vec();
    let client_key = include_bytes!("path/to/client-key.pem").to_vec();

    let mqtt_options = MqttOptions::new(client_id, "xxxxxxx", 8883)
        .set_ca(ca)
        .set_client_auth(client_cert, client_key)
        .set_keep_alive(10);

    MqttClient::start(mqtt_options);
    // let topic = "hello/world";

    // thread::spawn(move || {
    //     for i in 0..100 {
    //         let payload = format!("publish {}", i);
    //         thread::sleep(Duration::from_secs(1));
    //         if let Err(err) = mqtt_client.publish(topic.clone(), QoS::AtLeastOnce, false, payload) {
    //             println!("{:?}", err);
    //         }
    //     }
    // });

    // for notification in notifications {
    //     println!("{:?}", notification)
    // }
}

I got the following message while executing RUST_BACKTRACE=1 cargo run --example tls, is there any workaround or am I doing something wrong?

thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: ()', src/libcore/result.rs:1165:5
stack backtrace:
   0: backtrace::backtrace::libunwind::trace
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/libunwind.rs:88
   1: backtrace::backtrace::trace_unsynchronized
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/mod.rs:66
   2: std::sys_common::backtrace::_print_fmt
             at src/libstd/sys_common/backtrace.rs:77
   3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
             at src/libstd/sys_common/backtrace.rs:61
   4: core::fmt::write
             at src/libcore/fmt/mod.rs:1030
   5: std::io::Write::write_fmt
             at src/libstd/io/mod.rs:1412
   6: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:65
   7: std::sys_common::backtrace::print
             at src/libstd/sys_common/backtrace.rs:50
   8: std::panicking::default_hook::{{closure}}
             at src/libstd/panicking.rs:188
   9: std::panicking::default_hook
             at src/libstd/panicking.rs:205
  10: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:464
  11: std::panicking::continue_panic_fmt
             at src/libstd/panicking.rs:373
  12: rust_begin_unwind
             at src/libstd/panicking.rs:302
  13: core::panicking::panic_fmt
             at src/libcore/panicking.rs:141
  14: core::result::unwrap_failed
             at src/libcore/result.rs:1165
  15: core::result::Result<T,E>::unwrap
             at /rustc/4f03f4a989d1c8346c19dfb417a77c09b34408b8/src/libcore/result.rs:933
  16: rumqtt::client::network::stream::NetworkStreamBuilder::connect
             at src/client/network.rs:208
  17: rumqtt::client::connection::Connection::tcp_connect_future
             at src/client/connection.rs:315
  18: rumqtt::client::connection::Connection::mqtt_connect
             at src/client/connection.rs:321
  19: rumqtt::client::connection::Connection::mqtt_eventloop
             at src/client/connection.rs:91
  20: rumqtt::client::connection::Connection::run::{{closure}}
             at src/client/connection.rs:60
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
GopherJ commented 4 years ago

@tekjar Hello, could you help on this?

tekjar commented 4 years ago

@GopherJ Are you using ip address by any chance?

https://github.com/AtherEnergy/rumqtt/blob/master/src/client/network.rs#L208

Rumqtt doesn't support direct ip addresses on tls. You need to provide a dns

GopherJ commented 4 years ago

Hello, I still get error message:

 ERROR rumqtt::client::connection > Connection error = Error(Inner(Io(Custom { kind: InvalidData, error: WebPKIError(CertNotValidForName) })))

Could you help me on this? we would like to use rumqtt for all the projects but it seems there are still some problems.

GopherJ commented 4 years ago

@tekjar any ideas? Thanks for your help!

tekjar commented 4 years ago

Probably your certificate doesn't have correct SAN? It's necessary for rustls

GopherJ commented 4 years ago

Hello @tekjar , yes probably, any idea how to check it? I did some researches but I still don't know how to check it.

tekjar commented 4 years ago

@GopherJ

https://stackoverflow.com/questions/13127352/how-to-check-subject-alternative-names-for-a-ssl-tls-certificate

https://www.geocerts.com/certificate-decoder

Try these

GopherJ commented 4 years ago

Hello @tekjar , sadly that it may be caused by this issue, but I cannot change the root certificate.

In this case, I also would like to just test rumqtt works well with tls, but while testing, it seems that I get the same error:

 ERROR rumqtt::client::connection > Connection error = Error(Inner(Io(Custom { kind: InvalidData, error: WebPKIError(CertExpired) })))
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Io(Custom { kind: InvalidData, error: WebPKIError(CertExpired) })', src/libcore/result.rs:1165:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

what I did:

cd tlsfiles && /usr/sbin/mosquitto -c mosquitto.conf
cd ../ && cargo run --example tls

am I doing something wrong? or it's just because the test certificate is expired?

GopherJ commented 4 years ago

I wrote a script which generates SAN certificates, but still I get errors...........................:)

#!/bin/bash

set -e
set -u

HOST=example.com
SUBJ_ROOT="/C=FR/ST=Paris/O=EMQ/CN=Root"
SUBJ_CLIENT="/C=FR/ST=Paris/O=EMQ/CN=Client"
SUBJ_SERVER="/C=FR/ST=Paris/O=EMQ/CN=Server"
DAYS=3650

openssl genrsa -out root-ca.key 2048

openssl req \
  -x509 \
  -nodes \
  -new \
  -key root-ca.key \
  -out root-cacert.pem \
  -subj $SUBJ_ROOT \
  -sha256 \
  -days $DAYS

(cat /etc/ssl/openssl.cnf; printf "[SAN]\nsubjectAltName=DNS:$HOST") > openssl.cnf

openssl genrsa -out client.key 2048

openssl req \
  -new \
  -key client.key \
  -out client-cert.csr \
  -subj $SUBJ_CLIENT \
  -reqexts SAN \
  -extensions SAN \
  -config openssl.cnf

openssl x509 \
  -req \
  -in client-cert.csr \
  -out client-cert.pem \
  -CA root-cacert.pem \
  -CAkey root-ca.key \
  -CAcreateserial \
  -CAserial $HOST-CA.serial \
  -extensions SAN \
  -extfile openssl.cnf \
  -sha256 \
  -days $DAYS

openssl req \
  -new \
  -key server.key \
  -out server-cert.csr\
  -subj $SUBJ_SERVER \
  -reqexts SAN \
  -extensions SAN \
  -config openssl.cnf

openssl x509 \
  -req \
  -in server-cert.csr \
  -out server-cert.pem \
  -CA root-cacert.pem \
  -CAkey root-ca.key \
  -CAcreateserial \
  -CAserial $HOST-CA.serial \
  -extensions SAN \
  -extfile openssl.cnf \
  -sha256 \
  -days $DAYS
ERROR rumqtt::client::connection > Connection error = Error(Inner(Io(Custom { kind: InvalidData, error: WebPKIError(CertNotValidForName) })))
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Io(Custom { kind: InvalidData, error: WebPKIError(CertNotValidForName) })', src/libcore/result.rs:1165:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
tekjar commented 4 years ago

Error in your previous message says Certificate Expired. Did you check into that? I created these some time back to automate this

https://github.com/AtherEnergy/rumqtt/tree/master/utils/certgenerator

This might probably help. I might not be able to dig deep into the problem as I'm in a time crunch at the moment and I'm not working on this repo anymore.

But I might be able to help in a week as I'm creating a new broker and I have to verify the same at that time. Alternately I can give you access to my private repo if you want to test the new client with TLS. But it's in very early stages

GopherJ commented 4 years ago

OK I used your script and now I get new error - -:

WebPKIError(UnknownIssuer)
GopherJ commented 4 years ago
 ERROR rumqtt::client::connection > Connection error = Error(Inner(Io(Custom { kind: InvalidData, error: WebPKIError(UnknownIssuer) })))
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Io(Custom { kind: InvalidData, error: WebPKIError(UnknownIssuer) })', src/libcore/result.rs:1165:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

trace:

 ERROR rumqtt::client::connection > Connection error = Error(Inner(Io(Custom { kind: InvalidData, error: WebPKIError(UnknownIssuer) })))
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Io(Custom { kind: InvalidData, error: WebPKIError(UnknownIssuer) })', src/libcore/result.rs:1165:5
stack backtrace:
   0: backtrace::backtrace::libunwind::trace
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.37/src/backtrace/libunwind.rs:88
   1: backtrace::backtrace::trace_unsynchronized
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.37/src/backtrace/mod.rs:66
   2: std::sys_common::backtrace::_print_fmt
             at src/libstd/sys_common/backtrace.rs:76
   3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
             at src/libstd/sys_common/backtrace.rs:60
   4: core::fmt::write
             at src/libcore/fmt/mod.rs:1030
   5: std::io::Write::write_fmt
             at src/libstd/io/mod.rs:1412
   6: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:64
   7: std::sys_common::backtrace::print
             at src/libstd/sys_common/backtrace.rs:49
   8: std::panicking::default_hook::{{closure}}
             at src/libstd/panicking.rs:196
   9: std::panicking::default_hook
             at src/libstd/panicking.rs:210
  10: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:473
  11: std::panicking::continue_panic_fmt
             at src/libstd/panicking.rs:380
  12: rust_begin_unwind
             at src/libstd/panicking.rs:307
  13: core::panicking::panic_fmt
             at src/libcore/panicking.rs:85
  14: core::result::unwrap_failed
             at src/libcore/result.rs:1165
  15: core::result::Result<T,E>::unwrap
             at /rustc/4560ea788cb760f0a34127156c78e2552949f734/src/libcore/result.rs:933
  16: tls::main
             at examples/tls.rs:17
  17: std::rt::lang_start::{{closure}}
             at /rustc/4560ea788cb760f0a34127156c78e2552949f734/src/libstd/rt.rs:64
  18: std::rt::lang_start_internal::{{closure}}
             at src/libstd/rt.rs:49
  19: std::panicking::try::do_call
             at src/libstd/panicking.rs:292
  20: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:80
  21: std::panicking::try
             at src/libstd/panicking.rs:271
  22: std::panic::catch_unwind
             at src/libstd/panic.rs:394
  23: std::rt::lang_start_internal
             at src/libstd/rt.rs:48
  24: std::rt::lang_start
             at /rustc/4560ea788cb760f0a34127156c78e2552949f734/src/libstd/rt.rs:64
  25: main
  26: __libc_start_main
  27: _start
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
GopherJ commented 4 years ago

is there a workaround @tekjar , I just would like to make it works...

tekjar commented 4 years ago

@GopherJ I just verified both your code and the example. Both of them work for me

I suspect you are not using correct ca which is used to sign the server certificate. It's ca-chain.cert.pem in case you are using certgenerator script in utils.

GopherJ commented 4 years ago

Hello @tekjar , could you tell me what shall I use?

out
├── client
│   ├── crl
│   ├── csr
│   │   └── client.csr.pem
│   ├── private
│   │   └── client.key.pem
│   └── tlsfiles
│       └── client.cert.pem
├── intermediate
│   ├── crl
│   ├── crlnumber
│   ├── csr
│   │   └── intermediate.csr.pem
│   ├── index.txt
│   ├── index.txt.attr
│   ├── index.txt.attr.old
│   ├── index.txt.old
│   ├── newcerts
│   │   ├── 1000.pem
│   │   └── 1001.pem
│   ├── private
│   │   └── intermediate.key.pem
│   ├── serial
│   ├── serial.old
│   └── tlsfiles
│       ├── ca-chain.cert.pem
│       └── intermediate.cert.pem
├── root
│   ├── crl
│   ├── index.txt
│   ├── index.txt.attr
│   ├── index.txt.old
│   ├── newcerts
│   │   └── 1000.pem
│   ├── private
│   │   └── ca.key.pem
│   ├── serial
│   ├── serial.old
│   └── tlsfiles
│       └── ca.cert.pem
└── server
    ├── crl
    ├── csr
    │   └── server.csr.pem
    ├── private
    │   └── server.key.pem
    └── tlsfiles
        └── server.cert.pem

I don't think I made a mistake, but if yours can work then maybe I did something different from you

tekjar commented 4 years ago

https://discord.gg/ZQw8Y3

Please join that group. We'll resolve this there

GopherJ commented 4 years ago

hello @tekjar , could you send a new invitation, I cannot join for some strange reasons, I'll try now.

tekjar commented 4 years ago

@GopherJ https://discord.gg/afS2vC

GopherJ commented 4 years ago

thanks @tekjar