'stick': unknown fetch method 'res.cook_reg'


#1

HAproxy gurus

I have a stick table based on JSESSIONID and it works well with apps that actually use a cookie by that name.
However, oracle webcenter uses 2 differently named cookies

WCC-ADF-JSESSIONID
_WL_AUTHCOOKIE_WCC-ADF-JSESSIONID

The following matches both and thus sticks both into the stick table

stick store-response res.cook(WCC-ADF-JSESSIONID)
stick match req.cook(WCC-ADF-JSESSIONID)

  1. It should not store the second one imho as the match is documented as “exact string”
  2. The following should work afaict
    stick store-response res.cook_reg(^WCC-ADF-JSESSIONID$)
    stick match req.cook_reg(^WCC-ADF-JSESSIONID$)

but causes haproxy to barf

[ALERT] 248/160853 (26241) : parsing [/usr/local/etc/haproxy.cfg:131] : ‘stick’: unknown fetch method ‘res.cook_reg’
[ALERT] 248/160853 (26241) : parsing [/usr/local/etc/haproxy.cfg:132] : ‘stick’: unknown fetch method ‘req.cook_reg’
[ALERT] 248/160853 (26241) : Error(s) found in configuration file : /usr/local/etc/haproxy.cfg
[ALERT] 248/160853 (26241) : Fatal errors found in configuration.

I thought I might not have compiled pcre so I did that again to be sure:

make TARGET=linux2628 USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1
[root@devpxyc01n01 ~]# rpm -q pcre-devel
pcre-devel-8.32-17.el7.x86_64
[root@devpxyc01n01 ~]# ldd /usr/local/sbin/haproxy | grep pcre
libpcreposix.so.0 => /lib64/libpcreposix.so.0 (0x00007f082e3a4000)
libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f082e142000)

I need to explicitly match WCC-ADF-JSESSIONID only.

Any help would be appreciated.

Thx


#2

Forgot the version. HA-Proxy version 1.8.13


#3

You can’t stick on two cookies. But why so complicated anyway? I assume the only thing you need to accomplish is stickiness, so I’d suggest you have haproxy set a dedicated cookie for this, without relaying on the application cookies and without the need for any stick tables.

You can read more about it here (Session cookie setup by the Load-Balancer):


#4

lukastribus

Thanks for the response. You misunderstood. I don’t want to match both cookies but HAProxy does.
That is the issue. The res.cook and req.cook methods don’t do exact matching but rather substring matching, which is undesired here since one cookie contains the other in its name. If I have 2 cookies
COOKIE1
COOKIE12

there should be a way to match COOKIE1 explicitly either via word boundary ‘\bCOOKIE1\b’ or regex ‘^COOKIE1$’.

I know I can insert cookies but it would be nice to use the existing jsession cookie’s lifetime for persistence.
And, to be honest, at this point I’m just curious whether you can match a cookie name by regex rather than string with “stick”. It seems impossible and I’d like to know if that is indeed a current limitation.

thx
thx


#5

Ok, I understand what you mean now, however I’m unable to reproduce this issue.

I setup a php script which basically sets both cookies:

<?php
setcookie('_WL_AUTHCOOKIE_WCC-ADF-JSESSIONID', "wrong long cookie");
setcookie('WCC-ADF-JSESSIONID', "realshortcookie");
?>

Running this through haproxy with the following config in the backend (and a stats socket /tmp/haproxy.stats level admin in the global section):

stick-table type string len 32 size 204800
stick store-response res.cook(WCC-ADF-JSESSIONID)
stick match req.cook(WCC-ADF-JSESSIONID)

And when I run the request through it:

0000004a:port80.accept(0007)=000b from [10.0.0.4:61009] ALPN=<none>
0000004a:port80.clireq[000b:ffffffff]: GET /dualcookie.php HTTP/1.1
0000004a:port80.clihdr[000b:ffffffff]: Host: dev.lan.ltri.eu
0000004a:port80.clihdr[000b:ffffffff]: User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0
0000004a:port80.clihdr[000b:ffffffff]: Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
0000004a:port80.clihdr[000b:ffffffff]: Accept-Language: de,en;q=0.8,it;q=0.5,en-US;q=0.3
0000004a:port80.clihdr[000b:ffffffff]: Accept-Encoding: gzip, deflate
0000004a:port80.clihdr[000b:ffffffff]: DNT: 1
0000004a:port80.clihdr[000b:ffffffff]: Connection: keep-alive
0000004a:port80.clihdr[000b:ffffffff]: Upgrade-Insecure-Requests: 1
0000004a:port80.clihdr[000b:ffffffff]: Cache-Control: max-age=0
0000004a:my-backend.srvrep[000b:000c]: HTTP/1.1 200 OK
0000004a:my-backend.srvhdr[000b:000c]: Server: nginx/1.10.3 (Ubuntu)
0000004a:my-backend.srvhdr[000b:000c]: Date: Sat, 08 Sep 2018 12:05:23 GMT
0000004a:my-backend.srvhdr[000b:000c]: Content-Type: text/plain; charset=utf-8
0000004a:my-backend.srvhdr[000b:000c]: Transfer-Encoding: chunked
0000004a:my-backend.srvhdr[000b:000c]: Connection: keep-alive
0000004a:my-backend.srvhdr[000b:000c]: Set-Cookie: _WL_AUTHCOOKIE_WCC-ADF-JSESSIONID=wrong+long+cookie
0000004a:my-backend.srvhdr[000b:000c]: Set-Cookie: WCC-ADF-JSESSIONID=realshortcookie

The table contains only the exact cookie match:

lukas@dev:~$ echo "show table my-backend" | sudo socat unix-connect:/tmp/haproxy.stats stdio
# table: my-backend, type: string, size:204800, used:1
0x2006204: key=realshortcookie use=0 exp=0 server_id=1
lukas@dev:~$

It does not contain the _WL_AUTHCOOKIE_WCC-ADF-JSESSIONID cookie at all. If the php script does not set the WCC-ADF-JSESSIONID cookie (only the other cookie), the table remains completely empty.

So I can absolutely not reproduce the issue, it’s an exact string match for me.

Are you sure your table does not contain values from older tests, maybe you have peers configured so that the tables are synched back?

Can you show the entire configuration and the output of haproxy -vv?

Regarding the cookie regexp matches, it seems nonfunctional to me. But I also fail to see the real use-case. This probably never worked correctly; I assume there is no actual use-case for this, so I’m not sure if it’s worth the effort to fix it or (if it never worked in the first place) if it’s time to remove this functionality.


#6

Luka
Thank you for your efforts. I figured out what’s really going on.
Turns out when you hit the login page you only get WCC-ADF-JSESSIONID. If you log in successfully 2 things happen:

  1. You also get _WL_AUTHCOOKIE_WCC-ADF-JSESSIONID
  2. The content of WCC-ADF-JSESSIONID is changed !!!

Initially when I looked at the stick table I assumed both entries were from the 2 respective cookies. Then I saw the cook_reg option and got hung up on the idea of being able to match a cookie name by regex so I went down this rabbit hole.
In reality ha proxy adds a new stick entry because the original cookie’s content changes. So now you have one expiring entry and one live entry but for the same cookie.
In other words you are right…the match is exact as advertised. Sorry about that confusion.

So regarding the acl derivatives this is just a matter of cleaning up the docs ?
F.e. since I cannot persist via more than one cookie why would I use cook_beg for prefix match ?
Then again I find it hard to believe that the docs are that grossly misguiding. I’m curious about this section from https://cbonte.github.io/haproxy-dconv/1.8/configuration.html

ACL derivatives :
cook([]) : exact string match
cook_beg([]) : prefix match
cook_dir([]) : subdir match
cook_dom([]) : domain match
cook_end([]) : suffix match
cook_len([]) : length match
cook_reg([]) : regex match
cook_sub([]) : substring match

Thank you for your support !


#7

Well the code is there, and fetches like cook_reg are accepted in ACLs, in my quick test yesterday it did not work as expected though.

I need to take a closer look at what works exactly and what doesn’t.

That would be for ACL’s, not stick tables.