SSL FIX Connection Using Stunnel

This guide details the process of configuring SSL (Secure Socket Layer) for the FIX (Financial Information Exchange) protocol using Stunnel in C#. Stunnel provides a layer of SSL encryption for network connections, making it a versatile tool for secure communications.

Here is the list of topics this guide covers:

  1. Understanding Stunnel for SSL encryption in FIX communications.
  2. Setting up and configuring Stunnel.
  3. Example configuration for Stunnel in a FIX environment.
  4. Trade-offs and benefits of separating SSL and FIX configurations.

Understanding Stunnel for SSL Encryption in FIX Communications

Stunnel is a software tool that adds SSL encryption to existing TCP connections. It is ideal for securing FIX protocol communications as it works independently of the application layer, providing a flexible encryption solution.

Setting Up and Configuring Stunnel

To begin using Stunnel for FIX communications, first, install Stunnel on your server. Once installed, the primary task is to configure Stunnel to encrypt the FIX session.

Example Configuration for Stunnel in a FIX Environment

Here’s an example of how to configure Stunnel for FIX protocol. The configuration file, typically named stunnel.conf, should be set up as follows:

; Stunnel configuration for FIX protocol
; GLOBAL OPTIONS
; global options for accept/local/remote sockets
; For FIX connections, it is recommended to disable the Nagle algorithm of TCP to reduce latency.
socket=a:TCP_NODELAY=1
socket=l:TCP_NODELAY=1
socket=r:TCP_NODELAY=1

client = yes
output = /path/to/stunnel.log
; Debug level (0 = emergency, 7 = debug)
debug = 7

; SERVICE-LEVEL OPTIONS
[fix_tunnel]
accept = 127.0.0.1:8085
connect = fix.acme.com:443

cert = /path/to/cert.pem
key = /path/to/key.pem
CAfile = /path/to/ca.pem
; or
; CApath = /path/to/ca/chain_dir
verify = 2
verifyChain = yes
verifyPeer = yes
checkHost = fix.acme.com

; Enforce specific SSL/TLS versions
sslVersion = TLSv1.2
sslVersionMax = TLSv1.2

Basic options:

  • client specifies whether Stunnel will act as a client (yes) or server (no).
  • output specifies path to the stunnel log file
  • debug specifies the level of debug. Useful to set to the highest (7) level when configuring

Tunnel options:

  • accept defines the local port to listen for incoming FIX connections.
  • connect specifies the remote FIX server and port to connect to.

Certificate options:

  • cert, key, and CAfile are the paths to the SSL certificate, private key, and CA bundle, respectively. CApath can be used instead of CAfile to configure multiple certificates.
  • verify sets the level of verification for SSL certificates (0 — no verification. 1 — verify the peer certificate chain if present, 2 — verify the peer certificate chain, 3 — Verify the peer certificate chain and the end-entity (leaf) peer certificate against a locally installed certificate, 4 — Ignore the peer certificate chain and only verify the end-entity (leaf) peer certificate against a locally installed certificate).
  • verifyChain is a more specific option that controls whether stunnel verifies the entire certificate chain, as opposed to just the certificate presented by the peer. When enabled, it ensures that not only the certificate itself is valid, but also that all certificates up to the root certificate are valid and trusted.
  • verifyPeer — specifically dictates whether stunnel should verify the peer's SSL/TLS certificate. When enabled, it requires that the peer presents a valid certificate for the connection to be established. This is essential for scenarios where authentication of the connecting party is required for security reasons. If this option is disabled, stunnel will not authenticate the peer based on its certificate, which might be suitable for environments where certificate management is not feasible or necessary.
  • checkHost — verify the host of the end-entity (leaf) peer certificate subject

If your organization uses a proxy for internet access, additional configuration is needed to ensure Stunnel can connect through the proxy:

; Stunnel configuration with proxy support
[fix_tunnel]
accept = 127.0.0.1:8085
protocol = connect
protocolHost = fix.acme.com:443
connect = [proxy_server]:[proxy_port]
...

In this proxy configuration:

  • protocol is set to connect, indicating a proxy connection.
  • protocolHost specifies the actual FIX server and port.
  • connect is modified to the proxy server address and port.

After editing the configuration file, restart Stunnel to apply these settings.

Connection Testing

On successful connection, stunnel output with max debug level (7) should look like the following:


2024-01-10 12:34:56 LOG5[main]: Reading configuration from file C:\Users\...
2024-01-10 12:34:56 LOG5[main]: UTF-8 byte order mark not detected
2024-01-10 12:34:56 LOG5[main]: FIPS mode disabled
2024-01-10 12:34:56 LOG5[main]: Compression disabled
2024-01-10 12:34:56 LOG5[main]: No PRNG seeding was required
2024-01-10 12:34:56 LOG5[main]: Initializing service [fix_tunnel]
2024-01-10 12:34:56 LOG5[main]: Initializing context [fix_tunnel]
2024-01-10 12:34:56 LOG5[main]: stunnel default security level set: 2
2024-01-10 12:34:56 LOG7[main]: Ciphers: HIGH:!aNULL:!SSLv2:!DH:!kDHEPSK
2024-01-10 12:34:56 LOG7[main]: TLSv1.3 ciphersuites: TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256
2024-01-10 12:34:56 LOG7[main]: TLS options: 0x02100000 (+0x0, -0x0)
2024-01-10 12:34:56 LOG5[main]: Session resumption enabled
2024-01-10 12:34:56 LOG6[main]: Loading certificate from file: /path/to/cert.pem
2024-01-10 12:34:56 LOG6[main]: Certificate loaded from file: /path/to/cert.pem
2024-01-10 12:34:56 LOG6[main]: Loading private key from file: /path/to/key.pem
2024-01-10 12:34:56 LOG6[main]: Private key loaded from file: /path/to/key.pem
2024-01-10 12:34:56 LOG7[main]: Private key check succeeded
2024-01-10 12:34:56 LOG7[main]: Configured trusted server CA: C=US, L=New York, O=ACME Corp, CN=fix.acme.com
2024-01-10 12:34:56 LOG7[main]: Configured trusted server CA: C=US, O=DigiCert Inc, CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1
2024-01-10 12:34:56 LOG7[main]: Configured trusted server CA: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G2
2024-01-10 12:34:56 LOG7[main]: OCSP: Client OCSP stapling enabled
2024-01-10 12:34:56 LOG7[main]: DH initialization skipped: client section
2024-01-10 12:34:56 LOG7[main]: ECDH initialization
2024-01-10 12:34:56 LOG7[main]: ECDH initialized with curves X....
2024-01-10 12:34:56 LOG7[main]: Configuration successful
....
2024-01-10 12:34:56 LOG5[main]: Binding service [fix_tunnel]
2024-01-10 12:34:56 LOG7[main]: Service [fix_tunnel] (FD=3) bound to 127.0.0.1:8085
...
2024-01-10 12:35:00 LOG7[0]: Service [fix_tunnel] accepted connection from 127.0.0.1:56123
...
2024-01-10 12:35:00 LOG7[0]: SSL state (connect): before SSL initialization
2024-01-10 12:35:00 LOG7[0]: Initializing application specific data for session authenticated
2024-01-10 12:35:00 LOG7[0]: SSL state (connect): SSLv3/TLS write client hello
2024-01-10 12:35:00 LOG7[0]: SSL state (connect): SSLv3/TLS write client hello
2024-01-10 12:35:00 LOG7[0]: SSL state (connect): SSLv3/TLS read server hello

2024-01-10 12:35:00 LOG7[0]: Verification started at depth=2: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G2
2024-01-10 12:35:00 LOG7[0]: CERT: Pre-verification succeeded
2024-01-10 12:35:00 LOG7[0]: OCSP: Certificate chain verification disabled
2024-01-10 12:35:00 LOG7[0]: Certificated accepted at depth=2: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G2

2024-01-10 12:35:00 LOG7[0]: Verification started at depth=1: C=US, O=DigiCert Inc, CN=DigiCert Global Root G2 TLS RSA SHA256 2020 CA1
2024-01-10 12:35:00 LOG7[0]: CERT: Pre-verification succeeded
2024-01-10 12:35:00 LOG7[0]: OCSP: Certificate chain verification disabled
2024-01-10 12:35:00 LOG7[0]: Certificated accepted at depth=1: C=US, O=DigiCert Inc, CN=DigiCert Global Root G2 TLS RSA SHA256 2020 CA1

2024-01-10 12:35:00 LOG7[0]: Verification started at depth=0: C=US, L=New York, O=ACME Corp, CN=fix.acme.com
2024-01-10 12:35:00 LOG7[0]: CERT: Pre-verification succeeded
2024-01-10 12:35:00 LOG7[0]: CERT: Host name "fix.acme.com" matched with "fix.acme.com"
2024-01-10 12:35:00 LOG7[0]: CERT: Locally installed certificate matched
2024-01-10 12:35:00 LOG7[0]: OCSP: Certificate chain verification disabled
2024-01-10 12:35:00 LOG7[0]: Certificated accepted at depth=0: C=US, L=New York, O=ACME Corp, CN=fix.acme.com

2024-01-10 12:35:00 LOG7[0]: TLS state (connect): SSLv3/TLS read server certificate
2024-01-10 12:35:00 LOG7[0]: TLS state (connect): SSLv3/TLS read server key exchange
2024-01-10 12:35:00 LOG7[0]: Received trusted client CA: ...
2024-01-10 12:35:00 LOG7[0]: TLS state (connect): SSLv3/TLS read server certificate request
...

Trade-offs for using separate SSL and FIX Configurations

Using Stunnel allows for the separation of SSL and FIX configurations. This separation offers several benefits, including easier management of SSL certificates, as they are independent of the FIX application, and the ability to update SSL protocols without modifying the FIX application. However, it also introduces additional complexity in terms of network architecture and monitoring, as SSL encryption is handled externally. Additionally, there might be a slight increase in latency due to the additional encryption/decryption layer.