HAProxy Enterprise 2.3 & HAProxy 2.4 Support the Financial Information eXchange Protocol (FIX)

A floor of commotion bustling with people holding phones and shouting out purchase and sell orders, some using hand signals to communicate over the noise. This was a common scene on Wall Street in the 1980s. Nowadays, transactions happen at the push of a button with traders sitting directly in front of a computer. In fact, the computer has made it possible to automate the buying and selling of securities, leading to an era of high-frequency, algorithmic trading.

What also makes it possible is having a common language for communicating trades and pricing information between peers. That language is called the Financial Information eXchange protocol (FIX). FIX is a standard that’s been adopted across the financial industry. Defining a simple, text-based format of data arranged in key-value pairs, it allows people—and automated systems—across the world to transact business.

HAProxy 2.4, scheduled for release this summer, adds support for the FIX protocol into the world’s fastest and most widely used software load balancer. This new feature has already been backported to HAProxy Enterprise 2.3. In this blog post, we’ll describe some of the benefits of using an HAProxy load balancer to route traffic to your FIX application servers, including enabling:

  • load balancing across multiple FIX servers

  • secure TLS encryption for FIX messages

  • validation of FIX Logon messages

  • routing based on tags in a Logon message (e.g. by the SenderCompID)

  • authentication with TLS client certificates

  • matching of clients with IP addresses

  • logging of FIX tag values

HAProxy is an open-source software load balancer that leads the pack in performance and is trusted by companies around the world to support latency-sensitive applications that handle the immense traffic load. Having FIX available in HAProxy is welcome news for many financial organizations since it means that they can finally replace their expensive hardware load balancers and pursue a cloud-native approach.

Join our live webinar: HAProxy and the Financial Information eXchange (FIX) Protocol

Load Balance Fix Servers

The FIX protocol is an application-layer messaging protocol, which means that it does not dictate how it should be transported. However, most implementations use TCP/IP as the transport protocol beneath it. An HAProxy load balancer accepts incoming client connections over TCP/IP and distributes them evenly to a pool of FIX servers. That means that you can scale out your server capacity easily by adding more servers, with zero downtime. Simultaneously, you increase the availability of your service.

load balance fix servers

Tls Encryption

FIX messages that exchange trade information should be encrypted when traveling across untrusted networks like the Internet. HAProxy provides end-to-end Transport Layer Security (TLS) encryption, which you can fine tune such as to enforce a minimum version of TLS between the client and HAProxy.

In the configuration snippet below, we enable TLS in the HAProxy listener and permit only TLS 1.2 or newer to be used, as required by the FIX over TLS (FIXS) protocol:

frontend fix_listener
mode tcp
bind :443 ssl crt /etc/haproxy/certs/cert.pem ssl-min-ver TLSv1.2
default_backend fix_servers

You can also enable TLS between HAProxy and your backend servers to achieve end-to-end encryption. Add the ssl parameter to the server lines in your backend section, which is where you define your pool of servers. In the example below, HAProxy establishes TLS connections to backend servers by using the ssl parameter. It also monitors them using the check parameter so that it can remove a server if it becomes unresponsive:

backend fix_servers
mode tcp
server server1 10.0.0.1:443 check ssl
server server2 10.0.0.2:443 check ssl
server server3 10.0.0.3:443 check ssl

HAProxy is built on the popular OpenSSL library, giving you a robust and vetted technology for encryption. That means that you don’t need to layer on additional proxies to gain TLS or build it into your application servers. Everything you need is built into HAProxy and can be enabled with a simple configuration.

Validation of Logon Messages

HAProxy 2.4 and HAProxy Enterprise 2.3 introduce a new configuration directive for validating the Logon (35=A) message that begins a FIX session. In the configuration snippet below, we inspect the message using the req.payload method and validate it with the fix_is_valid converter directive. Connections with an invalid Logon message are rejected and immediately closed:

frontend fix_listener
mode tcp
bind :443 ssl crt /etc/haproxy/certs/cert.pem ssl-min-ver TLSv1.2
tcp-request inspect-delay 1s
tcp-request content reject unless { req.len gt 0 } { req.payload(0,0),fix_is_valid }
default_backend fix_servers

Validation includes the following checks:

  • all tag IDs and their values are not empty and tag IDs are numeric

  • the BeginString tag is the first tag and it has a valid FIX version

  • the BodyLength tag shows the correct body length

  • the third tag is MsgType

  • the checksum in the message trailer is valid

You can also layer on additional checks, such as to verify that the SenderCompID, TargetCompID, or client IP address matches what you expect.

Route by Tag Value

You can use the fix_tag_value to extract the value of any tag from a FIX Logon message. This gives you the opportunity to route to a different pool of application servers based on, for instance, the SenderCompID or TargetCompID.

In the configuration snippet below, we leverage the use_backend directive to route to a pool named fixservers_a when the SenderCompID is firmA, and to fix_servers_b otherwise:

frontend fix_listener
# ...other listener settings...
tcp-request content set-var(txn.sendercompid) req.payload(0,0),fix_tag_value(SenderCompID)
use_backend fix_servers_a if { var(txn.sendercompid) -m str firmA }
default_backend fix_servers_b

This allows you to route to a different pool of application servers, which may utilize a different FIX engine, based on who the sender or target receiver is.

Client Certificate Authentication

With HAProxy in front of your application servers, you can authenticate clients using TLS client certificates. In this scenario, you give each client a certificate that you’ve digitally signed with your Certificate Authority, which allows you to know whether to trust the certificate that’s sent with a request by verifying its signature.

Setting up the verification of client certificates is straightforward. Simply set the verify parameter to required and set the path to your CA file with the ca-file parameter:

frontend fix_listener
mode tcp
bind :443 ssl crt /etc/haproxy/certs/cert.pem ssl-min-ver TLSv1.2 verify required ca-file /etc/haproxy/certs/ca.crt
# ...other listener settings...

Authentication with client certificates provides a simple but effective way to validate a client’s identity and restrict access to your FIX servers.

Matching Client IP Addresses

In some cases, you may want to accept connections from a client only if their IP address matches what you expect. This helps prevent unauthorized access. HAProxy allows you to map a company’s SenderCompID to an expected IP address by using our unique Map file feature. A Map file is a text file that stores key-value pairs. HAProxy can cross-check information in a request with a row from the file. Furthermore, you may want to restrict clients whose IP addresses are not in this list from connecting at all.

Consider a map file, which we will call sender_ips.map, that contains three rows, shown below:

172.16.0.2 ACMEFirm
172.17.1.5 AnotherFirm
172.17.2.0/24 YetAnotherFirm

Here, the first IP address is associated with the company ID ACMEFirm, while the second IP address is associated with the ID AnotherFirm. The third row maps a range of IP addresses to YetAnotherFirm. In your HAProxy configuration, you would look up the client’s IP address in the map file and cross-check the sender’s SenderCompID tag with the value in the file. If it doesn’t match, or if it isn’t found, you would reject the request.

frontend fix_listener
mode tcp
bind :443 ssl crt /etc/haproxy/certs/cert.pem ssl-min-ver TLSv1.2
tcp-request inspect-delay 1s
tcp-request content reject unless { req.len gt 0 } { req.payload(0,0),fix_is_valid }
tcp-request content set-var(txn.sendercompid) req.payload(0,0),fix_tag_value(SenderCompID)
tcp-request content set-var(txn.mapped_sendercompid) src,map_str(/etc/haproxy/maps/sender_ips.map)
# Reject connection if the IP was
# not found in the map file
tcp-request content reject unless { var(txn.mapped_sendercompid) -m found }
# Reject connection if the IP didn't
# match the one associated with the
# SenderCompID in the map file
tcp-request content reject unless { var(txn.sendercompid),strcmp(txn.mapped_sendercompid) eq 0 }

Map files support both single IP addresses and IP ranges.

Log Fix Tag Values

You can include values from the FIX Logon message in your HAProxy access logs. First, in your configuration, set an environment variable that stores the default log format for TCP connections:

global
setenv TCP_LOG "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq"

Then, define a new log format that adds onto this. Below, we capture the SenderCompID and TargetCompID values for each new connection:

frontend fix_listener
# ...other listener settings...
tcp-request content set-var(txn.sendercompid) req.payload(0,0),fix_tag_value(SenderCompID)
tcp-request content set-var(txn.targetcompid) req.payload(0,0),fix_tag_value(TargetCompID)
# Define a new log format
log-format "${TCP_LOG} %[var(txn.sendercompid)] %[var(txn.targetcompid)]"

You could also log errors that might come from validating or authenticating FIX clients. Considering the example of matching client IP addresses in a map file, you might record the specific error in a variable named errormessage:

frontend fix_listener
# ...other listener settings...
tcp-request content set-var(txn.errormessage) str("SenderCompID not found in map file") unless { var(txn.mapped_sendercompid) -m found }
tcp-request content set-var(txn.errormessage) str("SenderCompID not from expected IP") unless var(txn.sendercompid),strcmp(txn.mapped_sendercompid) eq 0 }
# Define a new log format
log-format "${TCP_LOG} %[var(txn.sendercompid)] %[var(txn.targetcompid)] %[var(txn.errormessage)]"

Conclusion

The Financial Information eXchange protocol has become the language of the finance world and it has revolutionized how institutions, traders, regulators, and automated systems communicate with each other. HAProxy 2.4 and HAProxy Enterprise 2.3 add support for it, enabling you to scale out your server infrastructure, validate messages, encrypt communication, implement intelligent routing, and authenticate clients.

Interested in learning more about HAProxy Enterprise? Contact us today.

Interested in seeing more content like this? Subscribe to our blog and follow us on Twitter. You can also join the conversation on our Slack.

Subscribe to our blog. Get the latest release updates, tutorials, and deep-dives from HAProxy experts.