TLS configuration of MQTT
Java clients and telemetry channels
Configure TLS to authenticate the telemetry channel and the MQTT
Java client, and encrypt the transfer of messages
between them. MQTT
Java clients use Java Secure Socket Extension (JSSE) to connect telemetry
channels using TLS. As an alternative to using SSL, some kinds of Virtual Private Network (VPN), such as IPsec, authenticate the endpoints of a TCP/IP connection. VPN encrypts each IP packet that flows over the network. Once such a VPN connection is established, we have established a trusted network. We can connect MQTT clients to telemetry channels using TCP/IP over the VPN network.
We can configure the connection between a Java
MQTT client and a telemetry channel to use the TLS
protocol over TCP/IP. What is secured depends on how you configure TLS to use JSSE. Starting with
the most secured configuration, we can configure three different levels of security:
Permit only trusted MQTT clients to connect.
Connect an MQTT client only to a trusted telemetry
channel. Encrypt messages between the client and the queue manager; see MQTT client authentication using TLS
Configure the telemetry channel parameters using IBM MQ Explorer. Set the MQTT
Java Client parameters in the
MqttConnectionOptions.SSLProperties attribute. Modify JRE security parameters by
editing files in the JRE security directory on both the client and server.
MQ Telemetry channel
Set all the telemetry channel TLS parameters using IBM MQ Explorer.
ChannelName
ChannelName is a required parameter on all channels.
The channel name identifies the channel associated with a particular port number. Name channels
to help you administer sets of MQTT clients.
PortNumber
PortNumber is an optional parameter on all channels. It defaults to
1883 for TCP channels, and 8883 for TLS channels.
The TCP/IP port number associated with this channel. MQTT clients are connected to a channel by specifying the
port defined for the channel. If the channel has TLS properties, the client must connect using the
TLS protocol; for example:
MQTTClient mqttClient = new MqttClient( "ssl://www.example.org:8884", "clientId1");
mqttClient.connect();
KeyFileName
KeyFileName is a required parameter for TLS channels. It must be omitted for TCP
channels.
KeyFileName is the path to the Java keystore containing digital certificates that you
provide. Use JKS, JCEKS or PKCS12 as the type of keystore on the server.
Identify the keystore type by using one of the following file extensions:
.jks
.jceks
.p12
.pkcs12
A keystore with any other file extension is assumed to be a JKS keystore.
We can combine one type of keystore at the server with other types of keystore at the client.
Place the private certificate of the server in the keystore. The certificate is known as the
server certificate. The certificate can be self-signed, or part of a certificate chain that is
signed by a signing authority.
If you are using a certificate chain, place the associated certificates in the server keystore.
The server certificate, and any certificates in its certificate chain, are sent to clients to
authenticate the identity of the server.
If we have set ClientAuth to Required, the keystore must
contain any certificates necessary to authenticate the client. The client sends a self-signed
certificate, or a certificate chain, and the client is authenticated by the first verification of
this material against a certificate in the keystore. Using a certificate chain, one certificate can
verify many clients, even if they are issued with different client certificates.
PassPhrase
PassPhrase is a required parameter for TLS channels. It must be omitted for TCP
channels.
The passphrase is used to protect the keystore.
ClientAuth
ClientAuth is an optional TLS parameter. It defaults to no client
authentication. It must be omitted for TCP channels.
Set ClientAuth if you want the telemetry (MQXR) service to authenticate the
client, before permitting the client to connect to the telemetry channel.
If you set ClientAuth, the client must connect to the server using TLS, and
authenticate the server. In response to setting ClientAuth, the client sends its
digital certificate to the server, and any other certificates in its keystore. Its digital
certificate is known as the client certificate. These certificates are authenticated against
certificates held in the channel keystore, and in the JRE cacerts store.
CipherSuite
CipherSuite is an optional TLS parameter. It defaults to try all the enabled
CipherSpecs. It must be omitted for TCP channels.
If you want to use a particular CipherSpec, set CipherSuite to the name of the
CipherSpec that must be used to establish the TLS connection.
The telemetry service and MQTT client negotiate a
common CipherSpec from all the CipherSpecs that are enabled at each end. If a specific CipherSpec is
specified at either or both ends of the connection, it must match the CipherSpec at the other end.
Install additional ciphers by adding additional providers to JSSE.
Federal Information Processing Standards (FIPS)
FIPS is an optional setting. By default it is not set.
Either in the properties panel of the queue manager, or using runmqsc, set
SSLFIPS. SSLFIPS specifies whether only FIPS-certified algorithms
are to be used.
Revocation namelist
Revocation namelist is an optional setting. By default it is not set.
Either in the properties panel of the queue manager, or using runmqsc, set
SSLCRLNL. SSLCRLNL specifies a namelist of authentication
information objects which are used to provide certificate revocation locations.
No other queue manager parameters that set TLS properties are used.
MQTT
Java client
Set TLS properties for the Java client in
MqttConnectionOptions.SSLProperties ; for example:
java.util.Properties sslClientProperties = new Properties();
sslClientProperties.setProperty("com.ibm.ssl.keyStoreType", "JKS");
com.ibm.micro.client.mqttv3.MqttConnectOptions conOptions = new MqttConnectOptions();
conOptions.setSSLProperties(sslClientProperties);
The names and values of specific properties are described in the
MqttConnectOptions class. For links to client API documentation for the MQTT client libraries, see MQTT client programming reference.
Protocol
Protocol is optional.
The protocol is selected in negotiation with the telemetry server. If you require a specific
protocol we can select one. If the telemetry server does not support the protocol the connection
fails.
ContextProvider
ContextProvider is optional.
KeyStore
KeyStore is optional. Configure it if ClientAuth is set at the
server to force authentication of the client.
Place the digital certificate of the client, signed using its private key, into the keystore.
Specify the keystore path and password. The type and provider are optional. JKS is the default type,
and IBMJCE is the default provider.
Specify a different keystore provider to reference a class that adds a new keystore provider.
Pass the name of the algorithm used by the keystore provider to instantiate the
KeyManagerFactory by setting the key manager name.
TrustStore
TrustStore is optional. We can place all the certificates you trust in the JRE
cacerts store.
Configure the truststore if you want to have a different truststore for the client. You might not
configure the truststore if the server is using a certificate issued by a well known CA that already
has its root certificate stored in cacerts.
Add the publicly signed certificate of the server or the root certificate to the truststore, and
specify the truststore path and password. JKS is the default type, and IBMJCE is the default
provider.
Specify a different truststore provider to reference a class that adds a new truststore provider.
Pass the name of the algorithm used by the truststore provider to instantiate the
TrustManagerFactory by setting the trust manager name.
JRE
Other aspects of Java security that affect the
behavior of TLS on both the client and server are configured in the JRE. The configuration files on
Windows are in Java Installation Directory\jre\lib\security. If you are using the JRE
shipped with IBM MQ the path is as shown in the
following table:
Table 1. Filepaths by platform for JRE TLS configuration files
The cacerts file contains the root certificates of well-known certificate
authorities. The cacerts is used by default, unless you specify a truststore.
If we use the cacerts store, or do not provide a truststore, you must review
and edit the list of signers in cacerts to meet your security requirements.
We can open cacerts using the IBM MQ command strmqikm.which runs the IBM Key Management utility. Open cacerts
as a JKS file, using the password changeit. Modify the password to secure the file.
Configure security classes
Use the java.security file to register additional security providers and
other default security properties.
Permissions
Use the java.policy file to modify the permissions granted to resources.
javaws.policy grants permissions to javaws.jar
Encryption strength
Some JREs ship with reduced strength encryption. If we cannot import keys into keystores,
reduced strength encryption might be the cause. Either, try starting ikeyman
using the strmqikm command, or download strong, but limited jurisdiction files
from
IBM developer kits, Security information.
Important: Your country of origin might have restrictions on the import, possession,
use, or re-export to another country, of encryption software. Before downloading or using the
unrestricted policy files, you must check the laws of your country. Check its regulations, and its
policies concerning the import, possession, use, and re-export of encryption software, to determine
if it is permitted.
Modify the trust provider to permit the client to connect to any server
The example illustrates how to add a trust provider and reference it from the MQTT client code. The example performs no authentication of
the client or server. The resulting TLS connection is encrypted without being authenticated.
The code snippet in Figure 1 sets the
AcceptAllProviders trust provider and trust manager for the MQTT client.
Figure 1. MQTT Client code snippet
java.security.Security.addProvider(new AcceptAllProvider());
java.util.Properties sslClientProperties = new Properties();
sslClientProperties.setProperty("com.ibm.ssl.trustManager","TrustAllCertificates");
sslClientProperties.setProperty("com.ibm.ssl.trustStoreProvider","AcceptAllProvider");
conOptions.setSSLProperties(sslClientProperties);
Figure 2. AcceptAllProvider.java
package com.ibm.mq.id;
public class AcceptAllProvider extends java.security.Provider {
private static final long serialVersionUID = 1L;
public AcceptAllProvider() {
super("AcceptAllProvider", 1.0, "Trust all X509 certificates");
put("TrustManagerFactory.TrustAllCertificates",
AcceptAllTrustManagerFactory.class.getName());
}
Figure 3. AcceptAllTrustManagerFactory.java
protected static class AcceptAllTrustManagerFactory extends
javax.net.ssl.TrustManagerFactorySpi {
public AcceptAllTrustManagerFactory() {}
protected void engineInit(java.security.KeyStore keystore) {}
protected void engineInit(
javax.net.ssl.ManagerFactoryParameters parameters) {}
protected javax.net.ssl.TrustManager[] engineGetTrustManagers() {
return new javax.net.ssl.TrustManager[] { new AcceptAllX509TrustManager() };
}