HAProxy community

How to extend Haproxy with Lua

Hi. I’m trying to follow this article: https://www.haproxy.com/blog/5-ways-to-extend-haproxy-with-lua/

I’ve cloned haproxy from github and compiled it myself with:
make -j $(nproc) TARGET=linux-glibc USE_OPENSSL=1 USE_ZLIB=1 USE_LUA=1 USE_PCRE=1 USE_SYSTEMD=1

I’ve copied the code from the article and it doesn’t work for me. This is the example function:

core.register_fetches("greater_than", function(txn, var1, var2)
    local number1 = tonumber(txn:get_var(var1))
    local number2 = tonumber(txn:get_var(var2))
    if number1 > number2 then return true
    else return false end
end)

But I’m getting this error:

ua sample-fetch ‘greater_than’: runtime error: /home/user/projects/haproxy/hlib.lua:17: bad argument #1 to ‘Debug’ (string expected, got nil) from [C] field ‘Debug’, /home/user/projects/haproxy/hlib.lua:17 C function line 13.
[ALERT] 329/141214 (32243) : Lua sample-fetch ‘greater_than’: runtime error: /home/user/projects/haproxy/hlib.lua:17: bad argument #1 to ‘Debug’ (string expected, got nil) from [C] field ‘Debug’, /home/user/projects/haproxy/hlib.lua:17 C function line 13.

Can somebody explain why this article is off? It was written on May 24, 2019, so not that long ago. Am I doing something wrong?

First, I guess you have not executed this lua script, because there is no call to core.Debug(). Then, here, the error reported is that you try to print a nil variable (probably number1 or number2).
In the provided example, var1 and var2 must exist.

This is how I’m calling the method:

http-request deny if { lua.greater_than(txn.conn_rate,txn.connrate_threshold) -m bool }

Are the txn.* values nill?

Oh… I didn’t understand your reply. There is a call to core.Debug(), but I didn’t paste the entire log. This would be it:

[debug] 330/083747 (13688) : Hello HAProxy!.
Proxy http_front started.
Proxy fallback_api started.
Lua sample-fetch ‘greater_than’: runtime error: /home/user/projects/haproxy/hlib.lua:19: attempt to compare two nil values from /home/user/projects/haproxy/hlib.lua:19 C function line 13.
[ALERT] 330/083750 (13688) : Lua sample-fetch ‘greater_than’: runtime error: /home/user/projects/haproxy/hlib.lua:19: attempt to compare two nil values from /home/user/projects/haproxy/hlib.lua:19 C function line 13.

So it means the both variables are undefined (nil in lua). This script does not handle this case, because it is just an example. By reading the blog, I saw these variables are set before calling the script. The first one to a constant value :

http-request set-var(txn.connrate_threshold) int(100)

The second one to the connection rate, coming from a stick table :

stick-table type ip size 1m expire 10s store conn_rate(10s)
http-request track-sc0 src
http-request set-var(txn.conn_rate) src_conn_rate

Are you sure these variables are set ?

You are correct. I was missing set-var lines. The example now works. Thanks.

Do you maybe have an idea how would I get the value of ssl_c_der (base64 or not) into a lua variable (as a function argument)?

Got it!

http-request set-header X-SSL-ClientCertDER %{+Q}[ssl_c_der,base64]
http-request set-var(txn.cert_der) req.hdr(X-SSL-ClientCertDER)
http-request deny if { lua.test_method(txn.cert_der) -m bool }