January 17, 2024
|
3
min read

Introducing end-to-end HTTP/2 support from client to origin server

Blain Smith

The ever-evolving digital landscape continues to push for a single over-arching goal–speed. As technologies advance, the improvements reflect a growing demand for faster, more efficient, and more secure online experiences. With that in mind, we are excited to announce that ngrok now supports HTTP/2 end-to-end from client or origin server. This means you can now use HTTP/2-based protocols like gRPC through ngrok HTTP edges. This is a step toward opening up new possibilities of end-to-end streaming L7 protocol support and provides us with a solid foundation to build upon going forward.

A little, but long, history lesson

The industry specification for HTTP/2 has been around since 2015 and has greatly improved the way we browse the web. Before that, HTTP/1.1 allowed us to have things like reusable connections and extensions–hello, WebSockets! However, the spec was defined all the way back in 1997 with RFC 2068 and then touched up in 2022 with RFC 9112. Needless to say, HTTP/1.1 has gotten us very far in its lifetime.

 HTTP/2 changes the way we deliver content over the web. While it uses the same HTTP/1.1 message structure, HTTP/2 uses binary encoding, multiplexing, header compression, and stream prioritization to reduce latency and increase performance.

Each of those improvements combines to create a much more efficient process of passing data. The binary encoding and header compression work together to create smaller messages transmitted over the wire. The multiplexing and stream prioritization allow for multiple channels that can run in parallel and be prioritized by opening a single TCP connection and transmitting assets instead of continually opening and closing a TCP connection for each asset.

HTTP/2 at ngrok

At ngrok, our platform was always capable of accepting HTTP/2 requests for your origin server, but we had no way of knowing if your origin server supported receiving traffic over HTTP/2. Since most web servers and languages support both HTTP/1.1 and HTTP/2, it was a safe assumption on our part that when you started an HTTP connection, we would use the wildly common HTTP/1.1 first. So we always responded with HTTP/1.1 from our platform to your origin server. This made the developer experience nice and easy.

The client and server negotiate whether the connection can be upgraded to HTTP/2 in a variety of ways. We’ll talk about three negotiation types–direct, connection upgrade,  and Application Layer Protocol Negotiation (ALPN).

Direct (prior known): This is the simplest form of negotiation. Both client and server know that HTTP/2 is supported, so clients start off immediately sending HTTP/2 requests.

Connection Upgrade: HTTP/2 clients send Connection and Upgrade headers indicating they would like to start using HTTP/2. The server then needs to respond with code 101: Switching Protocols. This is similar to how WebSockets initialize. The downside is that the additional round-trip to request the upgrade from HTTP/1.1 to HTTP/2 adds latency. While this is a viable means of negotiating HTTP/2 there is less support for this because vendors are choosing to use ALPN as the primary form of negotiation.

Application Layer Protocol Negotiation (ALPN): This form of negotiation leverages TLS between the client and server. It allows the client and server to negotiate which application layer protocol–HTTP/1.1 or HTTP/2–during the initial TLS handshake. This is the most secure option because of the encryption used, but it is also more challenging from a proxy perspective. 

Since ngrok is a proxy between your clients and your origin server, our platform becomes a server for your clients and a client itself for your origin. Our Edge also handles all TLS termination for most HTTP connections to an origin server that does not have TLS configured. That is one of the benefits of ngrok. In order for our Edge to proxy requests to the agent and then to your origin, we do so over a non-encrypted connection using HTTP/2 Cleartext (h2c). Cleartext is standard, and ngrok provides robust security capabilities such as DDoS protection, IP restrictions, authentication, and authorization to protect origin servers.

Using HTTP/2 with ngrok

To start getting support for HTTP/2 to your origin server, we opted to start with the direct (prior known) method of negotiation to be explicit that you want HTTP/2 to be the protocol of choice between our Edge and your origin. When starting an HTTP connection with ngrok, you can specify this by adding a <code>--app-protocol</code> flag.

$ ngrok http 80 --app-protocol=http2

This will initiate an HTTP request and also instruct our Edge to always speak HTTP/2 with your origin. Now when clients make HTTP/2 requests to your origin, ngrok will forward the requests, retaining the HTTP/2 protocol, knowing that your upstream service will be able to handle the requests appropriately.

This is just an introduction to our support for HTTP/2. You can find more information about HTTP/2 support in our documentation.

What’s next?

We’re constantly working to add features to the ngrok platform. Now that we have laid the foundation for getting HTTP/2 from your clients to your origin server, we can build upon this to support the ALPN and Connection Upgrade negotiation methods. This also opens up the possibility to begin supporting higher-level HTTP/2 protocols like gRPC and other stream-based L7 application protocols as their own edge type, which could allow you to do things like protobuf decoding at the ngrok edge to make intelligent routing decisions based on information in the stream.

If you’d like to learn more about other features of the ngrok platform, I recommend some of the other awesome content from the ngrok blog:

If you have any questions, don’t hesitate to reach out. Connect with us on Twitter, the ngrok community on Slack, or contact us at support@ngrok.com. 

Share this post
Blain Smith
Blain Smith is a Staff Software Engineer at ngrok, working on their network edge team. His most recent work includes enabling HTTP/2 support as well as supporting their on-premise product. Blain has spent 3 decades working as a software engineer across financial, AAA gaming, networking, and IoT industries.