HAProxy community

Lua tcp-request content action timeout on core.sleep()

Hi,

I’m trying to read the first bytes (below 500 bytes) of a custom protocol to extract and log session identifying information. Since the client might be extremely slow to send the initial bytes I wanted to try and implement a while loop to read the first incoming message and tried with a very simple sleep to get started.

However this ends up with the message aborting Lua processing on expired timeout.

Is this type of thing generally not possible within a tcp-request content action?

test.lua

local function my_tcp_action(txn)
    txn.Info(txn, ">>> TCP ACTION")
    txn.Info(txn, ">>> request buffer not complete, waiting a second")
    core.sleep(10)
    txn.Info(txn, ">>> done sleeping")
    local request_buffer_content_len = txn.req:get_in_len()
    core.Debug(request_buffer_content_len)
    local request_buffer_content = txn.req:dup()
    core.Debug(tostring(request_buffer_content))
end

core.register_action('my_tcp_action', {'tcp-req'}, my_tcp_action, 0)

haproxy.cfg

global
  log stdout format raw local0
  tune.ssl.default-dh-param 2048
  ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:!aNULL:!MD5:!DSS
  ssl-default-bind-options ssl-min-ver TLSv1.2
  ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:!aNULL:!MD5:!DSS
  ssl-default-server-options ssl-min-ver TLSv1.2
  server-state-file global

  # lua settings
  tune.lua.session-timeout 30s
  lua-load /srv/lua/test.lua

defaults
  log               global
  retries                   3
  backlog               10000
  maxconn               10000
  timeout connect         30s
  timeout client          30s
  timeout server          30s
  timeout tunnel        3600s
  timeout http-keep-alive  1s
  timeout http-request    15s
  timeout queue           30s
  timeout tarpit          60s

frontend minimal_frontend
  bind *:55777 ssl crt /srv/crt/some_crt.pem tfo tls-ticket-keys /srv/crt/tls-ticket-keys
  mode tcp
  timeout client 10m
  option clitcpka
  tcp-request inspect-delay 30s
  tcp-request content accept if { req_ssl_hello_type 1 }
  use_backend minimal_backend

backend minimal_backend
  balance roundrobin
  mode tcp
  timeout server 10m
  tcp-request inspect-delay 30s
  tcp-request content lua.stratus_tcp_action
  server nc 127.0.0.1:6667 id 6667 weight 0

With the long tune.lua.session-timeout 30s I am able to run a while loop to wait for the bytes to trickle in but as soon as a core.sleep/core.msleep is involved the [ALERT] 125/084517 (6) : Lua function 'my_tcp_action': aborting Lua processing on expired timeout. error stops the action.

When I put a core.yield() the following error crashes haproxy:

A bogus STREAM [0x557bc1d85cf0] is spinning at 188177 calls per second and refuses to die, aborting now! Please report this error to developers [strm=0x557bc1d85cf0 src=127.0.0.1 fe=minimal_frontend be=minimal_backend dst=unknown rqf=0 rqa=480 rpf=80000000 rpa=0 sif=EST,200008 sib=INI,10 af=(nil),0 csf=0x557bc1d82d90,8200 ab=(nil),0 csb=(nil),0 cof=0x557bc1d28f30,80201306:PASS(0x557bc1d81320)/SSL(0x557bc1d73970)/tcpv4(36) cob=(nil),0:NONE((nil))/NONE((nil))/NONE(0) ]