envoy as http 2 front proxy – enabling http 2 for envoy (aka h2)
Out of the box envoy is not configured to set up connections with clients connecting to it with the new HTTP/2.
HTTP/2 is optimized for the modern web, with binary headers, etc. – higher speed.
Since envoy is capable of speaking HTTP/2 to clients, it is a no-brainer to set it up.
And the setup is really easy, too. You just add one line in the common_tls_context of your listener:
alpn_protocols: [ "h2,http/1.1" ]
That’s it. (The quotes should be normal quotes, in case WordPress messes these up)
ALPN stands for Application-Layer Protocol Negotiation – it is apparently needed for HTTP/2 to work.
By default, the http_connection_manager envoy filter will support both HTTP1 and HTTP2 in the mode AUTO.
By adding the alpn_protocols you allow this functionality to actually be used.
My envoy.yaml for your reference
I’m going to reproduce my entire envoy.yaml so you see the context the line has to be put in:
static_resources:
listeners:
– address:
socket_address:
address: 0.0.0.0
port_value: 80
filter_chains:
– filters:
– name: envoy.http_connection_manager
config:
codec_type: auto
stat_prefix: ingress_http
route_config:
virtual_hosts:
– name: backend
domains: [“*”]
routes:
– match: { prefix: “/” }
redirect:
path_redirect: “/”
https_redirect: true
http_filters:
– name: envoy.router
config: {}
– address:
socket_address:
address: 0.0.0.0
port_value: 443
filter_chains:
– tls_context:
common_tls_context:
tls_certificates:
– certificate_chain: { filename: “/etc/example-com.crt” }
private_key: { filename: “/etc/example-com.key” }
alpn_protocols: [ “h2,http/1.1” ]
filters:
– name: envoy.http_connection_manager
config:
stat_prefix: ingress_https
route_config:
virtual_hosts:
– name: backend
domains: [“*”]
routes:
– match: { prefix: “/” }
route: { cluster: target_taxgod }
http_filters:
– name: envoy.router
config: {}
clusters:
– name: target_taxgod
connect_timeout: 0.25s
type: strict_dns
lb_policy: round_robin
hosts:
– socket_address:
address: taxgod
port_value: 3000
admin:
access_log_path: “/tmp/envoy.log”
address:
socket_address:
address: 0.0.0.0
port_value: 9901
This envoy.yaml listens on port 80 and port 443. HTTP requests to port 80 are redirected to port 443. All traffic is sent to a docker container “taxgod” on the same docker network. Refer to this article by me for details.
Please don’t expect copy pasting this whole thing to work – WordPress unfortunately is too clever for it’s own good sometimes, and messes up all kinds of characters and code formatting.
References:
- https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation
- https://www.envoyproxy.io/docs/envoy/latest/api-v2/config/filter/network/http_connection_manager/v2/http_connection_manager.proto#enum-config-filter-network-http-connection-manager-v2-httpconnectionmanager-codectype
- https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/ssl.html?highlight=common
- https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/auth/cert.proto.html?highlight=common#auth-commontlscontext –> I got the information how to set alpn properly (where to put it in the configuration file, and what to put inside it) up from here
- https://github.com/envoyproxy/envoy/issues/3394 –> this got me started in the right direction. I had never heard of ALPN before I read this.