Quick steps to set up an encrypted connection for ADS

Introduction

Elektron SDKs support several connection types such as a socket, reliable multicast, HTTP, and HTTPS when connecting to Advanced Distribution Server (ADS). Users can configure ADS to support the socket, reliable multicast, and HTTP connection types. However, for the HTTPS connection type, it requires an additional encryption device which is in the middle of Elektron SDKs and ADS to handle encryption. An encryption device could be a hardware SSL accelerator or software. This article demonstrates how to use software called stunnel to provide secure encrypted connections and how to configure or implement Elektron SDKs to support this encrypted channel.

It is assumed that the reader is familiar with EMA or ETA applications, and has experience developing products using the C, C++ orJava programming language in a networked environment.

Environment

The ADS must be installed and run properly on the environment. The components used in this article are:

  • stunnel 5.41 on Windows
  • Advanced Distribution Server 3.2.0.L1
  • Elektron SDK C/C++ 1.2.2
  • Elektron SDK Java 1.2.2

stunnel

stunnel is an open-source multi-platform application used to provide secure encrypted connections for clients or servers that do not natively support SSL or TLS. stunnel uses the OpenSSL library to support the underlying TLS or SSL protocol. It can be downloaded from stunnel. In this article, stunnel is used as an SSL accelerator to handle encryption on behalf of ADS.

Steps to configure stunnel

1. Download and install

The stunnel package can be downloaded from www.stunnel.org

2. Add the following configurations to stunnel.conf at the end of file

[RSSL]
client = no
accept = 14002
connect = ads1:14002
cert = stunnel.pem

The stunnel.conf file is in the stunnel/config folder.

You need to change ads1:14002 to the IP address or hostname and RSSL port of your ADS machine. The above configurations create a new service definition called RSSL. This service will listen on TCP port 14002 on the local machine. After receiving a connection on this port, it will forward the connection to TCP port 14002 on ads1 machine. The certificate file used by this service is stunnel.pem which is available in the stunnel package.

3. Convert the certificate file stunnel.pem to stunnel.der

The stunnel package contains the openssl command in the stunnel/bin folder. This command can be used to convert the certificate file into other formats.

openssl x509 -outform der -in stunnel.pem -out stunnel.der

The converted certificate file will be used in the following sections.

4. Start the stunnel process

After starting stunnel, you need to make sure that the ADS is up and running. Then, the stunnel is ready for accepting encryption connections from Elektron APIs.

 

The next sections show how to set up and configure Elektron SDKs to connect to the stunnel. These sections include:

  • Steps to set up and configure EMA C++
  • Steps to set up and configure EMA Java
  • Run a Consumer example in ETA C
  • Run a Consumer example in ETA Java

Steps to configure and run EMA C++

To demonstrate this, I use the Cons112 example (112MarketPriceTunnelingConnection) in the package. This example supports an encrypted connection.

1. (Windows Only) Install the certificate file

On Windows, Elektron SDKs use WinInet to create HTTP and HTTPS connections to a server. Therefore, for an encrypted connection, the certificate file must be installed to a Windows certificate store.

  • Run a command prompt as Administrator
  • Change to the directory that has the stunnel.der file created by the previous step
  • Run the following command to add the stunnel certificate to the Windows certificate store
certutil -addstore -f "Root" stunnel.der

After installing, you can verify it by running "certmgr.msc". The certificate is installed in the Trusted Root Certification Authorities.

After testing, the certificate can be uninstalled by running the following command as Administrator.

certutil -delstore root localhost

On the Linux machine, this step can be ignored.

2. Configure an IP address for the encrypted channel

EMA has supported encrypted channel type since Elektron SDK 1.2.0.L1. The channel type can be set through the EMA configuration file (EmaConfig.xml). The channel type of the encrypted channel must be ChannelType::RSSL_ENCRYPTED.

The Cons112 example uses Consumer_3. From the configuration file, the Consumer_3 uses Channel_3 for a connection and the channel type of the Channel_3 is ChannelType::RSSL_ENCRYPTED. We still need to change the value of Host configuration to the IP address of the machine that runs stunnel. In this scenario, the IP address is 127.0.0.1 which is a loopback address.

    <Consumer>
      <Name value="Consumer_3"/>

      <!-- ChannelSet specifies an ordered list of Channels to which OmmConsumer will attempt to    -->
      <!-- connect, one at a time, if the previous one fails to connect                            -->
      <ChannelSet value="Channel_3"/>

      <Logger value="Logger_1"/>
      <Dictionary value="Dictionary_1"/>
      <XmlTraceToStdout value="0"/>
    </Consumer>
...
...
        <Channel>
            <Name value="Channel_3"/>
            <ChannelType value="ChannelType::RSSL_ENCRYPTED"/>
            <CompressionType value="CompressionType::None"/>
            <GuaranteedOutputBuffers value="5000"/>
            <Host value="127.0.0.1"/>
            <Port value="14002"/>
            <!-- ObjectName is optional: defaulted to ""                                                -->
            <ObjectName value=""/>
        </Channel>

3. Modify and run the code

The code in the Cons112 example consumes data from DIRECT_FEED service. We need to change this to the service name supported by ADS. In this scenario, the service name is ELEKTRON_DD.

int main( int argc, char* argv[] )
{ 
...
        OmmConsumer consumer(config.username("user").consumerName("Consumer_3"));
        consumer.registerClient( ReqMsg().serviceName( "ELEKTRON_DD" ).name( "IBM.N" ), client );
...
}

You may need to change the username in the code if the entitlement is enabled on ADS.

Then, run the example. The example will create an encrypted connection to the stunnel which performs encryption and decryption on behalf of ADS.

If the example is unable to retrieve the data, the verbose log can be enabled in the EmaConfig.xml to verify the problem. The verbose log of Consumer_3 can be enabled by setting LoggerSeverity of Logger_1 to LoggerSeverity::Verbose.

<LoggerGroup>
    <LoggerList>
        <Logger>
            <Name value="Logger_1"/>

            <!-- LoggerType is optional:  defaulted to "File"                                            -->
            <!-- possible values: Stdout, File                                                            -->
            <LoggerType value="LoggerType::Stdout"/>

            <!-- LoggerSeverity is optional: defaulted to "Success"                                        -->
            <!-- possible values: Verbose, Success, Warning, Error, NoLogMsg                            -->
            <LoggerSeverity value="LoggerSeverity::Verbose"/>
        </Logger>

Steps to configure and run EMA Java

To demonstrate this, I use the example112MarketPriceTunnelingConnection.Consumer example in the package. This example supports an encrypted connection.

1. Import a certificate into your keystore file

First, the certificate file must be imported the a keystore used by the application. The keystore file (.jsk) contains the server’s certification, including its private key which is used for encryption channels. The keystore file is protected with a password. Each keystore entry has a unique alias that refers to a particular certificate. We need to use the keytool command to manage the keystore file.

The following command will create a new keystore file (if it doesn't exist) and import the stunnel.der file created in the previous step to this keystore file.

keytool -import -alias stunnel -keystore stunnel.jks -file stunnel.der

It will ask for a password for this keystore file. The keystore file (stunnel.jks) and password will be used in the next step.

2. Configure an IP address for the encrypted channel

EMA has supported encrypted channel type since Elektron SDK 1.2.0.L1. The channel type can be set through the EMA configuration file (EmaConfig.xml). The channel type of the encrypted channel must be ChannelType::RSSL_ENCRYPTED.

The example112MarketPriceTunnelingConnection.Consumer example uses Consumer_3. From the configuration file, the Consumer_3 uses Channel_4 for a connection and the channel type of the Channel_4 is ChannelType::RSSL_ENCRYPTED. We still need to change the value of Host configuration to the IP address of the machine that runs stunnel. In this scenario, the IP address is 127.0.0.1 which is a loopback address.

        <Consumer>
            <Name value="Consumer_3"/>

            <!-- Channel set to "RSSL_ENCRYPTED"                                                        -->
            <Channel value="Channel_4"/>

            <!-- Dictionary is optional: defaulted to "ChannelDictionary"                                -->
            <Dictionary value="Dictionary_1"/>
            <XmlTraceToStdout value="0"/>
        </Consumer>
...
...
        <Channel>
            <Name value="Channel_4"/>
            <ChannelType value="ChannelType::RSSL_ENCRYPTED"/>
            <CompressionType value="CompressionType::None"/>
            <GuaranteedOutputBuffers value="5000"/>
            <Host value="127.0.0.1"/>
            <Port value="14002"/>
            <!-- ObjectName is optional: defaulted to ""                                                -->
            <ObjectName value=""/>
        </Channel>

3. Modify and run the code

The code in the example112MarketPriceTunnelingConnection.Consumer example consumes data from DIRECT_FEED service. We need to change this to the service name supported by ADS. In this scenario, the service name is ELEKTRON_DD.

            AppClient appClient = new AppClient();

            consumer  = EmaFactory.createOmmConsumer(config.username("user").consumerName("Consumer_3"));

            consumer.registerClient( EmaFactory.createReqMsg().serviceName("ELEKTRON_DD").name("IBM.N"), appClient, 0);

You may need to change the username in the code if the entitlement is enabled on ADS.

Then run the example with the following arguments:

-keyfile stunnel.jks -keypasswd <password>

The stunnel.jks is the keystore file created in the previous step. <password> 
is the password defined when creating the keystore file.

Then, run the example. The example will create an encrypted connection to the stunnel which performs encryption and decryption on behalf of ADS.

If the example is unable to retrieve the data, please enable logging in EMA Java to verify the problem. To enable logging, please refer to How to integrate Elektron Message API Java edition with Log4j Logging Framework.

Run a Consumer example in ETA C

To demonstrate this, I use the rsslConsumer example (Eta\Applications\Examples\Consumer) in the package. It supports an encrypted connection.

1. (Windows Only) Install the certificate file

Please follow the first step in the Steps to set up and configure EMA C++ to install the certificate file on Windows

2. Run the Consumer example

The rsslConsumer example in the package supports an encrypted channel with the following parameters:

-c encrypted -h 127.0.0.1 -p 14002 -s ELEKTRON_DD -mp IBM.N -uname user

With the above parameters, the rsslConsumer example will create an encrypted channel to stunnel running on the local machine, use user as a username for a login request, and then subscribe to IBM.N from ELEKTRON_DD service.

Run a Consumer example in ETA Java

To demonstrate this, I use the com.thomsonreuters.upa.examples.consumer.Consumer example in the package. This example supports an encrypted connection.

1. Import a certificate into your keystore file

If you don't have the keystore file for stunnel, please follow the first step in the Steps to set up and configure EMA Java to import a certificate into the keystore file.

2. Run the Consumer example

The com.thomsonreuters.upa.examples.consumer.Consumer example in the package supports an encrypted channel with the following parameters:

-connectionType encrypted -s ELEKTRON_DD -h 127.0.0.1 -keyfile stunnel.jks -keypasswd <password> -mp IBM.N -uname user

The stunnel.jks is the keystore file created in the previous step. <password> 
is the password defined when creating the keystore file.

With the above parameters, the com.thomsonreuters.upa.examples.consumer.Consumer example will create an encrypted channel to stunnel running on the local machine, use user as a username for a login request, and then subscribe to IBM.N from ELEKTRON_DD service.

Troubleshooting

1. "Error: 0012 Invalid connection type.", "Error initializing channel"

This error indicates that the application is unable to connect to the stunnel. Please make sure the stunnel is running properly. You can also enable debug log level in stunnel.conf and then reload the configuration file, as shown below.

debug = debug

After reloading, you will see [RSSL] is bound to 0.0.0.0:14002 in the stunnel log.

2018.12.12 16:27:53 LOG7[main]: Service [RSSL] (FD=520) bound to 0.0.0.0:14002

When the application connects to the stunnel, you will see the following log in the stunnel.

...
2018.12.12 16:33:29 LOG7[main]: Service [RSSL] accepted (FD=428) from 127.0.0.1:49109
2018.12.12 16:33:29 LOG7[main]: Creating a new thread
2018.12.12 16:33:29 LOG7[main]: New thread created
2018.12.12 16:33:29 LOG7[4]: Service [RSSL] started
2018.12.12 16:33:29 LOG7[4]: Option TCP_NODELAY set on local socket
2018.12.12 16:33:29 LOG5[4]: Service [RSSL] accepted connection from 127.0.0.1:49109
2018.12.12 16:33:29 LOG6[4]: Peer certificate not required
2018.12.12 16:33:29 LOG7[4]: TLS state (accept): before/accept initialization
2018.12.12 16:33:29 LOG7[4]: SNI: no virtual services defined
2018.12.12 16:33:29 LOG7[4]: TLS state (accept): SSLv3 read client hello A
2018.12.12 16:33:29 LOG7[4]: TLS state (accept): SSLv3 write server hello A
...
2018.12.12 16:33:29 LOG6[4]: TLS accepted: new session negotiated
2018.12.12 16:33:29 LOG6[4]: No peer certificate received
2018.12.12 16:33:29 LOG6[4]: Negotiated TLSv1.2 ciphersuite ECDHE-RSA-AES256-SHA384 (256-bit encryption)
2018.12.12 16:33:29 LOG7[4]: Compression: null, expansion: null
2018.12.12 16:33:29 LOG6[4]: s_connect: connecting 192.168.27.16:14002
2018.12.12 16:33:29 LOG7[4]: s_connect: s_poll_wait 192.168.27.16:14002: waiting 10 seconds
2018.12.12 16:33:29 LOG5[4]: s_connect: connected 192.168.27.16:14002
2018.12.12 16:33:29 LOG6[4]: persistence: 192.168.27.16:14002 cached
2018.12.12 16:33:29 LOG5[4]: Service [RSSL] connected remote server from 10.42.68.175:49110
2018.12.12 16:33:29 LOG7[4]: Option TCP_NODELAY set on remote socket
2018.12.12 16:33:29 LOG7[4]: Remote descriptor (FD=356) initialized
...

If the stunnel is running properly, you still see this error. Please verify that the certificate file is installed properly on a Windows certificate store (Windows C/C++) or a keystore file (Java)

Summary

Elektron SDKs support several connection types such as a socket, reliable multicast, HTTP, and HTTPS. However, when using the HTTPS connection type with ADS, an SSL accelerator is required to handle encryption on behalf of ADS. This article demonstrates how to quickly set up the stunnel as an SSL accelerator and test the encrypted connection with examples in the Elektron SDKs package.

References