3

I have a tomcat 9.0.2 server supporting HTTP/2 and running on TLS1.2. Below is the connector configuration in server.xml

<Connector port="8443" protocol="org.apache.coyote.http11.Http11Nio2Protocol"
    address="0.0.0.0"
    maxThreads="150" SSLEnabled="true" asyncTimeout="10000" maxHeaderCount="50"
    maxPostSize="1048576" scheme="https" secure="true" compression="force" 
    compressionMinSize="2048" maxConnections="10000">
    <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
    <SSLHostConfig protocols="TLSv1.2">
        <Certificate certificateKeystoreFile="${keystore.file.path}"
            certificateKeystorePassword="${keystore.password}"
            certificateKeyAlias="${server.cert.alias}"
            certificateKeystoreType="${keystore.type}" />
    </SSLHostConfig>
</Connector>

I am using HA Proxy 1.8 and configuration is like below

frontend  mydomain-ux
  mode    http
  bind    <ip>:8080 ssl crt /etc/certs/mydomain.com.cert.pem
  http-request set-var(txn.path) path
  acl mydomain hdr_end(host) -i mydomain.com
  use_backend mydomain_server if mydomain  

backend  mydomain_server
  mode    http
  server  mydomain_backeend_server <server-ip>:8443 ssl

Since, I have multiple backends based on host, I cannot use TCP mode and do pass through HTTP/2 SSL termination

Is there a way I can have HTTP/2 termination in backend mode http ?

Geshode
  • 3,600
  • 6
  • 18
  • 32
Chaitanya
  • 201
  • 2
  • 9

2 Answers2

4

As far as I'm aware HAProxy does not support HTTP/2 on the back end. They only recently announced front end support. (Edit 18th Jan 2019 - since added in v1.9 - https://www.haproxy.com/blog/haproxy-1-9-has-arrived/).

Even without backend HTTP/2 support, it is possible to terminate the front end on HTTPS, and then forward to the back end on TCP (without HTTPS), and it may be possible to use the SNI part of the HTTPS to do the optional routing you want (this is completely untested btw):

frontend  mydomain-ux
  mode    tcp
  bind    <ip>:8080 ssl crt /etc/certs/mydomain.com.cert.pem alpn h2,http/1.1
  use_backend     mydomain_server      if { ssl_fc_sni mydomain.com}
  use_backend     mydomain_server2     if { ssl_fc_sni mydomain2.com }
  default_backend mydomain_server

backend  mydomain_server
  mode    tcp
  server  mydomain_backeend_server <server-ip>:8081

This would allow your backend to speak HTTP/2 on port 8081 but without HTTPS (port 8443), and even works on HAProxy before 1.8 (when front end HTTP/2 support was added). However it would mean your Tomcat would need to be setup without SSL.

HAProxy also do not recommend using the SNI host for routing as discussed in this answer and in the the mailing thread it refers to. Plus additionally SNI support is not universal (though to all practical intents it is unless supporting really old browsers like IE8 on XP).

The other question you should ask yourself is if you really need HTTP/2 in the backend or if just supporting this at the HAProxy level is enough?

Barry Pollard
  • 40,655
  • 7
  • 76
  • 92
  • Based on recommendations, i will wait until there is serious need of HTTP/2 at backend servers. Accepted the answer but I am not trying the prescribed configuration as of now. – Chaitanya Jan 27 '18 at 15:01
  • Yup that’s what I’d recommend. And when there is a serious need, HAProxy will probably support it natively on the back end. Above is a bit of a hack to be honest. – Barry Pollard Jan 27 '18 at 15:58
  • 1
    haproxy 1.9 was released and supports HTTP/2 on the backend https://www.haproxy.com/blog/haproxy-1-9-has-arrived/ > Once turned on, you can use HTTP/2 to your backend servers. Add alpn h2 to a server line (or alpn h2,http/1.1 if you prefer to let HAProxy negotiate the protocol with the server). – jmoney Jan 18 '19 at 16:52
  • Thanks. Updated answer to reflect this. – Barry Pollard Jan 18 '19 at 16:55
0

I have done a full h2 pipe base on the previous post by Barry Pollard with some modification and It's work good enough to be use in dev for now. Some futher test are need to clear the path to production. But at least its work.

h2 clear text (h2c) is'nt supported by browser as google want everybody to use ssl but it works fine between 2 httpd server (tested with apache, but not with nginx or tomcat or whatever else httpd).

frontend  mydomain-ux
  mode    tcp
  bind    0.0.0.0:443 ssl crt /etc/ssl/tdl.pem  alpn h2,h2c,http/1.1
  bind    0.0.0.0:80  alpn h2,h2c,http/1.1
  use_backend     mydomain_server     if { ssl_fc_alpn -i h2 }
  default_backend mydomain_server

backend  mydomain_server
  mode    tcp
  http-request add-header X-Forwarded-Proto https
  server  mydomain_backeend_server 1.1.1.1:80
  server  mydomain_backeend_server2 1.1.1.2:80

here is what i can see from the backend access_log:

1.1.1.3 - - [17/Jan/2019:10:57:49 -0500] "GET / HTTP/2.0" 403 3985 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"

wyzeman
  • 89
  • 4