Traefik 2 on Kubernetes, part 2: TLS TCP with Letsencrypt

In a previous post we described howto setup Traefik 2 on Kubernetes, please check it out if you are not familiair with Traefik’s custom CRD’s like IngressRoutes etc.

This is part 2 of the series, it will focus on TCP TLS support using Letsencrypt. We will create a simple TCP service in an isolated namespace and expose this service in Traefik securely with TLS.


Introduction

A major feature of Treafik 2 is it’s support for TCP TLS. This is exciting because Traefik will manage the certificates required for valid TLS connections and offload the secure TLS connection to a normal TCP based service like a NodeJS backend. No more reloads for daemons to activate a new certificate, yay! And finally easy gRPC and HTTP2 connections without the complexity of TLS.

Let’s see how we can create a simple service and then add TLS support for this service using Traefik 2.

Preparation

In this example we will use Mosquitto as a simple TCP based service, a MQTT broker that works as a pub/sub system for IoT metrics and such. Easy to setup and it does support TLS, however in this case we secure it via Traefik 2 and skip all that hassle.

Step 1) Deploy mosquitto in a namespace

kubectl create namespace mosquitto
kubectl -n mosquitto create deployment mosquitto --image=eclipse-mosquitto

Step 2) Expose the mosquitto deployment

We’ll expose the deployment in the namespace.

kubectl -n mosquitto create service clusterip mosquitto --tcp=1883:1883

Step 3) Create an IngressRouteTCP object for Traefik

Save the contents below to a file named mosquitto-traefik-ingress.yaml and apply to the correct namespace. It will create an IngressRouteTCP object for Traefik2 and also apply TLSoptions required for normal operation.

Please note that the TLSoptions are bound to a namespace, so in this example we refer to this object as you can see.

Make sure you change the HostSNI below to a valid hostname that can be used for SSL. As you can see we enable this service on an entrypoint named “mqtt”, make sure you specify this entrypoint in your Traefik deployment!

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteTCP
metadata:
  name: mosquitto
spec:
  entryPoints:
  - mqtt
  routes:
  - match: HostSNI(`mqtt.canhaz.domain`)
    services:
    - name: mosquitto
      port: 1883
  tls:
    passthrough: false
    options:
      name: default
      namespace: mosquitto

---

apiVersion: traefik.containo.us/v1alpha1
kind: TLSOption
metadata:
  name: default
spec:
  cipherSuites:
  - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
  - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
  - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  minVersion: VersionTLS13
  sniStrict: true

Step 4) Test the configuration

In one window run this command to subscribe to the wildcard “#” channel using TLS. Remember to give Traefik some time to generate the certificates.

mosquitto_sub -h mqtt.canhaz.domain -t \# -V mqttv5 -v -p 8883 --capath /etc/ssl/certs

In another window run the following command to publish random payloads to the mqtt broker, which should appear in the other window.

while :; do mosquitto_pub -h mqtt.canhaz.domain -p 8883 -t $RANDOM/$RANDOM/$RANDOM \
-V mqttv5  -m $RANDOM --capath /etc/ssl/certs; sleep 2; done

Treafik 2 TLS with Mosquitto

That’s it, you now have a working setup using Traefik 2 and Mosquitto. It’s secured with the latest TLS1.3 ciphers without ever touching a single .csr, .crt or .pem file!

You can easily test another service with the same approach, the basics are the same, just remember that entrypoints in Traefik are attached to ports and can be configured using the IngressRouteTCP object.

Next post will dive deeper into Traefik with network policies.

Stay tuned..