Træfik 2 voor containers
Als je veel versleutelde services op één server wilt draaien, ben je vaak aan het worstelen met certificaten. De ene service wil ze op een bepaalde locatie, de tweede wil ze in een bepaald formaat, en een derde kan geen TLS zonder hulp. Wanneer je de certificaten moet vernieuwen, betekent dat telkens veel werk. Træfik doet dat niet alleen voor HTTPS, maar voor elke TCP-verbinding die versleuteld moet worden. Merlin Schumacher en Noud van Kruysbergen
Als je Træfik 1 gebruikt voor het beheren van TLS-certificaten en routing, moet je de certificaten ophalen wanneer een service niet via HTTPS loopt. Daar bestaan betrouwbare tools voor, maar uiteindelijk bevinden de certificaatbestanden zich op verschillende plaatsen in het systeem – in mappen, containervolumes of zelfs databases. Als er een nieuw certificaat nodig is, zul je alle gegevens moeten bijwerken en de bijbehorende containers vaak opnieuw moeten opstarten. Dat is veel werk, dat niet alleen vervelend is, maar ook leidt tot slordigheidsfouten. Træfik 2 maakt daar een einde aan omdat het elke TCP-verbinding met de buitenwereld via TLS kan beveiligen en volledig automatisch voor het certificaatbeheer zorgt. Voor de service die erachter zit, gebeurt dat volledig transparant. Bovendien kan Træfik requests afhankelijk van de hostname naar verschillende services routen.
Wanneer je al ervaring hebt met Træfik 2 zul je het concept snel onder de knie krijgen. Het is namelijk heel goed te vergelijken met de procedure voor HTTP-verbindingen. We hebben bij dij dit artikel een repository op GitHub gezet, die je kunt vinden via de link op de rechterpagina. Daar staan alle hier beschreven bestanden in.
CONFIGURATIE
De voorbeeld- repository gaat ervan uit dat je een werkende Docker-installatie hebt met een actuele Docker Compose. Behalve het compose-bestand zijn er nog twee configuratiebestanden voor Træefik, genaamd static. yml en dynamic.yml. In de standaardconfiguratie luistert Træfik in eerste instantie alleen naar de HTTP(S)-poorten, die 'entrypoints' worden genoemd. Om te kunnen luisteren naar requests voor bijvoorbeeld de MQTT-poort, moet je het entrypoint voor poort 8883 instellen. Daarvoor pas je het bestand static. yml aan. Binnen de draaiende docker-container is die dan voor Træfik toegankelijk onder /etc/traefik/traefik.yml en dient als primair configuratiebestand. Voeg het onderstaande toe aan het blok entryPoints als sectie voor MQTT: entryPoints: web: address: “:80” web-secure: address: “:443” mqtt:
address: “:8883”
Dan luistert Træfik naar de poorten 80, 443 en 8883. Vergeet niet om de poorten voor de Træfik-container ook naar buiten te openen door docker-compose.yml en je firewall-regels aan te passen. Herstart Træfik om de wijzigingen toe te passen.
Om Træfik te laten weten wat de nieuwe TCP-service is, moet je een aantal labels instellen. Om dat te doen, bewerk je het compose-bestand van de container. De listing op de volgende pagina laat een voorbeeld zien. Het eerste label traefik.tcp.routers.mqtt.rule definieert de hostname 'mqtt.example.org'. Bij requests sturen moderne clients altijd de hostname via SNI (Server Name Indication). De router stuurt de request dan op de juiste manier door. Wanneer je meerdere services op één server wilt aanbieden, moet je verschillende (sub) domeinen gebruiken.
Bij het tweede label, traefik.tcp.routers.mqtt. entrypoints=mqtt, wordt het eerder gedefinieerde entrypoint gebruikt. traefik.tcp.routers.mqtt. tls=true zorgt ervoor dat de service TLS-termination gebruikt. Als de variabele ontbreekt of niet true is, is de service ook niet toegankelijk, omdat Træfik hem negeert. Door traefik.tcp.routers.mqtt.tls.certResolver=default weet Træfik waar hij het certificaat moet halen. In sommige configuraties, bijvoorbeeld bij wildcard-certificaten, is het ontbreken van een certificaat geen probleem. Maar om problemen met configuratiewijzigingen te voorkomen, kun je die optie maar beter instellen. default is meestal de juiste keuze, tenzij je certificaten uit verschillende bronnen haalt.
Bij elke Træfik-router hoort ook een service. Welke dat is, bepaalt traefik.tcp.routers.mqtt.service.
Het laatste label is de servicedefinitie voor mqtt-svc. Daar geef je de poort op van de dienst die in de container draait. Voor MQTT is dat 1883. Vervolgens start of update je de container dan met docker-compose up -d. Als je het Træfik-dashboard hebt geactiveerd, moet je zowel de nieuw geconfigureerde router als de service bij het onderdeel 'TCP' kunnen zien.
TESTEN
Met een bij de service behorende client of met OpenSSL kun je controleren of de service nu versleuteld werkt. openssl s_client -connect mqtt.example.org:8883
OpenSSL maakt een versleutelde verbinding met de service en geeft informatie over de verbinding en de gebruikte certificaten. Nu kun je via het toetsenbord direct gegevens naar de service sturen. Als de service er iets mee kan doen, zal hij antwoorden. Als de communicatie abrupt wordt beëindigd door een 'bad gateway', werkt het routen niet en weet Træfik niet waar de gegevens naartoe moeten.
Met Ctrl+C beëindig je openssl. Voor het testen van de MQTT-service erachter kun je het programma MQTT-Explorer gebruiken. Bij de instellingen kun je bepalen of het de certificaten van TLS-verbindingen controleert of niet. Daarmee kun je problemen bij het ophalen van certificaten onderzoeken omdat de broker bereikbaar is, zelfs als Træfik zijn ongeldige standaardcertificaat uitgeeft.
Als je er zeker van wilt zijn dat de TLS-configuratie van Træfik voldoet aan de huidige beveiligingsstandaarden, moet je nog het bestand dynamic.yml aanpakken. tls: options: default: minVersion: VersionTLS12 sniStrict: true cipherSuites: - “TLS_ECDHE_ECDSA_WITH...” - “TLS_ECDHE_RSA_WITH_...”
Daarbij is het raadzaam om tenminste TLS versie 1.2 ( minVersion) te vereisen, requests zonder SNI ( sniStrict) af te wijzen en de lijst met cipher-suites te beperken om oude encryptieprocedures uit te sluiten. Met de Mozilla SSL Configuration Generator kun je een goede uitgangsconfiguratie genereren. Hoe je dit doet, staat beschreven in het kader 'Beter versleutelen'.