TLS/Gateway: http2 error: Invalid HTTP header field was received: name: [:authority], value: [foo.bar.example.com]

Firefox and curl errors out when retrieving a HTTP2 service proxied through a Gateway with TLS enabled.

Notes:

  • Services configured the same way which are not HTTP2 work fine over TLS
  • Accessing the app without TLS works
  • curl -v reveals the error in the title (Invalid HTTP header)
  • The app itself is PHP served with php -S (for development & testing purposes); Serving it another way for my use case is not an option.

I suspect if I can fix the CURL error, then Firefox will start working, but how can I fix it?

Below is both the Gateway config, and below that is the output of curl:

apiVersion: v1
items:
- apiVersion: networking.istio.io/v1beta1
  kind: Gateway
  metadata:
    creationTimestamp: "2020-05-26T15:52:09Z"
    generation: 1
    labels:
      app: foo-bar-example-com
      sid: d3beb6c1-9f68-11ea-a953-42010a675002
    name: foo-bar-example-com
    namespace: hd-proxies
    resourceVersion: "5752999"
    selfLink: /apis/networking.istio.io/v1beta1/namespaces/hd-proxies/gateways/foo-bar-example-com
    uid: 53052450-c7dc-4449-a261-14c845f7dea1
  spec:
    selector:
      istio: ingressgateway
    servers:
    - hosts:
      - foo.bar.example.com
      port:
        name: http
        number: 80
        protocol: HTTP
    - hosts:
      - foo.bar.example.com
      port:
        name: https
        number: 443
        protocol: https
      tls:
        credentialName: example-tls
        mode: SIMPLE
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""

Here’s the curl request:

$ curl -v https://foo.bar.example.com/
*   Trying 104.151.51.10...
* TCP_NODELAY set
* Connected to foo.bar.example.com (104.151.51.10) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=example.com
*  start date: May 16 06:45:05 2020 GMT
*  expire date: Aug 14 06:45:05 2020 GMT
*  subjectAltName: host "foo.bar.example.com" matched cert's "*.bar.example.com"
*  issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7f843b00d600)
> GET / HTTP/2
> Host: foo.bar.example.com
> User-Agent: curl/7.64.1
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 4294967295)!
* http2 error: Invalid HTTP header field was received: frame type: 1, stream: 1, name: [:authority], value: [foo.bar.example.com]
* HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)
* stopped the pause stream!
* Connection #0 to host foo.bar.example.com left intact
curl: (92) HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)
* Closing connection 0