0th Root Secure Network (0SNet)

Exploring Application Layer Protocol Negotiation (ALPN)

A simple TLS extension to support different applications on a single port

Dorai Ashok S A
Geek Culture

--

Photo by Julius Jansson on Unsplash

The Internet protocol suite which forms the basis for modern Internet allows for different services to be provided by a single host. These services are assigned a port number and any connection to the port is assumed to be for that service. To give an example, the services http and https use the port numbers 80 and 443 respectively.

This allowed for good visibility on the network traffic, and its management. However, a new port number need to be used if protocol used by the service has changed and is not backward compatible. While HTTPS simply establishes a TLS session and runs HTTP on top of it, it uses port 443 instead of port 80.

This resulted in deployments where service running on https port would only handle TLS termination and pass the request to the same service that handles http. Or else, have the service running on http port to redirect requests to https service, as its one and only function.

Application Layer Protocol Negotiation — ALPN

The introduction of HTTP/2 improved the situation. HTTP/2 relies on TLS extension Application Layer Protocol Negotiation (ALPN) to use the same https port that provides HTTP/1.1 service over TLS. This works seamlessly, doesn’t incur any additional network latency, and doesn’t require any additional round trip or upgrade mechanism.

Once the connection is established with the server, TLS requires that the client send a ClientHello message. This message would include the extension application_layer_protocol_negotiation containing a list of protocol ids supported by the client. The server on the receiving end can either ignore the extension or choose a protocol and send it to the client as part of its ServerHello message.

The protocol id can be one of the registered ids, such as “http/1.1” for HTTP/1.1 and “h2” for HTTP/2. Once the TLS session is established, the agreed upon application protocol would be used by both client and server. To give an example, if client sends “h2” in its protocol list and server responds with “h2”, client should send HTTP/2 requests to server and not HTTP/1.1 requests, ie., even though https port is used.

TCP Port Service Multiplexer — TCPMUX

The idea of using a single port for multiple services is not new. As a matter of fact, port number 1 is assigned to a service named TCP Port Service Multiplexer (TCPMUX). A client can connect to port 1 and send ServiceName<CRLF>. The tcpmux service will respond with +Reason<CRLF> or -Reason<CRLF>. On a positive response, the client can initiate the protocol for the service, otherwise the connection is simply closed.

TCPMUX was deprecated. However, we can get similar functionality with ALPN. It is possible for non-HTTP TLS clients to send ALPN request for a service which the server can either accept or deny. Do note, ALPN does define a fatal alert no_application_protocol for the deny case.

However, there isn’t any single port assigned for ALPN to connect to the service that one wishes. Even if there was, there are drawbacks which one can learn from TCPMUX deprecation, such as reduced maximum number of connections between two machines and complicated firewall management.

ACME

Another major use of ALPN is in automated certificate issuance. It was discovered in early 2018 that the SNI based method used by Automatic Certificate Management Environment (ACME) protocol, for domain validation over https port, was insecure. This prompted a new challenge method for domain validation over ALPN.

ALPN protocol id “acme-tls/1” is assigned for this purpose. A supporting client and server will use “acme-tls/1” in ALPN extension to perform the domain validation. An interesting fact to note is, there is no application data.

The protocol consists of a TLS handshake in which the required validation information is transmitted. The “acme-tls/1” protocol does not carry application data. Once the handshake is completed, the client MUST NOT exchange any further data with the server and MUST immediately close the connection.

nginx configuration

On the practical side of things, it is possible to configure proxy servers to route traffic to respective services based on ALPN. With nginx one can use the stream_ssl_preread_module and map ALPN protocol ids to their corresponding upstream service.

stream {
map $ssl_preread_server_name $x_name {
hostnames;
default 10.0.3.11:443;
}
map $ssl_preread_alpn_protocols $x_up {
~\bacme-tls/1\b 127.0.0.1:10443;
default $x_name;
}
server {
listen 443;
proxy_pass $x_up;
ssl_preread on;
}
}

The sample configuration shown above can be used to setup a proxy based on both ALPN protocol id and server name (SNI). It maps the protocol id “acme-tls/1” to a local service 127.0.0.1:10443 and all other application protocols to a map based on server name. Do note, the TLS termination will be on the upstream server.

With the introduction of ALPN, the term over https can have a new meaning. As one can make pretty much any service available on https port, as long as the client supports ALPN. This provides a lot of flexibility. And, as the support for ALPN becomes wide spread, we will likely see its true potential.

References:

  1. ALPN, https://tools.ietf.org/html/rfc7301
  2. TCPMUX, https://tools.ietf.org/html/rfc1078
  3. TLS-ALPN-01, https://tools.ietf.org/html/rfc8737

At 0th Root, we provide a solution 0th Root Secure Network — 0SNet to secure organization’s internal web apps with TLS client certificates. Do check out our product, it is easy to deploy and available as images on AWS, GCP and Azure.

--

--

Dorai Ashok S A
Geek Culture

Engineer, at heart! Founder of 0th Root. I write on topics related to Internet Architecture and Security