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:
- Understanding Stunnel for SSL encryption in FIX communications.
- Setting up and configuring Stunnel.
- Example configuration for Stunnel in a FIX environment.
- 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 filedebug
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
, andCAfile
are the paths to the SSL certificate, private key, and CA bundle, respectively.CApath
can be used instead ofCAfile
to configure multiple certificates.I recommend using the
CAFile
option and concatenate multiple certificates there, asCAPath
requires to specially hash the names of the files.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.