TLS passthrough
Set up a TLS listener on the Gateway that serves one or more hosts and passes TLS traffic through to a destination. Because TLS traffic is not terminated at the Gateway, the destination must be capable of handling incoming TLS traffic.
Before you begin
-
Set up kgateway by following the Quick start or Installation guides.
-
Make sure that you have the OpenSSL version of
openssl
, not LibreSSL. Theopenssl
version must be at least 1.1.-
Check the
openssl
version that is installed. If you see LibreSSL in the output, continue to the next step.openssl version
-
Install the OpenSSL version (not LibreSSL). For example, you might use Homebrew.
brew install openssl
-
Review the output of the OpenSSL installation for the path of the binary file. You can choose to export the binary to your path, or call the entire path whenever the following steps use an openssl command.
- For example, openssl might be installed along the following path:
/usr/local/opt/openssl@3/bin/
- To run commands, you can append the path so that your terminal uses this installed version of OpenSSL, and not the default LibreSSL.
/usr/local/opt/openssl@3/bin/openssl req -new -newkey rsa:4096 -x509 -sha256 -days 3650...
- For example, openssl might be installed along the following path:
-
-
Decide whether to set up a listener inline on the Gateway resource or as a separate ListenerSet resource. For more information, see the Listener overview.
ListenerSets: This feature is available in kgateway version 2.1.x or later. Also, you must install the experimental channel of the Kubernetes Gateway API at version 1.3 or later.
Deploy an nginx server that is configured for HTTPS traffic
Deploy a sample nginx server and configure the server for HTTPS traffic.
-
Create a root certificate for the
example.com
domain. You use this certificate to sign the certificate for your nginx service later.mkdir example_certs openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example_certs/example.com.key -out example_certs/example.com.crt
-
Create a server certificate and private key for the
nginx.example.com
domain.openssl req -out example_certs/nginx.example.com.csr -newkey rsa:2048 -nodes -keyout example_certs/nginx.example.com.key -subj "/CN=nginx.example.com/O=some organization" openssl x509 -req -sha256 -days 365 -CA example_certs/example.com.crt -CAkey example_certs/example.com.key -set_serial 0 -in example_certs/nginx.example.com.csr -out example_certs/nginx.example.com.crt
-
Create a secret that stores the certificate and key for the nginx server.
kubectl create secret tls nginx-server-certs \ --key example_certs/nginx.example.com.key \ --cert example_certs/nginx.example.com.crt
-
Prepare your nginx configuration. The following example configures nginx for HTTPS traffic with the certificate that you created earlier.
cat <<\EOF > ./nginx.conf events { } http { log_format main '$remote_addr - $remote_user [$time_local] $status ' '"$request" $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; error_log /var/log/nginx/error.log; server { listen 443 ssl; root /usr/share/nginx/html; index index.html; server_name nginx.example.com; ssl_certificate /etc/nginx-server-certs/tls.crt; ssl_certificate_key /etc/nginx-server-certs/tls.key; } } EOF
-
Store the nginx configuration in a configmap.
kubectl create configmap nginx-configmap --from-file=nginx.conf=./nginx.conf
-
Deploy the nginx server.
kubectl apply -f- <<EOF apiVersion: v1 kind: Service metadata: name: my-nginx labels: run: my-nginx spec: ports: - port: 443 protocol: TCP selector: run: my-nginx --- apiVersion: apps/v1 kind: Deployment metadata: name: my-nginx spec: selector: matchLabels: run: my-nginx replicas: 1 template: metadata: labels: run: my-nginx spec: containers: - name: my-nginx image: nginx ports: - containerPort: 443 volumeMounts: - name: nginx-config mountPath: /etc/nginx readOnly: true - name: nginx-server-certs mountPath: /etc/nginx-server-certs readOnly: true volumes: - name: nginx-config configMap: name: nginx-configmap - name: nginx-server-certs secret: secretName: nginx-server-certs EOF
-
Verify that the server is up and running.
kubectl get pods | grep nginx
Example output:
my-nginx-c4c49df8f-2bkws 1/1 Running 0 34s
Set up TLS passthrough
To route TLS traffic to the nginx server directly without terminating the TLS connection at the Gateway, you can use either an inline Gateway listener or a ListenerSet. Then, you create a TLSRoute that represents the route to your nginx server and attach it to the Gateway or ListenerSet.
If you plan to set up your listener as part of a ListenerSet, keep the following considerations in mind. For more information, see ListenerSets (experimental).
- This feature is available in kgateway version 2.1.x or later.
- You must install the experimental channel of the Kubernetes Gateway API at version 1.3 or later.
-
Create a Gateway that passes through incoming TLS requests for the
nginx.example.com
domain.kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: tls-passthrough namespace: kgateway-system spec: gatewayClassName: kgateway listeners: - name: tls protocol: TLS hostname: "nginx.example.com" tls: mode: Passthrough port: 8443 allowedRoutes: namespaces: from: All EOF
Review the following table to understand this configuration.
Setting Description spec.gatewayClassName
The name of the Kubernetes GatewayClass that you want to use to configure the Gateway. When you set up kgateway, a default GatewayClass is set up for you. spec.listeners
Configure the listeners for this Gateway. In this example, you configure a TLS passthrough Gateway that listens for incoming traffic for the nginx.example.com
domain on port 8443. The Gateway can serve TLS routes from any namespace.spec.listeners.tls.mode
The TLS mode for incoming requests. In this example, TLS requests are passed through to the backend service without being terminated at the Gateway.
-
Create a Gateway that enables the attachment of ListenerSets.
kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: tls-passthrough namespace: kgateway-system spec: gatewayClassName: kgateway allowedListeners: namespaces: from: All listeners: - protocol: TLS port: 80 name: generic-tls allowedRoutes: namespaces: from: All EOF
Review the following table to understand this configuration.
Setting Description spec.gatewayClassName
The name of the Kubernetes GatewayClass that you want to use to configure the Gateway. When you set up kgateway, a default GatewayClass is set up for you. spec.allowedListeners
Enable the attachment of ListenerSets to this Gateway. The example allows listeners from any namespace. spec.listeners
Optionally, you can configure a listener that is specific to the Gateway. Note that due to a Gateway API limitation, you must configure at least one listener on the Gateway resource, even if the listener is not used and is a generic, “dummy” listener. This generic listener cannot conflict with the listener that you configure in the ListenerSet, such as using the same port or name. In this example, the generic listener is configured on port 80, which differs from port 443 in the ListenerSet that you create later. -
Create a ListenerSet that configures a TLS passthrough listener for the Gateway.
kubectl apply -f- <<EOF apiVersion: gateway.networking.x-k8s.io/v1alpha1 kind: XListenerSet metadata: name: my-tls-listenerset namespace: kgateway-system spec: parentRef: name: tls-passthrough namespace: kgateway-system kind: Gateway group: gateway.networking.k8s.io listeners: - protocol: TLS port: 8443 hostname: nginx.example.com name: tls-listener-set tls: mode: Passthrough allowedRoutes: namespaces: from: All EOF
Review the following table to understand this configuration.
Setting Description spec.parentRef
The name of the Gateway to attach the ListenerSet to. spec.listeners
Configure the listeners for this ListenerSet. In this example, you configure a TLS passthrough listener for the nginx.example.com
domain on port 8443.spec.listeners.tls.mode
The TLS mode for incoming requests. TLS requests are passed through to the backend service without being terminated at the Gateway.
Create a TLSRoute
kubectl apply -f- <<EOF
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
name: tlsroute
namespace: default
spec:
parentRefs:
- name: tls-passthrough
namespace: kgateway-system
rules:
- backendRefs:
- group: ""
kind: Service
name: my-nginx
port: 443
EOF
kubectl apply -f- <<EOF
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
name: tlsroute
namespace: default
spec:
parentRefs:
- name: my-tls-listenerset
namespace: kgateway-system
kind: XListenerSet
group: gateway.networking.x-k8s.io
rules:
- backendRefs:
- group: ""
kind: Service
name: my-nginx
port: 443
EOF
Verify TLS passthrough traffic for nginx
-
Get the external address of the gateway proxy and save it in an environment variable.external address of the gateway proxy and save it in an environment variable.
export INGRESS_GW_ADDRESS=$(kubectl get svc -n kgateway-system tls-passthrough -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}") echo $INGRESS_GW_ADDRESS
-
Send a request to the
nginx.example.com
domain and verify that you get back a 200 HTTP response code from your nginx server. Because nginx accepts incoming TLS traffic only, the 200 HTTP response code proves that TLS traffic was not terminated at the Gateway. In addition, you can verify that you get back the server certificate that you configured your nginx server with in the beginning.-
Load balancer IP:
curl -vik --resolve "nginx.example.com:8443:${INGRESS_GW_ADDRESS}" --cacert example_certs/example.com.crt https://nginx.example.com:8443/
-
Load balancer hostname:
curl -vik --resolve "nginx.example.com:8443:$(dig +short $INGRESS_GW_ADDRESS | head -n1)" --cacert example_certs/example.com.crt https://nginx.example.com:8443/
Example output:
* Request completely sent off < HTTP/1.1 200 OK HTTP/1.1 200 OK < Server: nginx/1.27.4 Server: nginx/1.27.4 ... < <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> * Connection #0 to host nginx.example.com left intact
-
-
Port-forward the tls-passthrough gateway proxy pod on port 8443.
kubectl port-forward deployment/tls-passthrough -n kgateway-system 8443:8443
-
Send a request to the
nginx.example.com
domain and verify that you get back a 200 HTTP response code from your nginx server. Because nginx accepts incoming TLS traffic only, the 200 HTTP response code proves that TLS traffic was not terminated at the Gateway. In addition, you can verify that you get back the server certificate that you configured your nginx server with in the beginning.curl -vi --cacert example_certs/example.com.crt --resolve "nginx.example.com:8443:127.0.0.1" https://nginx.example.com:8443
Example output:
* Request completely sent off < HTTP/1.1 200 OK HTTP/1.1 200 OK < Server: nginx/1.27.4 Server: nginx/1.27.4 ... < <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> * Connection #0 to host nginx.example.com left intact
Cleanup
You can remove the resources that you created in this guide.rm -r example_certs
rm nginx.conf
kubectl delete configmap nginx-configmap
kubectl delete tlsroute tlsroute
kubectl delete gateway tls-passthrough -n kgateway-system
kubectl delete deployment my-nginx
kubectl delete service my-nginx
kubectl delete secret nginx-server-certs
rm -r example_certs
rm nginx.conf
kubectl delete configmap nginx-configmap
kubectl delete tlsroute tlsroute
kubectl delete XListenerSet my-tls-listenerset -n kgateway-system
kubectl delete gateway tls-passthrough -n kgateway-system
kubectl delete deployment my-nginx
kubectl delete service my-nginx
kubectl delete secret nginx-server-certs