HTTP/2 support using TLS offloading


#1

Hi,

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 127.0.0.1:443 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.


#2

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.

#3

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.


#4

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?


#5

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


#6

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:


#7

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.