Viele unserer Kunden setzen DB2 als Datenbank ein.
DB2 kann JDBC-Verbindungen mittels TLS verschlüsseln.
Leider treten dabei gelegentlich Probleme auf, die
“Anwender” melden dann idR. Zertifikatsprobleme
unabhängig vom tatsächlichen Problem.
Ausgangslage
Zugriff auf die DB2 klappt für alle Programme, die Java8 oder neuer
verwenden. Bei Java7 gibt es eine “SSLHandshakeException”:
123456
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1991)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1098)
...
Oberflächlich ist klar:
Entweder ist das DB2-Zertifikat abgelaufen
… oder von einer merkwürdigen CA ausgestellt
… oder die CA nicht im “cacerts” eingetragen (das ist “was spezielles” für
diesen Kunden, er ändert diese gerne)
… scheint nicht zu klappen. Liegt an der veralteten Version von OPENSSL:
12
$ openssl version
OpenSSL 0.9.8j-fips 07 Jan 2009
Neuer Versuch mit neuerer Version:
12345678910111213141516171819202122232425
$ openssl version
OpenSSL 1.0.1g 7 Apr 2014
$ openssl s_client -connect db2.internal.biz:62000
CONNECTED(00000003)
depth=2 DC = biz, DC = ios, DC = iosPKI, CN = IOS-CA-ROOT-42
verify return:1
depth=1 DC = biz, DC = ios, DC = iosPKI, CN = IOS-CA-PROC-43
verify return:1
depth=0 C = DE, O = IOS GmbH, OU = DB2ADM, CN = db2.internal.biz, L = Stuttgart, ST = Baden-Wuerttemberg
...
$ openssl s_client -connect db2.internal.biz:62000|openssl x509 -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 3899571 (0x3b80b3)
Signature Algorithm: sha256WithRSAEncryption
Issuer: DC=biz, DC=ios, DC=iosPKI, CN=IOS-CA-PROC-43
Validity
Not Before: Mar 22 12:17:19 2019 GMT
Not After : Mar 22 00:00:00 2023 GMT
Subject: C=DE, O=IOS GmbH, OU=DB2ADM, CN=db2.internal.biz, L=Stuttgart, ST=Baden-Wuerttemberg
...
X509v3 Subject Alternative Name:
DNS:gateway001.internal.biz, DNS:gateway002.internal.biz
...
Man sieht:
* das Zertifikat ist gültig
* … und von der richtigen CA ausgestellt
* … und auf die richtigen Namen ausgestellt
Am Zertifikat gibt es nichts zu bemängeln!
Abstimmung mit dem DB2-Team – Ciphers
Das DB2-Team hat die BSI-Empfehlung zu TLS
umgesetzt und die darin enthaltenen Ciphers als zulässig konfiguriert.
Also Quercheck mit unserer Java7-Version: Gibt es da Überlappungen? Unterstützt
unsere Java7-Version einen der hinterlegten Ciphers? Die unterstützten Ciphers kann man sich leicht anzeigen lassen mit Ciphers.java:
Das “Sternchen” bedeutet hier, dass es sich um einen “Default Cipher” handelt.
Es gibt beispielsweise den Cipher TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, der
in der Liste der Default Ciphers enthalten ist und auch in der BSI-Liste.
“Eigentlich müßte es funktionieren”.
Analyse mit SSLPoke
Mit SSLPoke
kann man weitere Erkenntnisse sammeln:
1234567891011121314
$ javac SSLPoke.java
$ /java8/bin/java SSLPoke db2.internal.biz 62000
Successfully connected
$ java SSLPoke db2.internal.biz 62000
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1991)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1098)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1344)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:721)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:122)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:136)
at SSLPoke.main(SSLPoke.java:31)
SSLPoke verhält sich ähnlich zu den Java-Programmen: Mit Java8 funktioniert alles,
mit Java7 gibt’s Probleme!
Also: SSL-Debugging aktivieren und nochmal probieren: