Zum Inhalt springen

mTLS: Wenn Services erst den Ausweis zeigen müssen

14. Juli 2026 durch
mTLS: Wenn Services erst den Ausweis zeigen müssen
Tom Ziegler

Ein TLS-Zertifikat auf dem Server ist nett – aber wenn jeder Client ungefragt reinspazieren darf, ist das eher Türsteher mit Augenklappe. Bei mTLS drehen wir den Spieß ein Stück weiter: Nicht nur der Server beweist seine Identität, auch der Client muss ein gültiges Zertifikat vorzeigen. Service A spricht also nur mit Service B, wenn beide sagen können: „Ja, ich bin wirklich ich.“ Klingt nach Paranoia. Ist aber produktive Paranoia.

Wir haben das im Test mit zwei kleinen Services nachgebaut: `orders-service` ruft `payment-service` auf. Ohne mTLS reicht ein gültiger DNS-Name und TLS. Mit mTLS braucht `orders-service` zusätzlich ein Client-Zertifikat, das vom `payment-service` akzeptiert wird.

Erstmal brauchen wir eine eigene kleine CA. Nicht für die große PKI-Weltherrschaft, sondern für interne Service-Zertifikate:

```bash

openssl genrsa -out ca.key 4096

openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \

-out ca.crt -subj "/CN=PLUTEX Internal Service CA"

```

Dann bekommt der Server sein Zertifikat:

```bash

openssl genrsa -out payment.key 2048

openssl req -new -key payment.key -out payment.csr \

-subj "/CN=payment-service.internal"

openssl x509 -req -in payment.csr -CA ca.crt -CAkey ca.key \

-CAcreateserial -out payment.crt -days 365 -sha256

```

Und jetzt der wichtige Teil: der Client bekommt ebenfalls ein Zertifikat:

```bash

openssl genrsa -out orders.key 2048

openssl req -new -key orders.key -out orders.csr \

-subj "/CN=orders-service"

openssl x509 -req -in orders.csr -CA ca.crt -CAkey ca.key \

-CAcreateserial -out orders.crt -days 365 -sha256

```

Auf Serverseite muss nun nicht nur TLS aktiv sein, sondern auch Client-Zertifikate müssen geprüft werden. Beispiel mit Nginx als Reverse Proxy vor dem `payment-service`:

```nginx

server {

listen 443 ssl;

server_name payment-service.internal;

ssl_certificate /etc/nginx/certs/payment.crt;

ssl_certificate_key /etc/nginx/certs/payment.key;

ssl_client_certificate /etc/nginx/certs/ca.crt;

ssl_verify_client on;

location / {

proxy_pass http://payment-backend:8080;

proxy_set_header X-Client-Cert $ssl_client_s_dn;

}

}

```

Der kleine Schalter mit großer Wirkung ist:

```nginx

ssl_verify_client on;

```

Ohne gültiges Client-Zertifikat gibt es dann keinen Kaffee, sondern einen TLS-Handshake-Abbruch. Sehr befriedigend.

Test ohne Client-Zertifikat:

```bash

curl https://payment-service.internal

```

Ergebnis: scheitert. Gut so.

Test mit Client-Zertifikat:

```bash

curl https://payment-service.internal \

--cert orders.crt \

--key orders.key \

--cacert ca.crt

```

Jetzt klappt der Request – vorausgesetzt, Zertifikat, Key und CA passen zusammen. Wenn nicht, bekommst du OpenSSL-Fehlertexte, die aussehen wie aus einem Dämonenbeschwörungsbuch. Klassiker.

Wichtig im Betrieb: Zertifikate brauchen Lebenszyklen. Ablaufdaten, Rotation, Sperrung, Automatisierung. Wer Client-Zertifikate manuell per SCP verteilt, baut sich früher oder später ein Museum für kaputte Deployments. Besser: cert-manager in Kubernetes, Vault PKI, SPIFFE/SPIRE oder eine interne CA mit automatisierter Ausgabe.

Auch wichtig: mTLS ersetzt keine Autorisierung. Nur weil `orders-service` echt ist, darf er nicht automatisch alles. Identität ist Schritt eins. Danach kommen Policies: Welcher Service darf welchen Endpoint aufrufen?

Unser Fazit nach dem Selbstversuch: mTLS ist nicht kompliziert, aber gnadenlos präzise. Falscher CN, falsche CA, abgelaufenes Zertifikat – zack, Funkstille. Genau das ist der Punkt. Service-zu-Service-Kommunikation sollte nicht auf „wird schon intern sein“ basieren. Intern ist kein Sicherheitskonzept. Intern ist nur ein Ort, an dem Angreifer nach dem ersten Treffer besonders gerne weitermachen.

mTLS: Wenn Services erst den Ausweis zeigen müssen
Tom Ziegler 14. Juli 2026
Diesen Beitrag teilen