MQTT Binding and SSL

@rlkoshak Rich - You’ve swayed me! Simpler is always better.

@vzorglub Vincent - I don’t think I need “your” setup for what I’m trying to do since I’m trying to bridge to an external server and set up trust with an external entity.

I set up a DDNS assigning a domain name to my WAN IP. The setup also runs a job that updates the DDNS if my IP changes.

I have my port forwarding on my router to forward traffic coming in on 8883 to be forwarded to my local server port 8883.

I used Certbot (Let’s Encrypt) to generate the certificates for my domain (i.e., self-signed since I’m the CA for my server). Certbot generates four certificate (PEM) files:

  1. privkey.pem
  2. fullchain.pem contains all certificates, including server certificate (aka leaf certificate or end-entity certificate). The CA certificate is in the content of fullchain.pem, specifically, the first certificate in the file. (PEM files are editable and contain public keys as certificates between BEGIN/END lines(these lines belong to the PEM file).
  3. cert.pem contains the server certificate by itself
  4. chain.pem contains the additional intermediate certificate or certificates that web browsers will need in order to validate the server certificate.

Certbot cannot create client certificates (yet)… but OwnTracks doesn’t actually require this.

Question: When I generate the certificates, does the domain get “incorporated” into the certificates? If I generate certificates for my DDNS domain, but I really am having my local server authenticate, do these certificates “work” on my localhost broker?

I followed Vincent’s procedure and created the keystore and truststore. Question: My Certbot certificates (i.e., the one I used to generate the truststore) expires in 90 days. I set up the Certbot job to automatically renew the certificates. Will I need to recreate the truststore when my certificates refresh? I can easily do that by putting the truststore command in my Certbot post hook script. I just need to know if that is required.

Disclaimer - I am completely baffled by this entire certificate mechanism. I’ve read and read… but my eyes glaze over. I just need a good tutorial with good visuals and diagrams. Haven’t found that succinct tutorial!

I added these lines to my mqtt.cfg file:
openhab_sslbroker.clientId=“openhab2”
openhab_sslbroker.user=“openhabian”
openhab_sslbroker.pwd=“PASSWORD”
openhab_sslbroker.url=“ssl://localhost:8883”

In the openHAB log viewer I get ‘Connection refused’:

2018-04-29 02:27:35.929 [INFO ] [t.mqtt.internal.MqttBrokerConnection] - Starting MQTT broker connection 'openhab_sslbroker'
2018-04-29 02:27:37.101 [ERROR] [penhab.io.transport.mqtt.MqttService] - Error starting broker connection
org.eclipse.paho.client.mqttv3.MqttException: Unable to connect to server
	at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:79) [224:org.openhab.io.transport.mqtt:1.11.0]
	at org.eclipse.paho.client.mqttv3.internal.SSLNetworkModule.start(SSLNetworkModule.java:86) [224:org.openhab.io.transport.mqtt:1.11.0]
	at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:650) [224:org.openhab.io.transport.mqtt:1.11.0]
	at java.lang.Thread.run(Thread.java:748) [?:?]
Caused by: java.net.ConnectException: Connection refused (Connection refused)
	at java.net.PlainSocketImpl.socketConnect(Native Method) ~[?:?]
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[?:?]
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[?:?]
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[?:?]
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[?:?]
	at java.net.Socket.connect(Socket.java:589) ~[?:?]
	at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:673) ~[?:?]
	at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:70) ~[?:?]
	... 3 more

I tried a mqtt client to confirm. It asked so I chose TLSv1. Is that right? Same result - ‘Connection refused’. It’s asking me to the user credentials - which I’ve done. I highly suspect I’ve screwed up the certificate stuff.

2018-04-29 02:34:38,133  INFO --- MqttFX ClientModel             : MqttClient with ID MQTT_FX_Client assigned.
2018-04-29 02:34:40,240 ERROR --- MqttFX ClientModel             : Error when connecting
org.eclipse.paho.client.mqttv3.MqttException: Unable to connect to server
	at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:94) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	at org.eclipse.paho.client.mqttv3.internal.SSLNetworkModule.start(SSLNetworkModule.java:103) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:701) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[?:1.8.0_162]
	at java.util.concurrent.FutureTask.run(Unknown Source) ~[?:1.8.0_162]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(Unknown Source) ~[?:1.8.0_162]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[?:1.8.0_162]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:1.8.0_162]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:1.8.0_162]
	at java.lang.Thread.run(Unknown Source) [?:1.8.0_162]
Caused by: java.net.ConnectException: Connection refused: connect
	at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) ~[?:1.8.0_162]
	at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source) ~[?:1.8.0_162]
	at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source) ~[?:1.8.0_162]
	at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source) ~[?:1.8.0_162]
	at java.net.AbstractPlainSocketImpl.connect(Unknown Source) ~[?:1.8.0_162]
	at java.net.PlainSocketImpl.connect(Unknown Source) ~[?:1.8.0_162]
	at java.net.SocksSocketImpl.connect(Unknown Source) ~[?:1.8.0_162]
	at java.net.Socket.connect(Unknown Source) ~[?:1.8.0_162]
	at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:80) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	... 9 more
2018-04-29 02:34:40,242 ERROR --- MqttFX ClientModel             : Please verify your Settings (e.g. Broker Address, Broker Port & Client ID) and the user credentials!
org.eclipse.paho.client.mqttv3.MqttException: Unable to connect to server
	at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:94) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	at org.eclipse.paho.client.mqttv3.internal.SSLNetworkModule.start(SSLNetworkModule.java:103) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:701) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[?:1.8.0_162]
	at java.util.concurrent.FutureTask.run(Unknown Source) ~[?:1.8.0_162]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(Unknown Source) ~[?:1.8.0_162]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[?:1.8.0_162]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:1.8.0_162]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:1.8.0_162]
	at java.lang.Thread.run(Unknown Source) [?:1.8.0_162]
Caused by: java.net.ConnectException: Connection refused: connect
	at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) ~[?:1.8.0_162]
	at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source) ~[?:1.8.0_162]
	at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source) ~[?:1.8.0_162]
	at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source) ~[?:1.8.0_162]
	at java.net.AbstractPlainSocketImpl.connect(Unknown Source) ~[?:1.8.0_162]
	at java.net.PlainSocketImpl.connect(Unknown Source) ~[?:1.8.0_162]
	at java.net.SocksSocketImpl.connect(Unknown Source) ~[?:1.8.0_162]
	at java.net.Socket.connect(Unknown Source) ~[?:1.8.0_162]
	at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:80) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	... 9 more
2018-04-29 02:34:40,246  INFO --- ScriptsController              : Clear console.
2018-04-29 02:34:40,247 ERROR --- BrokerConnectService           : Unable to connect to server

Help!

Mike

The certificate validates that the host you are talking to is the host that should be associated with a given domain name. So even while on your LAN, you must access the server through the DynDNS name or else the cert will be treated as invalid.

Put another way, the cert is for your DynDNS name, not localhost.

Yes, I’m pretty sure you do.

See above. The purpose of the cert is to verify that the machine at a given domain name is who it says it is. Therefore the cert is all about the domain name. You got a cert for some DynDNS domain name but you are accessing it using localhost.

At a super high level the way a cert works is:

  • a client prooves to a certificate authority (LetsEncrypt in this case) that they own a given domain name
  • the CA signs a certificate and gives it to you. The certificate says “I, LetsEncrypt, have proven to my satisfaction that meingraham owns mydomain.dyndns.net.”
  • now you associate that certificate with your server running at my domain.dyndns.net
  • when a client connects over SSL/TLS, the server provides the certificate to the client.
  • the client checks whether the cert was signed by a trusted CA (anyone can create a CA)
  • of it was then the client checks that the certs is for the domain name it is connecting to. This is whether it to failing for you because the cert is for mydomain.dyndns.net, not localhost.

Basically, a cert is a way to establish that you are not talk to an imposter that relies on the domain name and a trusted third party (the CA).

TLS2 would be better if it is supported.

@rlkoshak Rich,

Thanks for hanging with me! And thanks for the certificates for dummies summary. Lord knows I fit the bill!

OK, I’d tried it with openhab_sslbroker.url=“ssl://my_domain:8883” with no difference in outcome. That’s why I tried localhost. So, I did create the certificates using my domain. So it looks like we’re all good there once I update my mqtt.cfg to use my domain name instead of localhost.

I can easily refreshe the truststore when the time comes.

The only thing I can think of is that perhaps I haven’t got the right certificates in the right places. I suppose there are the server certificates (which I’m thinking have to go somewhere in the mosquitto directory tree (/etc/mosquitto/) under either certs or ca_certificates. Which certificate and which folder? Then there’s the certificate for the openHAB client. which and where?

Thanks.

Mike

P.S. I’m trying to get this to establish a successful connection. Then I’ll tackle firewall rules and ACLs. So, I’m not done with this thread even when I get this SSL stuff working :wink:

I have relied on this guy before:

http://www.steves-internet-guide.com/mosquitto-tls/

It doesn’t matter where you put them but you have to configure the listen to use them. You provide the path to the CA file and cert file in the listener config.

That is what Vincent’s original posting shows. You need to added it to the trust store. But I’m not 100% positive that will work. There may not be a way to user a client cert with openHAB.

@rlkoshak @vzorglub

I’m just chasing my tail… I’ve read what feels like EVERY post on the topic of mosquitto and SSL and openhab. I had already stumbled on Steve’s Internet Guide. But reading it again, some things now make a bit more sense than earlier times. Unfortunately, I’m still no further along getting this to function.

I’ve started over with a clean slate. Here’s what I’m doing:

I subscribed to a DDNS and defined a domain name to point to the IP address assigned to me currently by my ISP. To ensure that the domain remains sync, the setup includes a 5 minute cron job that updates the DDNS should my IP address change. For the sake of this e-mail, let’s say that my domain name is ‘MY_DOMAIN.ORG’.

$ sudo bash

# certbot certonly --standalone --standalone-supported-challenges http-01 -d' MY_DOMAIN.ORG

Certbot deposits the certificates in /etc/letsencrypt/live/MY_DOMAIN.ORG

Since these certificates expire after 90 days, I have a daily cron job to check if the certificates need to be renewed. If so, the certificates are regenerated. If new certificates are generated, it regenerates the truststore and then restarts mosquitto.

Certificate files are root:root 644

Vincent - I tweaked your procedure that generates the keystore and truststore to name the files per my naming conventions and also to use PKCS12 format stores (as recommended by the keytool utility) instead of JKS.

# keytool -genkeypair -alias my_openhab -keyalg RSA -storetype PKCS12 -keystore /etc/OPENHAB.keystore

# keytool -import -alias my_openhab -file /etc/letsencrypt/live/MY_DOMAIN.ORG/fullchain.pem -storetype PKCS12 -keystore /etc/OPENHAB.truststore

Appended to JAVA_OPTS section

-Dcom.ibm.ssl.trustManager=SunX509
-Dcom.ibm.ssl.keyManager=SunX509
-Dcom.ibm.ssl.contextProvider=SunJSSE
-Dcom.ibm.ssl.keyStore=/etc/OPENHAB.keystore
-Dcom.ibm.ssl.keyStorePassword=KEYSTORE_PASSWORD
-Dcom.ibm.ssl.keyStoreType=PKCS12
-Dcom.ibm.ssl.keyStoreProvider=SUN
-Dcom.ibm.ssl.trustStore=/etc/OPENHAB.truststore
-Dcom.ibm.ssl.trustStorePassword=TRUSTSTORE_PASSWORD
-Dcom.ibm.ssl.trustStoreType=PKCS12
-Dcom.ibm.ssl.trustStoreProvider=SUN

Contents of openHAB mqtt.cfg

openhab_tcpbroker.url=tcp://localhost:1883
openhab_sslbroker.url=ssl://MY_DOMAIN.ORG:8883
openhab_sslbroker.clientId=openhab2
openhab_sslbroker.user=SSLBROKER_USER
openhab_sslbroker.pwd=SSLBROKER_PASSWORD

Contents of /etc/mosquitto/conf.d/listeners.conf

listener 1883 localhost
port 1883

listener 8883
allow_anonymous false
require_certificate true
certfile /etc/letsencrypt/live/MY_DOMAIN.ORG/fullchain.pem
cafile /etc/letsencrypt/live/MY_DOMAIN.ORG/fullchain.pem
keyfile /etc/letsencrypt/live/MY_DOMAIN.ORG/privkey.pem

I’ve tried copying the certificates to the /etc/mosquitto certificates folders. No difference. Ultimately I want to end up with symbolic links so that when Certbot regenerates the certificates, the symlinks point to the new certificates without having to copy anything around.

openHAB fails to connect to openhab_sslbroker! Same log output as previous post except that now both my 1883 and 8883 brokers are failing (because I have now added the listener configuration which must not be right either).

Can you guys put a different set of eyes on this to see where I’m going wrong?

Thanks so much for your patience!

Mike

@rlkoshak @vzorglub

Nothing obvious then?

Hmmmm. I wrote this reply days ago. Guess the problems with the forum never let ut get posted.

Does the user mosquitto is running under have permission to read the pem files? Usually, mosquitto ends up running under a mosquitto user and with root:root 644 it should be able to read them, but perhaps the parent folder doesn’t allow the mosquitto user to change to that directory or read from that directory.

You can run a quick test from the command line:

sudo -u mosquitto cat /etc/letsencrypt/live/MY_DOMAIN.ORG/fullchain.pem

If it prints out the contents of the file you are good. If not then that is a problem.

I was never able to get this to work, but I run mosquitto in a Docker container and I can’t mount symbolic links into the container and each new cert ends up as a new file so I never went down that track and used self signed certs.

Break the problem in half. First focus on the broker half of the problem. Configure it like you think it needs to be done then test it with an MQTT client like mosquito_pub or MQTT.fx. In both cases you can pass in cert files to authenticate with the broker if it is needed.

However, like I said before, I don’t think openHAB supports client certificates so I’m pretty sure that openHAB can’t connect to a listener that has require_certificate true. It can only check whether the server’s cert is trusted based on the CA being in the trust store.

But why do you want your OH to talk to the broker on localhost encrypted anyway? It would be much easier to set up a UFW or iptables rule that prevents any communication to port 1883 except from localhost. Then just let OH talk to mosquitto unencrypted. The network traffic never leaves the host machine and nothing else can connect to the broker on that port to mess with you. Your clients are allowed to be on different listeners. Honestly, if your LAN is reasonably protected, you can skip the firewall rule entirely. Again, the network traffic never leaves the host so it can’t be sniffed (unless they are on your host in which case they don’t need to) and if there is a rogue on your network the last thing they will be trying to do is connect to your MQTT broker.

Here is how I had it set up in the past. This was way before LetsEncrypt and I’ve long since lost my mosquitto configs (I could probably dig up that old machine and recover them if I had to).

  • openHAB connects unencrypted on listener 1883
  • I used self-signed certs and created a server pem and client pems
  • I created listener 8883 configed just like you have it only using my self-signed certs and CA
  • The client certs were loaded to the phone clients and I think I checked the box to ignore cert errors. At that time (still?) there was a problem where if you import a CA file at least on Android there is a constant warning that all your traffic can be monitored because of the addition of the self-created CA. Remember it is the CA that is the third party vouching for the server and client certs so when you add your own it could indicate someone is trying to pull a fast one. So the warning is not a bad thing, but it wasn’t what I wanted so I disabled the server checking check box so OwnTracks would ignore that I was using a self-signed CA and cert. With LetsEncrypt you don’t have to do that.
  • Port forwarded 8883 through the router.
  • Did the other stuff I mentioned above.

The key takeaway is that OH doesn’t have to mess with the certs and TLS stuff. It’s traffic is already pretty well protected since it never leaves localhost. Only the OwnTracks clients need the encryption and client certs. The fact that the two connect to different listeners doesn’t matter, they can all see the topics they are allowed to see per the ACLs.

tl;dr Forget the encryption for OH. Get the encryption working with OwnTracks and let OH remain unencrypted. This will make your problem way easier. I believe OwnTracks has a tutorial to tell you how to do this. At least they did way back when.

Thanks Rich. I’d had issues when trying to post my note. I didn’t realize it was a forum-wide issue.

My intent is to NOT require encryption on localhost:1883. require_certificate true is obviously my misunderstanding thinking this applied to 8883. I gather from your response that’s an option that applies to the “default” listener. Therefore, I do not want that option in my listener config because I do not intend to encrypt the default (1883) listener; right?

I think I’m starting to get the picture more clearly.

  • I will have OwnTracks send its data to my SSL configured listener on 8883 by configuring OwnTracks to point to MY_DOMAIN.ORG:8883 and having that port forwarded on my router.
  • The encrypted OwnTracks data will be delivered to my 8883 mosquitto listener.
  • Internally on my server, I configure mosquitto to bridge 8883 over to 1883.
  • openHAB only needs to know about 1883 because the traffic from 8883 will be bridged over to that listener by the mosquitto configuration.
  • Therefore, in this scenario, I don’t need any of the keystore/truststore/openHAB setenv JAVA_OPTS stuff because I’m NOT having openHAB do the bridging from a cloud MQTT broker.

Did I understand right?

Mike

Then I’m confused by your mqtt.cfg. If you are not encrypting communication on localhost then you don’t need ANY certs or SSL config in OH. Everything is unencrypted on port 1883 between OH and the broker.

There is nothing to do. Without explicit ACLs all clients connected to all listeners can read/write to all topics regardless of which listener the client used to connect to the broker. The listener only controls the connection. Once connected everyone sees the same broker.

You only need to bridge when you have more than one broker running.

Mostly. Just the little bit of confusion about needing to do anything special to bridge between the listeners. You don’t. What you may want to do is set up some ACLs to limit what topics the OwnTracks clients can publish or subscribe to. But that too is independent of the listeners. And please don’t mess with ACLs until you get it working without them.

Yeah, sorry. I would undo everything prior. I would have no encryption between openHAB and mosquitto.

Again, more clarity… Thanks.

  • ONE broker, listening on two ports (1883 & 8883) - no bridging necessary.
  • OwnTracks sends data encrypted via the configured certificates to MY_DOMAIN.ORG:8883.
  • My router forwards port 8883 to MY_SERVER:8883.
  • My 8883 listener uses the configured certificates to decrypt that data.
  • My broker sees the data delivered by both the 1883 listener and the 8883 listener.
  • openHAB sees all the data coming into the single broker.

mqtt.cfg becomes:

openhab_tcpbroker.url=tcp://localhost:1883

listeners.conf becomes:

listener 1883 localhost
port 1883

listener 8883
certfile /etc/letsencrypt/live/MY_DOMAIN.ORG/fullchain.pem
cafile /etc/letsencrypt/live/MY_DOMAIN.ORG/fullchain.pem
keyfile /etc/letsencrypt/live/MY_DOMAIN.ORG/privkey.pem

Mike

P.S. Right. I’m not tackling ACLs until I get 8883 receiving data successfully.

Looks reasonable to me.

Step 1 success! I’m able to connect an MQTT client to my 8883 listener with the Certbot certificates!

This listener config line was wrong:
listener 1883 localhost

adding the host at the end binds all traffic on the port to have to come from that host only… which obviously is not what I want. The line needs to be:
listener 1883

Now on to OwnTracks, then openHAB, then ACLs.

Mike

P.S. Did you hear me scream in elation? :wink:
P.P.S. Symlinks worked.

@vzorglub

Many thanks for the excellent guide.
I have the impression that the following command is wrong.

sudo keytool -import -alias myopenhab -file addtrustexternalroot.cert -storetype JKS -keystore.jsk

In any case it didnt work for me. What worked is

sudo keytool -import -alias myopenhab -file addtrustexternalroot.cert -storetype JKS -keystore truststore.jks

And I confirm that it works ! I just used it to get some sensor values from “The things network” based on LoRaWAN sensors located 500 meters away !

Christos (or anyone), how did you get your addtrustexternalroot.cert file? When I go to the link in the instructions (CONTACT US - Comodo: Cloud Native Cyber Security Platform) it downloads a addtrustexternalroot.crt file. the extension is different, cert vs crt.

Do be honest it was a while ago and I may have made a mistake and it was crt and not cert

You need to generate a jks file from it in the next step, have you tried this with your crt file?

I think that it does not really matter what the extension is. It is the content that matters. You can put whatever extension you like so crt should be ok

1 Like

when I run this and enter my password:

keytool -import -alias myopenhab -file /home/pi/Desktop/temp/ca.crt -storetype JKS -keystore keystore.jks

I get this error:

keytool error: java.lang.Exception: Public keys in reply and keystore don't match

Try this:

sudo keytool -import -alias myopenhab -file addtrustexternalroot.cert -storetype JKS -keystore truststore.jks

Replace your files…

I can connect to my broker via:

mosquitto_sub --cert ca.crt --key ca.key --tls-version tlsv1 -t '#' -p 8883

However, my mqtt binding in openhab cannot. I get this error in openhab console:

15:23:48.293 [ERROR] [openhab.io.transport.mqtt.MqttService] - Error starting broker connection
org.eclipse.paho.client.mqttv3.MqttException: Unable to connect to server
        at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:79) [202:org.openhab.io.transport.mqtt:1.12.0]
        at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:650) [202:org.openhab.io.transport.mqtt:1.12.0]
        at java.lang.Thread.run(Thread.java:745) [?:?]
Caused by: java.net.ConnectException: Connection refused
        at java.net.PlainSocketImpl.socketConnect(Native Method) ~[?:?]
        at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[?:?]
        at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[?:?]
        at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[?:?]
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[?:?]
        at java.net.Socket.connect(Socket.java:589) ~[?:?]
        at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:70) ~[?:?]
        ... 2 more

my configurations:

/etc/openhab2/services/mqtt.cfg:

mosquitto.url=ssl://localhost:8883
mosquitto.user=mqtt_user
mosquitto.pwd=password
mosquitto.qos=1
mosquitto.retain=true
mosquitto.async=false
mosquitto.clientId=openhab2

/etc/mosquitto/mosquitto.conf

pid_file /var/run/mosquitto.pid

persistence true
persistence_location /var/lib/mosquitto/

log_dest file /var/log/mosquitto/mosquitto.log

Allow_anonymous true
Password_file /etc/mosquitto/pwfile
Listener 8883

cafile /etc/mosquitto/ca_certificates/ca.crt
keyfile /etc/mosquitto/certs/server.key
certfile /etc/mosquitto/certs/server.crt
tls_version tlsv1

/usr/share/openhab2/runtime/bin/setenv:

export JAVA_OPTS="${JAVA_OPTS}
  -Dopenhab.home=${OPENHAB_HOME}
  -Dopenhab.conf=${OPENHAB_CONF}
  -Dopenhab.runtime=${OPENHAB_RUNTIME}
  -Dopenhab.userdata=${OPENHAB_USERDATA}
  -Dopenhab.logdir=${OPENHAB_LOGDIR}
  -Dfelix.cm.dir=${OPENHAB_USERDATA}/config
  -Djetty.host=${HTTP_ADDRESS}
  -Djetty.http.compliance=RFC2616
  -Dorg.ops4j.pax.web.listening.addresses=${HTTP_ADDRESS}
  -Dorg.osgi.service.http.port=${HTTP_PORT}
  -Dorg.osgi.service.http.port.secure=${HTTPS_PORT}"
  -Dcom.ibm.ssl.trustManager=SunX509
  -Dcom.ibm.ssl.keyManager=SunX509
  -Dcom.ibm.ssl.contextProvider=SunJSSE
  -Dcom.ibm.ssl.keyStore=/etc/keystore.jks
  -Dcom.ibm.ssl.keyStorePassword=adminadmin
  -Dcom.ibm.ssl.keyStoreType=JKS
  -Dcom.ibm.ssl.keyStoreProvider=SUN
  -Dcom.ibm.ssl.trustStore=/etc/truststore.jks
  -Dcom.ibm.ssl.trustStorePassword=adminadmin
  -Dcom.ibm.ssl.trustStoreType=JKS
  -Dcom.ibm.ssl.trustStoreProvider=SUN