Matching TCP payloads is not working

OK, so I have a TCP application where the client sends a string as soon as it connects. I want to direct the client to a different backend depending on the content of that string. The string can vary in length between 330 - 420 characters or so (it’s a line of JSON).

I am working with a config like this:

frontend TEST_front
   bind *:51090
   mode tcp
   tcp-request inspect-delay 5s
   tcp-request content accept if WAIT_END
   option tcplog
   acl testacl payload(0,400) -m sub lon
   use_backend TEST_back_2 if testacl
   use_backend TEST_back

So, this works if the string “lon” is found in the first 400 characters and the line is 400 characters or longer. (and yes, I’ve tried using “req.payload(0,400)”, same thing. If the line is less than 400 characters, it does NOT set the ACL to “true”.

Since I never know exactly how long the line will be, or where in the line the text will appear, I am not able to get this to work consistently. I have also tried payload(0,0), but that does not seem to work either.

Any suggestions?


If anyone can assist with this, I am willing to pay/hire them to find a working config.


If I boil this down, it seems that payload(0,0) just returns an empty string. I can successfully search for a string when I use “payload(0,X)” where X <= the length of the initial string. If X > the string length, instead of returning the string it saw, it returns nothing.

Would there maybe be a way to populate a variable in advance with the length of the initial string? Or some way to get payload(0,0) to work as expected?

Is your content binary, payload(0,0) should work. The only thing i can think of is that you have binary content which haproxy is having problems with, since you’re doing a substring match.
Try hexadecimal instead:

# Hexadecimal mode
acl testacl payload(0,0),hex -m sub 6c6f6e   # hex of lon

The comparison stops at a null byte (00) in the payload - (at least up to the current version 2.2.0dev1). If you want to be sure you use the whole payload, use the solution from @gagan_goku - convert the payload into a hexified string. I am not sure if your pattern needs to have the [a-f] in big caps.