HTTP/2 support using TLS offloading


I’ve been using haproxy as a LB for years now in production.

Since we currently use a HTTP/2 webserver just as a proxy, it makes sense to try and use haproxy for this protocol as well.

Since there have been quite a few h2-related fixes even in the latest 1.8.13 release, we’d like to use the H2 support in a test basis.

For HTTP/2 we already have a “mode tcp” TLS offloading in a few processes, passing through a unix-socket backend.

We’d like to use another unix-socket for the H2 haproxy for 10% of our traffic, such as:

frontend h2-tls
    bind ssl crt /var/haproxy/certs alpn h2,http/1.1,http/1.0
    mode tcp
    default_backend tls-clean

backend tls-clean
    mode  tcp
    balance static-rr
    server original /var/run/original.sock weight 90
    server h2-haproxy /var/run/h2-haproxy.sock weight 10

frontend h2-clean
    bind unix@/var/run/h2-haproxy.sock
    default_backend ....

This doesn’t seem to we working, though.

Is there any plans to support this? Or is the http/2 support really an all-or-nothing approach?

If it is, we can probably do a L4 routing to 2 different layers, but we’ll have to duplicate the TLS offloading part, which will add quite a few memory usage in our case (We have over 3.000 certs), which is not ideal.

If we go the “just use another layer” approach, my main problem is that we have 2 new problems:

  • If we use unix socket/abstract socket for that new http2 tls-encrypted frontend, we’ll lose the SO_REUSEPORT, which then lose the fairness between the offload processes;
  • If we use a localhost:port approach (to gain SO_REUSEPORT), we’ll introduce AF_INET traffic in the loopback interface for essentially all our H2 traffic…which creates a lot of extra noise in our monitoring system (we capture all AF_INET/AF_INET6 traffic to monitor for network problems/latency/instability), not to mention the extra load on a local machine.

No, you can’t announce and negotiate H2 via ALPN, and then not do it. I don’t think you can negotiate http/1.0 in ALPN, btw.

You would have to create separate sockets and bind it to a specific process, then load-balance on the earlier layer.

I don’t have a suggestion other than excluding the loopback interface or its IP range from the capture.

The extra load is probably negligible, unless you have a huge traffic volumes. You can also enable splicing in your first layer, so the traffic is short-circuited in the kernel when it makes sense.

Hi Lukas!

Thank you for answer! :slight_smile:

Is there any plans for 1.9 to implement H2 using HTTP?

I saw an encouraging series today around 8ed0a3e32a90af08a23ca8ab79d52d5d30666780 which I think would indicate it will/would be possible in 1.9 to receive HTTP/2 traffic in a clean (non-TLS) connection.

Do you know anything about this?

I don’t know, but I don’t see how this would solve the issue you are facing?

Because that’s our problem right now: We have a frontend in TCP mode just for TLS Offloading (using SO_REUSEPORT with 12 processes)…passing the clean data through a unix socket to another frontend where we do all our processing (in another process, of course).

This “clean” frontend is in HTTP mode, though it doesn’t handle H2 traffic like I thought…that’s what I asked (or tried to) originally :slight_smile:

Ok, but even if we would support h2c, you would need to enable it for all the traffic, not just some, because if ALPN negotiates it, you need to handle it.