Hi Karol, On Thu, Jun 11, 2026 at 02:20:23PM +0200, Karol Kucharski wrote: > Hi, > > I tested a simple configuration with connecting to a tls backend server > using kTLS. > > haproxy.cfg > ``` > global > expose-experimental-directives > > defaults > mode tcp > timeout connect 5s > timeout client 30s > timeout server 30s > > frontend my_frontend > bind *:8080 > use_backend my_backend > > backend my_backend > server my_server 10.1.0.3:4043 ssl verify none ktls on force-tlsv12 > ``` > > I've noticed that when connecting to a backend server on loopback > (server my_server 127.0.0.1:4043 ...) HAProxy always enabled kTLS, > but when connecting to an external address it often failed to do so. > > I did some digging and it turns out that after calling connect() on a > socket, > HAProxy immediately calls setsockopt(..., TCP_ULP, "tls", ...) > > Linux tls module requires the socket to be in TCP_ESTABLISHED state: > https://elixir.bootlin.com/linux/v7.0.12/source/net/tls/tls_main.c#L1059-L1066 > > If a SYN+ACK packet from the server don't arrive in time when we call > setsockopt(), it will fail with ENOTCONN error. > > I've tested on HAProxy 3.4.0 with OpenSSL 3.5.6 and AWS-LC 5.0.0 > > strace > ``` > 3947 socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 156 > 3947 fcntl(156, F_SETFL, O_RDONLY|O_NONBLOCK) = 0 > 3947 setsockopt(156, SOL_TCP, TCP_NODELAY, [1], 4) = 0 > 3947 connect(156, {sa_family=AF_INET, sin_port=htons(4043), > sin_addr=inet_addr("10.1.0.3")}, 16) = -1 EINPROGRESS (Operation now in > progress) > 3947 setsockopt(156, SOL_TCP, TCP_ULP, [7564404], 4) = -1 ENOTCONN > (Transport endpoint is not connected) > 3947 recvmsg(155, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base=" > make teardown-iface \342\200\224 prz"..., iov_len=1024}], > msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 1024 > 3947 epoll_ctl(148, EPOLL_CTL_ADD, 156, > {events=EPOLLIN|EPOLLOUT|EPOLLRDHUP, data={u32=156, u64=156}}) = 0 > 3947 clock_gettime(CLOCK_THREAD_CPUTIME_ID, {tv_sec=0, > tv_nsec=4370772}) = 0 > 3947 epoll_wait(148, [{events=EPOLLOUT, data={u32=156, u64=156}}], 200, > 0) = 1 > ``` [...] > > I've moved the setsockopt(..., TCP_ULP, "tls", ...) call just before > configuring the kTLS keys and it resolved the issue for me. > > I've also tested the change on another system with kTLS disbled and > HAProxy > properly falls back to software tls.
Thanks a lot! Your analysis and patch sound entirely correct to me, so I just pushed it, only slightly altered. Regards, Olivier

