aethercert
Dokumentation

AEK443001: NetScaler – TLS-Handshake-Fehler wegen fehlender ECC-Kurven

Das Ausrollen auf einen Citrix NetScaler scheitert mit remote error: tls: handshake failure, weil am Management-Dienst keine ECC-Kurven gebunden sind. Ursache, Diagnose und zwei Lösungswege.

Der aethercert-agent kann ein Zertifikat nicht auf einen Citrix NetScaler ausrollen, wenn am Management-Dienst keine ECC-Kurven gebunden sind. Die Korrektur erfolgt auf dem NetScaler, am Agent und am Target ist nichts zu ändern.

FeldWert
ArtikelnummerAEK443001
BetroffenTarget Citrix NetScaler ADC (NITRO über die NSIP)
Nachgestellt mitNetScaler 14.1 Build 73.41
UrsacheKeine ECC-Kurven am Dienst nshttps-127.0.0.1-443, dadurch kein ECDHE-Cipher verhandelbar
LösungECC-Kurven und eine ECDHE-Cipher-Gruppe binden

Symptom

Der Deploy-Schritt auf das NetScaler-Target bricht mit einem TLS-Fehler ab, bevor ein NITRO-Aufruf stattfindet.

  • Das Agent-Log zeigt remote error: tls: handshake failure beim Verbindungsaufbau zur NSIP.
  • Die Zertifikatsausstellung selbst ist erfolgreich, nur das Ausrollen scheitert.
  • Die NetScaler-GUI im Browser und NITRO-Aufrufe mit curl.exe oder PowerShell funktionieren weiterhin. Deshalb fällt der Fehler im Alltag nicht auf.

Ursache

NetScaler und Agent haben keinen gemeinsamen Cipher, weil am Management-Dienst keine ECC-Kurven gebunden sind.

  1. Der HTTPS-Zugriff auf die NSIP läuft über die internen Dienste nshttps-127.0.0.1-443 und nshttps-::1l-443.
  2. Dort ist die Cipher-Gruppe DEFAULT gebunden, aber keine ECC-Kurve. Ohne Kurve kann der NetScaler keinen ECDHE-Cipher aushandeln.
  3. Aus DEFAULT bleiben damit nur Cipher mit reinem RSA-Schlüsselaustausch übrig, etwa AES128-SHA oder AES256-GCM-SHA384.
  4. Der aethercert-agent bietet keine Cipher mit reinem RSA-Schlüsselaustausch an. Diese Cipher haben keine Forward Secrecy und gelten als veraltet.
  5. Ohne Schnittmenge beendet der NetScaler den Handshake mit handshake_failure.

Browser und Windows-Werkzeuge (SChannel) bieten RSA-Schlüsselaustausch noch an und kommen deshalb durch.

Diagnose

Die Ursache ist bestätigt, wenn am Dienst keine ECC-Kurven erscheinen und der ECDHE-Test scheitert, der RSA-Test aber klappt. Alle Befehle sind nur lesend.

1. Dienst und SSL-Parameter prüfen (NetScaler-CLI):

show ssl service nshttps-127.0.0.1-443
show ssl parameter
  • In der Ausgabe des Dienstes fehlen Zeilen wie ECC Curve Name: P_256.
  • show ssl parameter zeigt unter Default profile, ob Enhanced SSL Profiles aktiv sind. Davon hängt ab, ob Lösung A oder Lösung B passt.
  • Sind die Profile aktiv, zusätzlich show ssl profile ns_default_ssl_profile_internal_frontend_service prüfen.

2. Gegenprobe mit OpenSSL (auf der NetScaler-Shell, <NSIP> ersetzen):

shell
openssl s_client -connect <NSIP>:443 -tls1_2 -cipher ECDHE-RSA-AES128-GCM-SHA256 </dev/null
openssl s_client -connect <NSIP>:443 -tls1_2 -cipher AES128-GCM-SHA256 </dev/null
exit

Der erste Aufruf endet mit einem Handshake-Fehler, der zweite baut die Verbindung auf.

Vorher Backup oder Snapshot erstellen

Lösung A: mit Enhanced SSL Profiles

Diese Lösung gilt, wenn show ssl parameter unter Default profile den Wert ENABLED zeigt. Kurven und Cipher-Gruppe werden dann einmal am Profil des Management-Dienstes gebunden. Die Cipher-Gruppe lässt sich danach als Hausstandard für weitere Profile nutzen.

1. Cipher-Gruppe anlegen (TLS 1.3 und ECDHE-GCM für RSA- und ECDSA-Zertifikate):

add ssl cipher CG_AETHERCERT
bind ssl cipher CG_AETHERCERT -cipherName TLS1.3-AES256-GCM-SHA384
bind ssl cipher CG_AETHERCERT -cipherName TLS1.3-CHACHA20-POLY1305-SHA256
bind ssl cipher CG_AETHERCERT -cipherName TLS1.3-AES128-GCM-SHA256
bind ssl cipher CG_AETHERCERT -cipherName TLS1.2-ECDHE-ECDSA-AES256-GCM-SHA384
bind ssl cipher CG_AETHERCERT -cipherName TLS1.2-ECDHE-ECDSA-AES128-GCM-SHA256
bind ssl cipher CG_AETHERCERT -cipherName TLS1.2-ECDHE-RSA-AES256-GCM-SHA384
bind ssl cipher CG_AETHERCERT -cipherName TLS1.2-ECDHE-RSA-AES128-GCM-SHA256

2. Profil des Management-Dienstes anpassen:

bind ssl profile ns_default_ssl_profile_internal_frontend_service -eccCurveName X_25519
bind ssl profile ns_default_ssl_profile_internal_frontend_service -eccCurveName P_256
bind ssl profile ns_default_ssl_profile_internal_frontend_service -eccCurveName P_384
bind ssl profile ns_default_ssl_profile_internal_frontend_service -cipherName CG_AETHERCERT -cipherPriority 1
set ssl profile ns_default_ssl_profile_internal_frontend_service -tls13 ENABLED

Die Kurven werden bewusst einzeln statt mit ALL gebunden. So bleibt die schwache Kurve P_224 außen vor.

3. Optional: DEFAULT lösen. Für den Deploy nicht nötig, mit den Kurven sind auch die ECDHE-Cipher aus DEFAULT verhandelbar. Das Lösen härtet den Dienst zusätzlich, weil danach nur noch die Cipher aus CG_AETHERCERT angeboten werden:

unbind ssl profile ns_default_ssl_profile_internal_frontend_service -cipherName DEFAULT

Lösung B: ohne Enhanced SSL Profiles

Sind die Profile nicht aktiviert, werden Kurven und Cipher-Gruppe direkt an beiden Management-Diensten gebunden. Das ändert nur diese zwei Dienste, bestehende Sitzungen bleiben erhalten.

1. Cipher-Gruppe anlegen (TLS 1.3 und ECDHE-GCM für RSA- und ECDSA-Zertifikate). Existiert CG_AETHERCERT schon, diesen Schritt überspringen:

add ssl cipher CG_AETHERCERT
bind ssl cipher CG_AETHERCERT -cipherName TLS1.3-AES256-GCM-SHA384
bind ssl cipher CG_AETHERCERT -cipherName TLS1.3-CHACHA20-POLY1305-SHA256
bind ssl cipher CG_AETHERCERT -cipherName TLS1.3-AES128-GCM-SHA256
bind ssl cipher CG_AETHERCERT -cipherName TLS1.2-ECDHE-ECDSA-AES256-GCM-SHA384
bind ssl cipher CG_AETHERCERT -cipherName TLS1.2-ECDHE-ECDSA-AES128-GCM-SHA256
bind ssl cipher CG_AETHERCERT -cipherName TLS1.2-ECDHE-RSA-AES256-GCM-SHA384
bind ssl cipher CG_AETHERCERT -cipherName TLS1.2-ECDHE-RSA-AES128-GCM-SHA256

2. Kurven binden:

bind ssl service nshttps-127.0.0.1-443 -eccCurveName X_25519
bind ssl service nshttps-127.0.0.1-443 -eccCurveName P_256
bind ssl service nshttps-127.0.0.1-443 -eccCurveName P_384
bind ssl service nshttps-::1l-443 -eccCurveName X_25519
bind ssl service nshttps-::1l-443 -eccCurveName P_256
bind ssl service nshttps-::1l-443 -eccCurveName P_384

3. Cipher-Gruppe binden:

bind ssl service nshttps-127.0.0.1-443 -cipherName CG_AETHERCERT
bind ssl service nshttps-::1l-443 -cipherName CG_AETHERCERT

4. Optional: DEFAULT lösen. Für den Deploy nicht nötig, das Lösen härtet die Dienste zusätzlich. Erst nach Schritt 3, damit die Dienste nie ohne Cipher sind:

unbind ssl service nshttps-127.0.0.1-443 -cipherName DEFAULT
unbind ssl service nshttps-::1l-443 -cipherName DEFAULT

Prüfen und Deploy wiederholen

Nach der Änderung klappt der ECDHE-Test, und der Deploy-Job läuft ohne weitere Anpassung durch.

  1. Die OpenSSL-Gegenprobe aus der Diagnose wiederholen. Der ECDHE-Test zeigt jetzt Cipher is ECDHE-RSA-AES128-GCM-SHA256. Wurde DEFAULT gelöst, scheitert der Test mit AES128-GCM-SHA256 nun bewusst, weil CG_AETHERCERT keinen RSA-Schlüsselaustausch enthält.

  2. Konfiguration speichern:

    save ns config
  3. Im aethercert-Dashboard unter Verwalten > Jobs den fehlgeschlagenen Job mit Bereitstellung wiederholen erneut anstoßen. Der Agent hat das Zertifikat bereits, es läuft also nur der Deploy-Schritt. Siehe Certificate jobs.

Hinweise

  • DEFAULT enthält weiterhin SHA1-CBC-Cipher und Cipher mit RSA-Schlüsselaustausch. CG_AETHERCERT kann deshalb auch für SSL-vServer der Hausstandard werden. Mit Lösung A geht das über das Profil ns_default_ssl_profile_frontend.
  • Mit aktivem Default-Profil bindet der NetScaler ns_default_ssl_profile_internal_frontend_service an die internen Dienste und deaktiviert dort SSLv3, TLS 1.0 und TLS 1.1.
  • Zertifikate von Hand auf dem NetScaler tauschen: Citrix NetScaler (ADC).

Quellen

Auf dieser Seite