This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm whether you accept or reject these cookies being set.

MQTT Secure Websocket - FATAL Unknown CA
#1
Hi,

does anyone have an idea what could be the problem here;

The setup is an MQTT broker running vernemq, with self-signed certificates using TLS 1.2 (certs were generated using i think ACME or certbot against a Letsencrypt CA).
The point is ofcourse that a client can connect over TLS-insecure (only hostname verification, to which it connects) with the broker, login and send messages.

On another client, which is a raspberry pi (raspbian), this runs without problems and without extra clientside keys/certs from a python script but on the logic machine i cant get it working.
I tried with uploading the Letsencrypt CA and referencing it from the Lua script but i keep seeing an error in the broker logs;

8:55:09.835 [info] <0.631.0> TLS server: In state certify received CLIENT ALERT: Fatal - Unknown CA

Ive tried setting TLS to v1.1 but that didn't do anything either.

Relevant LogicMachine packages:
libmosquitto 1.6.3-1
luamosquitto 0.3-5
luasocket 2.0.2-35
libopenssl 1.0.2o-1


Logic Machine:

require('socket')
mclient:login_set('someuser', 'somepass')
mclient = require('mosquitto').new("id:someid", true)
mclient:tls_set('/data/ftp/ca.pem')
mclient:tls_insecure_set(true)


....

function mconnect()
    local fd
 
    log('DEBUG: 1st connection attempt')
    local ok, rc = mclient:connect(somedomainname, 8883, 60)
   
    fd = mclient:socket()

    if fd then
      mclientfd = fd
      log('DEBUG: succesfully connected')
    else
      log('Connection attempt failed')
    end
  end



SERVER:


listener.wss.cafile = /etc/vernemq/fullchain.pem
listener.wss.certfile = /etc/vernemq/cert.pem
listener.wss.keyfile = /etc/vernemq/privkey.pem
Reply
#2
You need to provide full certificate chain in a single file including root certificate (DST Root CA X3). It is not supplied by default because it usually can be found in system's ca-certificates storage. Since LM does not have any ca-certificates by default you need to have all certificates in a single file.
Reply
#3
(06.09.2019, 09:04)admin Wrote: You need to provide full certificate chain in a single file including root certificate (DST Root CA X3). It is not supplied by default because it usually can be found in system's ca-certificates storage. Since LM does not have any ca-certificates by default you need to have all certificates in a single file.

Hi admin, thank you for your reply, the error is gone but I now notice, using wireshark, the TLS handshake repeatedly succeeds on every step, the server decodes application data as being 'mqtt' but after the final step there's a connection reset every time....

Why would the connection get constantly reset?

See attached screenshot

Greetings,

Attached Files Image(s)
   
Reply
#4
Can you post complete script listing?
Reply
#5
(06.09.2019, 15:52)admin Wrote: Can you post complete script listing?

Hi, yes here it is;
Thank you

Code:
mqtt = require("mosquitto")
client = mqtt.new()
client:tls_set('/data/ftp/ca.pem', nil, '/data/ftp/client.pem', '/data/ftp/client.key')

client:tls_insecure_set(true)

client.ON_CONNECT = function()
log('connected')
value = grp.getvalue('0/3/4') or 0
client:publish("SOME/TOPIC/1", value, qos, retain)
value = grp.getvalue('0/3/5') or 0
client:publish("SOME/TOPIC/2", value, qos, retain)
client:disconnect()
end

broker = 'some.broker.domain'
client:login_set('someuser', 'somepass')
client:connect(broker,8883)
client:loop_forever()

netstat:

tcp        0      0 <broker_ip>:8883      <lua-client_ip>:38060    ESTABLISHED -
Reply
#6
You have disconnect call in connect handler. This example is meant for one way publish when value is changed without having a constantly open connection.
Reply
#7
(10.09.2019, 07:42)admin Wrote: You have disconnect call in connect handler. This example is meant for one way publish when value is changed without having a constantly open connection.

Yes, that is the purpose, it's a script that is run every minute!
sorry for lack of info
Reply
#8
..but this doesn't change the fact that the script wont connect to mqtt.

Do you see any other reason why this could be?
Reply
#9
Are you sure you need both login/password and client certificate?
Reply
#10
(12.09.2019, 15:00)admin Wrote: Are you sure you need both login/password and client certificate?

i think so, the login is for the mqtt broker and the certs are for the secure websockets (TLS)
I can connect to the broker using a webclient like this one: http://www.espert.io/mqtt/index.html 
I have to check the SSL box, provide login, hostname, port 8883 and it all works.
Reply
#11
Client certificates are only needed if you are using it for client authentication which seems like you don't. So you only need to specify server certificate but there must be the whole certificate chain in a single file including root certificate.

If you are using the latest library version then tls_insecure_set(true) should completely ignore server certificates.
You can find latest packages here:
http://dl.openrb.com/pkg/libmosquitto_1.6.3-1_imx6.ipk
http://dl.openrb.com/pkg/luamosquitto_0.3-4_imx6.ipk

Example chain for Let's Encrypt, includes Let's Encrypt Authority X3 and DST Root CA X3:
Code:
-----BEGIN CERTIFICATE-----
YOUR SERVER CERT HERE
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
-----END CERTIFICATE-----
Reply
#12
(13.09.2019, 09:25)admin Wrote: Client certificates are only needed if you are using it for client authentication which seems like you don't. So you only need to specify server certificate but there must be the whole certificate chain in a single file including root certificate.

If you are using the latest library version then tls_insecure_set(true) should completely ignore server certificates.
You can find latest packages here:
http://dl.openrb.com/pkg/libmosquitto_1.6.3-1_imx6.ipk
http://dl.openrb.com/pkg/luamosquitto_0.3-4_imx6.ipk

Hi,

the packages were up to date and I had tried as you proposed. Now tried it again adding our cert.pem to your snippet but still the connection gets instantly reset after client hello.
Reply
#13
Have you modified your script to only pass one parameter (server cert) to tls_set?
Reply
#14
(13.09.2019, 15:37)admin Wrote: Have you modified your script to only pass one parameter (server cert) to tls_set?

Hi,

yes, like this:

mclient = require('mosquitto').new()
mclient:tls_set('/data/ftp/final.pem')
mclient:tls_insecure_set(true)
mclient:login_set('user','pass')


final.pem is the chain you provided with the cert.pem (server certificate)

server supports following ciphers:


| ssl-enum-ciphers:
|  TLSv1.2:
|    ciphers:
|      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (brainpoolP256r1) - A
|      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (brainpoolP256r1) - A
|      TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (brainpoolP256r1) - A
|      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (brainpoolP256r1) - A
|      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (brainpoolP256r1) - A
|      TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (brainpoolP256r1) - A
|      TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|      TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
|      TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
|      TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|      TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
|      TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
|    compressors:
|      NULL
|    cipher preference: client
|_  least strength: A
Reply
#15
tls_insecure_set(true) has lowest priority. If you want to try insecure mode then do not set certificates with tls_set at all.
Reply
#16
Hi, do you also know how to conenct to AWS IoT ?
AWS provides:
- the root CA :AmazonRootCA1.pem and AmazonRootCA3.pem
- the client cert : 0a1b2c3d4e-certificate.pem.crt
- the client private key: 0a1b2c3d4e-private.pem.key
- the client public key: 0a1b2c3d4e-public.pem.key

i would assume below is the correct way to connect, i left out login_set because auth is only certificate based

broker = 'random-ats.iot.eu-central-1.amazonaws.com'
client:tls_set('/data/ftp/AmazonRootCA1.pem', nil, '/data/ftp/0a1b2c3d4e-certificate.pem.crt', '/data/ftp/0a1b2c3d4e-private.pem.key')
local ok, rc = client:connect(broker,8883)
assert(ok)

I get this error:
AWS IoT Test 15.06.2020 14:53:44
Resident script:15: Invalid function arguments provided.
stack traceback:
[C]: in function 'tls_set'

What am I doing wrong ?
Reply
#17
tls_set can fail if any of the supplied files cannot be read.
Check that the script can access them before calling tls_set:
Code:
log(
  io.exists('/data/ftp/AmazonRootCA1.pem'),
  io.exists('/data/ftp/0a1b2c3d4e-certificate.pem.crt'),
  io.exists('/data/ftp/0a1b2c3d4e-private.pem.key')
)
Reply
#18
yes, it was indeed a problem with the path
now the assert is true and no errors but it never executes the ON_CONNECT routine
script is executed every 60s but i never see 'connected' in the logging

client.ON_CONNECT = function()
log('connected')
client:publish("TEST/test1", 1, 0, 0)
log('disconecting...')
client:disconnect()
end
Reply
#19
Add ON_LOG callback to get more info on what's going on.
Code:
client.ON_LOG = log

Also make sure that your LM has valid gateway and DNS settings.
Reply
#20
EDIT: after googling i found out the error is related to CA, i changed to CA1.pem and now i get

AWS IoT Test 15.06.2020 16:37:44
* arg: 1
  * number: 16
* arg: 2
  * string: Client TEST sending CONNECT

but it doesnt go into the loop




OLD POST:

network config is ok. i was able to ping the host from the network utilities

with the ON_LOG i see:

AWS IoT Test 15.06.2020 16:11:39
* arg: 1
  * number: 8
* arg: 2
  * string: OpenSSL Error: error:14090086:lib(20):func(144):reason(134)

just for clarity, the full script:

Code:
  require('socket')
  require('ssl')
  mqtt = require('mosquitto')
  client = mqtt.new('TEST')
  log('client created')
--client:tls_insecure_set(true)

cafile = '/data/ftp/AmazonRootCA3.pem'
certfile = '/data/ftp/a0b1c2e4-certificate.pem.crt'
keyfile = '/data/ftp/a0b1c2e4-private.pem.key'
--cafile = '/data/ftp/AmazonRootCA3.crt'
--certfile = '/data/ftp/a0b1c2e4-certificate.crt'
--keyfile = '/data/ftp/a0b1c2e4-private.key'

log(
  io.exists(cafile),
  io.exists(certfile),
  io.exists(keyfile)
)

  broker = 'random-ats.iot.eu-central-1.amazonaws.com'
  client:tls_set(cafile, nil, certfile, keyfile)
  local ok, rc = client:connect(broker,8883)
  assert(ok)
  log(ok)
  client.ON_LOG = log
  client.ON_CONNECT = function()


    log('connected')
    client:publish("TEST/test1", 1, 0, 0)
    log('disconecting...')
    client:disconnect()
end
log('loop...')
  client:loop_forever()
log('end...')
Reply


Forum Jump: