How to Do mTLS With Kong Behind AWS Application Load Balancer

What is mTLS

API security is more important than ever as organizations rely on them to power critical applications and services. Among the available authentication methods, mutual TLS (mTLS) is widely recognized as one of the strongest and most reliable solutions.

As shown in the diagram below, mTLS builds on the TLS handshake by requiring both the client and server to present certificates, ensuring a two-way authenticated connection. This two-way verification significantly reduces the risk of unauthorized access, man-in-the-middle attacks. For industries handling sensitive data or facing strict regulatory requirements, storing certificates on hardware tokens enhances the security of mTLS, making it more secure than most other authentication methods.

Kong Enterprise offers a dedicated plugin to support mTLS. The mTLS plugin simplifies the implementation of mTLS for enterprise users. To understand how to use this plugin, please check this blog post.

L4 Limitation

While mTLS offers superior security, its implementation comes with certain constraints that can affect the flexibility of modern API architectures. The primary challenge lies in the fact that mTLS authentication occurs during the TLS handshake at the transport layer (Layer 4) of the OSI model. Since mTLS authentication occurs at this layer, users are limited to using Layer 4 load balancers, which simply pass the TLS handshake through to Kong, as depicted in the diagram below.

This limitation can be problematic for users who want to take advantage of Layer 7 load balancers, like the AWS ALB, which supports advanced features such as integration with AWS WAF and certificate management via AWS Certificate Manager (ACM).

Solution

The AWS ALB supports mTLS in two modes:

  • Verify Mode: ALB not only terminates the TLS connection but also verifies the client certificate, ensuring it was issued by a trusted CA and checking revocation lists, among other tasks.
  • Passthrough Mode: ALB handles the TLS handshake with the client and, if a client certificate is presented, forwards the full certificate to backend services in the X-Amzn-Mtls-Clientcert header. In this mode, the backend (e.g., Kong) is responsible for validating the certificate.

In the Kong Enterprise 3.8, a new plugin header-cert-auth is introduced to support AWS LB passthrough mode.

This approach effectively splits the mTLS process:

  1. The ALB handles TLS termination
  2. Kong authenticates the certificate forwarded in the header from ALB.

Here is an example of the ALB HTTPS listener configuration, where mutual authentication is enabled in passthrough mode.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
resource "aws_lb_listener" "kong_https" {
load_balancer_arn = aws_lb.kong_lb.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS-1-2-Ext-2018-06"
certificate_arn = aws_acm_certificate.alb_cert.arn

default_action {
type = "forward"
target_group_arn = aws_lb_target_group.kong_https_tg.arn
}

mutual_authentication {
mode = "passthrough"
ignore_client_certificate_expiry = false
}
}

The configuration of this plugin is similar to the mTLS plugin. You’ll need to create CA certificate objects in Kong to validate the incoming client certificate. Additionally, you can specify the request header where the certificate will be appended, and whether it will be base64- or URL-encoded. More configuration can be found from official documentation. Below is a sample configuration:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
_format_version: "3.0"

services:
- name: echo-svc
url: http://echo:8080
routes:
- name: mtls-route
paths:
- /mtls
- name: echo-route
paths:
- /echo
ca_certificates:
- cert: |-
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
id: f993fd75-2871-4255-b3d4-8200eb998fa2
tags:
- intermediate
- cert: |-
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
id: fe66de95-5108-4195-b1da-7d81e9efb336
tags:
- root
consumers:
- username: mtls-user
plugins:
- route: mtls-route
config:
ca_certificates:
- fe66de95-5108-4195-b1da-7d81e9efb336
- f993fd75-2871-4255-b3d4-8200eb998fa2
certificate_header_format: url_encoded
certificate_header_name: x-amzn-mtls-clientcert
revocation_check_mode: SKIP
enabled: true
name: header-cert-auth

If you do not send a client certificate to the ALB, access to the /mtls route will be blocked. You can still send requests to the /echo route, which does not require mTLS.

Summary

With the introduction of this new plugin, you can enjoy the best of both worlds: the advanced features of the AWS ALB and the security of mTLS authentication with Kong. However, this method of breaking the mTLS process into two parts means you’re not conducting mTLS in the strictest sense. Caution must be exercised to ensure no requests can bypass ALB and reach Kong directly. If a malicious actor can send requests directly to Kong, they could bypass the mTLS handshake by simply injecting a certificate into the header, without proving possession of the private key. To mitigate this risk, a strict security policy must be enforced.

That’s all I want to share with you today. See you in next one.