Actions on server reject

I’m trying to proxy for a server that has its own anti-bot protection built-in - if the protection is triggered, it closes the connection with RST,ACK (as far as I’m aware it always does that after getting a request, e.g. TLS ClientHello). The proxy is transparent, and reuses source IP address.

I have a couple of issues handling that on my side:

  • I’d like to increase a per-src counter in my stick-table, so that I can reject the connections on the proxy side as well
  • I’d like the RST to be forwarded down to the client.

I tried to handle this with various combinations of tcp-response content and nbsrv, srv_is_up, but they don’t do what I’d expect in this case (looks like they’re only functional if monitoring is on?). I also tried setting up a backup server that just increases the counter and rejects the connection, but the backup server is never hit (again, due to monitoring not being on?).

I have a multiplex frontend with HTTP and HTTPS backends, and the HTTP proxy mainly returns an empty response (the upstream returns RST,ACK in response to the HTTP request), while the HTTPS proxy responds with 503 (the upstream returns RST,ACK during TLS handshake).

The case where haproxy just gracefully closes a client connection without any response is especially problematic, since I see that some browsers/clients respond to that by retrying the request.

Easy reproduction of the empty response from haproxy:

haproxy.cfg

listen repro
    mode http
    bind 127.0.0.1:1234
    server srv 127.0.0.1:1111

rstserver.py

import socket
import struct

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('0.0.0.0', 1111))
serversocket.listen(5)

while True:
    (s, addr) = serversocket.accept()
    s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
    s.close()