# mySQL, SSL und eine Java Applikation



## Profiler (28. April 2012)

Hallo Leute, ich bin neu hier, aber ich hoffe ich poste das hier im richtigen Forum.

Ich habe folgendes Problem:
Ich bin zur Zeit dabei meine Java Applikation zu testen, welche über ein Login-Formular die Echtheit eines Nutzers bestätigen soll, aber da diese, nicht wie bei Webservern üblich, über den _localhost_ auf die von mir verwendete, in XAMPP integrierte, mySQL-Datenbank zugreift habe ich vor das ganz über SSL zu verschlüsseln.

Ohne SSL funktioniert das ganze problemlos, aber sobald ich Client-seitig SSL erzwinge bekomme ich folgende Fehlermeldung:


```
SSL Connection required, but not supported by server.
```

Eigentlich ist klar, was das bedeutet, aber ich finde in keiner Konfigurationsdatei eine entsprechende Variable und Google ist was das angeht auch sehr zurückhaltend; wenn es mal was ausspuckt, dann nur für Linux. Allerdings verwende ich als Entwicklungsumgebung Windows 7.

Hat jemand Ahnung von mySQL in Verbindung mit SSL und kann mir helfen?
Ich danke schonmal im Vorraus


----------



## saftmeister (28. April 2012)

Hallo,

im MySQL Handbuch wird man fündig: http://dev.mysql.com/doc/refman/5.0/en/secure-create-certs.html

Da werden zwar auch Linux-Commands verwendet, aber OpenSSL gibts auch für Windows.

EDIT: Ich seh grad, im Example 3 im Handbuch wird auch erklärt, wie man es mit Windows macht.


----------



## Profiler (28. April 2012)

Danke für die Antwort, aber das ist nicht das, was ich suche.
In den Examples wird nur erklärt, wie man ein Zertifikat erstellt bzw. OpenSSL installiert, aber beides ist nicht das Problem. Zum einen verwende ich keine Zertifikate:


```
verifyServerCertificate=false
```

Und zum anderen ist laut phpMyAdmin sowohl SSL als auch OpenSSL installiert, nur werden beide als _disabled_ angezeigt. Ich kann das aber, meines Wissens nach, nicht direkt über phpMyAdmin ändern und die Konfigurationsdatein helfen mir nicht weiter.

Aber wenn das ganze Gedöns schon installiert ist muss man es ja auch benutzen können, nur meine Frage ist wie


----------



## saftmeister (28. April 2012)

SSL basiert aber nun mal auf Zertifikaten. Das kann man sich nicht aussuchen. verifyServerCertificate bedeutet lediglich, dass das Zertifikat nicht auf seine Gültigkeit hin überprüft werden soll, nicht aber, das man keines braucht.

In den User-Comments steht, wie man weiter vorgehen soll, nach dem man das Zertifikat erstellt hat:


```
In order to run MySQL as Service on Windows platform with SSL enabled just add this lines in [ mysqld] section:

ssl-key=C:/Program Files/MySQL/MySQL Server 5.0/cert/server-key.pem
ssl-cert=C:/Program Files/MySQL/MySQL Server 5.0/cert/server-cert.pem
ssl-ca=C:/Program Files/MySQL/MySQL Server 5.0/cert/ca-cert.pem

Where "C:/Program Files/MySQL/MySQL Server 5.0/cert/" is a path to certs described above
```

Hier noch mal eine 5-Schritte-Anleitung: http://www.chriscalender.com/?p=448


----------



## Profiler (28. April 2012)

Okey, danke für deine Hilfe, eine Verbindung kann ich nun herstellen, aber diese scheint sofort wieder abzubrechen, denn ich bekomme die Meldung:


```
Communications link failure

The last packet successfully received from the server was 2 milliseconds ago.  The last packet sent successfully to the server was 2 milliseconds ago.
```

Aber auch dies scheint ein reines SSL-Problem zu sein, denn wenn ich die Parameter für die sichere Verbindung aus dem Query entferne funktioniert alles wunderbar.

Auch wenn ich den Befehl


```
autoReconnect=true
```

benutze hilft das nicht. Ich habe in einem anderen Forum den Hinweis gefunden, dass es möglicherweise an der größe der gesendeten Daten liegt aber auch


```
useCompression=true
```

hilft nicht.

Weiß jemand Rat? Danke nochmal für Eure schnelle Hilfe bis jetzt, ist ein super Forum


----------



## saftmeister (29. April 2012)

Guten Morgen,

verwendest du rein zufällig einen Internet-Proxy? Ich hatte mal ein ähnliches Problem mit dem JDBC-Treiber für MySQL, da war der eingestellte Proxy im Internet Explorer schuld. Frag nicht warum, ich hab auch keine Ahnung, was ein JDBC-Treiber mit dem Proxy für HTTP zu schaffen hat ;-)

EDIT: Kannst du mal den kompletten Exception-Stacktrace posten?


----------



## Profiler (29. April 2012)

Guten Morgen auch 

Also ich benutze keinen Proxy. Ich weiss, dass manchmal Sachen die eigentlich nichts miteinander zu tun haben, für Probleme verantwortlich sind, aber dann könnte es ja auch irgendwie alles sein. 

Der Stacktrace sieht so aus:


```
exception: Communications link failure

The last packet successfully received from the server was 2 milliseconds ago.  The last packet sent successfully to the server was 1 milliseconds ago.
exception: java.net.SocketException: Software caused connection abort: recv failed
exception: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet successfully received from the server was 2 milliseconds ago.  The last packet sent successfully to the server was 1 milliseconds ago.
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
	at java.lang.reflect.Constructor.newInstance(Unknown Source)
	at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
	at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1116)
	at com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:105)
	at com.mysql.jdbc.MysqlIO.negotiateSSLConnection(MysqlIO.java:5150)
	at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1689)
	at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1276)
	at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2389)
	at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2422)
	at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2207)
	at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:797)
	at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
	at java.lang.reflect.Constructor.newInstance(Unknown Source)
	at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
	at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:389)
	at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:305)
	at java.sql.DriverManager.getConnection(Unknown Source)
	at java.sql.DriverManager.getConnection(Unknown Source)
	at MySQLConnection.Connection(MySQLConnection.java:59)
	at MySQLConnection.setDate(MySQLConnection.java:147)
	at thread.run(thread.java:44)
Caused by: java.net.SocketException: Software caused connection abort: recv failed
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.read(Unknown Source)
	at java.net.SocketInputStream.read(Unknown Source)
	at sun.security.ssl.InputRecord.readFully(Unknown Source)
	at sun.security.ssl.InputRecord.read(Unknown Source)
	at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
	at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
	at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
	at com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:90)
	... 20 more
```

Danke nochmal für deine Hilfe


----------



## saftmeister (29. April 2012)

Welchen JDBC-Treiber verwendest du? Die Caused-by-Exception hilft weiter: http://dev.mysql.com/doc/refman/4.1...s-troubleshooting.html#qandaitem-18-3-5-3-1-7


----------



## Profiler (29. April 2012)

Also eigentlich kann es nicht an der Version liegen. Ich arbeite mit _v. 5.1.19_ und das scheint, laut  MySQL der aktuelle Treiber zu sein.

Die _*.jar_ liegt bei mir in:


```
[...]\Java\jre7\lib\ext\
```

und außer dieser gibt es keine andere Version in dem Verzeichnis. Sollte ich noch wo anderes suchen?

Alternativ könnte ich eine ältere Version von dem Treiber bzw. von der RE installieren, aber da ist die Frage ob das hilft.


----------



## saftmeister (29. April 2012)

Welchen MySQL-Server verwendest du denn?


----------



## Profiler (29. April 2012)

Laut phpMyAdmin Version 5.5.16.


----------



## saftmeister (29. April 2012)

Ok, weiterer Versuch.

Ich hab es selbst grad mal probiert und es ist tatsächlich nicht so einfach. Ich hab noch gar keine Verbindung über Command-Line zurande bekommen.

Idee: Firewall-Settings? Welchen Port verwendest du im JDBC-DSN für den Connect? Ist der Port in deiner Firewall geblockt? Ist der Port überhaupt offen (netstat -nao an der Command Line aufrufen und kontrollieren). Bei SSL-Verbindungen soll laut der Step-by-Step-Anleitung der Port 3430 benutzt werden. Ich hab bei mir nachgesehen, der Port ist nicht im Status "LISTEN".

Rausfinden kannst du das, wenn du das netstat-Command mit den Parametern -nao aufrufst und kontrollierst, welche PID den Port 3306 (das ist der MySQL-Server) verwendet. Dann such weiter, ob die Process-ID noch einen anderen Port belegt.

EDIT: Ich bin einen Schritt weiter, mein MySQL-Server würde nun SSL-Verbindungen akzeptieren, es war eine Kombination aus eigener Unfähigkeit (Typo im Pfad zum Zertifikat) und der Tatsache, das OpenSSL den Private-Key anders kommentiert als MySQL es erwartet. Hier kannst du nachlesen, was zu tun ist: http://forums.mysql.com/read.php?11,400856,401127#msg-401127

Am besten ist es, wenn du dir sicher bist, das MySQL überhaupt mit SSL gestartet werden kann. Starte dazu an der Kommando-Zeile den mysqld einfach mal mit Parameter --ssl und schau, ob keine Warnings oder Fehlermeldungen kommen.

EDIT2: Hast du mal nachgesehen, ob dein MySQL-Server mittlerweile überhaupt SSL-Verbindungen gestattet? Versuch mal diesen Query:


```
SHOW GLOBAL VARIABLES LIKE '%ssl%';
```


----------



## Profiler (29. April 2012)

Zur Zeit läuft sowohl der Server als auch die App auf einem System, aber ich habe trotzdem die Firewall zum Test abgeschaltet und den Port:3430 freigegeben; erstmal kein Erfolg.

Dann hab ich, wie du's empfohlen hast über netstat die Ports überprüft und dabei fallen auf eine PID:  


```
TCP | 0.0.0.0:3306 | 0.0.0.0:0 | ABHÖREN
TCP | [ : : ]:3306 | 0.0.0.0:0 | ABHÖREN
```

Was allerdings interessant ist, als ich in meinem Query den Port von Standard-MySQL (3306) auf den Port, den du erwähnt hast, geändert hab (3430), hab ich diese Fehlermeldung erhalten:


```
Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
exception: java.net.ConnectException: Connection refused: connect
exception: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
	at java.lang.reflect.Constructor.newInstance(Unknown Source)
	at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
	at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1116)
	at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:348)
	at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2385)
	at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2422)
	at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2207)
	at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:797)
	at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
	at java.lang.reflect.Constructor.newInstance(Unknown Source)
	at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
	at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:389)
	at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:305)
	at java.sql.DriverManager.getConnection(Unknown Source)
	at java.sql.DriverManager.getConnection(Unknown Source)
	at MySQLConnection.Connection(MySQLConnection.java:61)
	at MySQLConnection.setDate(MySQLConnection.java:150)
	at thread.run(thread.java:44)
Caused by: java.net.ConnectException: Connection refused: connect
	at java.net.DualStackPlainSocketImpl.connect0(Native Method)
	at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
	at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
	at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
	at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
	at java.net.PlainSocketImpl.connect(Unknown Source)
	at java.net.SocksSocketImpl.connect(Unknown Source)
	at java.net.Socket.connect(Unknown Source)
	at java.net.Socket.connect(Unknown Source)
	at java.net.Socket.<init>(Unknown Source)
	at java.net.Socket.<init>(Unknown Source)
	at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:257)
	at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:298)
	... 17 more
```

Interessant scheinen die Stellen


```
The driver has not received any packets from the server.
```

und vorallem


```
java.net.ConnectException: Connection refused: connect
```

 zu sein, denn jetzt scheint die Verbindung Serverseitig abgewiesen zu werden.

EDIT: Ja, er erlaubt SSL-Verbindungen, auch das Starten mit --SSL funktionier ohne Probleme. Es sind sowohl "have_ssl", als auch "have_openssl" auf "true".


----------



## saftmeister (29. April 2012)

Je mehr ich darüber lese, um so unklarer wird die Situation bezüglich der Ports. Offensichtlich ist diese Information mit dem Port 3430 quatsch, denn MySQL scheint auch die SSL-Verbindungen über Port 3306 abzuwickeln, also Kommando "Reture" :-(

Wie schon erwähnt, ist es erstmal sinnvoll, sich darüber zu informieren, ob der MySQL-Server derzeit überhaupt SSL supported. Ich bekomme an der Command-Line jetzt den Fehler "ERROR 2026 (HY000): SSL connection error", die Ausgabe von SHOW GLOBAL... sieht jetzt bei mir so aus:


```
have_openssl 	YES
have_ssl 	YES
ssl_ca 	C:/Program Files/MySQL/MySQL Server 5.1/cert/ca-ce...
ssl_capath 	
ssl_cert 	C:/Program Files/MySQL/MySQL Server 5.1/cert/serve...
ssl_cipher 	
ssl_key 	C:/Program Files/MySQL/MySQL Server 5.1/cert/serve...
```

Grundsätzlich bietet mir mein Server also an, SSL-Verbindungen aufzubauen. Ich habe mir einen SSL-Benutzer angelegt, wie in der Step-by-Step-Anleitung empfohlen mit der Option "REQUIRE SSL" und das produziert den o.g. Fehler an der Kommandozeile - von phpMyAdmin mal abgesehen.

Ich habe außerdem gesehen, das es durchaus sinnvoll sein kann, mal im .err-File des MySQL-Servers zu stöbern. Das findest du im gleichen Ordner, der auch der DATA-Ordner (siehe my.ini) ist. Evtl verschiebt Windows 7 die Dateien nach C:\ProgramData\MySQL.

Ich versuche es weiter und berichte meine Erfolge/Misserfolge.

EDIT: Hier habe ich noch eine interessante Information bez. der Erstellung der Zertifikate entdeckt: http://orensol.com/2010/06/21/error-2026-hy000-ssl-connection-error-the-solution/ Es geht darum, unterschiedliche Common-Names bei der Erstellung für das Server- und das Client-Zertifikat zu verwenden.


----------



## Profiler (29. April 2012)

Okey, hab den Port wieder geändert, jetzt bekomme ich wieder den selben Fehler wie vor der Portänderung.

Ein Problem scheint mir zu sein, das ich folgendes bei _SHOW GLOBAL_ erhalte,


```
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| have_openssl  | YES   |
| have_ssl      | YES   |
| ssl_ca        |       |
| ssl_capath    |       |
| ssl_cert      |       |
| ssl_cipher    |       |
| ssl_key       |       |
+---------------+-------+
```

wenn ich in der _my.ini_ folgendes stehen hab: 


```
ssl=true
#ssl-key=/server-key.pem
#ssl-cert=/server-cert.pem
#ssl-ca=/ca-cert.pem
```

Aber wenn ich die drei Befehle entkommentiere erhalte ich folgendes:


```
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| have_openssl  | DIABLED   |
| have_ssl      | DISABLED   |
| ssl_ca        | ca-cert.pem   |
| ssl_capath    |       |
| ssl_cert      | server-cert.pem      |
| ssl_cipher    |       |
| ssl_key       | server-key.pem      |
+---------------+-------+
```

und zusätzlich noch folgende Fehlermeldung im MySQL-Errorlog:


```
SSL error: Unable to get certificate from '/server-cert.pem'
[Warning] Failed to setup SSL
[Warning] SSL error: Unable to get certificate
[Note] Event Scheduler: Loaded 0 events
```

Also scheint es ein Problem mit den Zertifikaten zu sein oder mit der Konfiguration des Servers bezüglich der Auswertung dieser. Wenn du mir deine Zertifikate zu verfügung stellen könntest, wäre es einen Versuch wert zu sehen ob sich etwas ändert.

Danke nochmal für deine ganze Hilfe 

EDIT:

Es geht noch weiter, wenn ich mit der zuletzt erwähnten Konfiguration versuche den Server mit mysql.exe --ssl zu starten bekomme ich folgenden Fehler:


```
ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061)
```

Also scheint es mir nie richtig gelungen zu sein, den Server in der richtigen Konfiguration, im _SSL-Mode_ zu starten. Jetzt stellt sich nur die Frage, wie man diesen Fehler behebt.


----------



## saftmeister (29. April 2012)

Du müsstest den vollen Pfad zu den Zertifikaten angeben. Je nach dem, wo sie abgelegt sind. Wenn ich dir meine Zertifikate zur Verfügung stelle, wird das dein spezielles Problem nicht beheben.

Ich habe meine Zertifikate innerhalb des Installationsordners von MySQL abgelegt. Der zeigt nach "C:/Program Files/MySQL/MySQL Server 5.1/", dort habe ich den Ordner "cert" erstellt und darin meine Zertifikate abgelegt. In der my.ini steht in der Sektion "mysqld" dann 


```
ssl-ca		= "C:/Program Files/MySQL/MySQL Server 5.1/cert/ca-cert.pem"
ssl-cert	= "C:/Program Files/MySQL/MySQL Server 5.1/cert/server-cert.pem"
ssl-key		= "C:/Program Files/MySQL/MySQL Server 5.1/cert/server-key.pem"
```

EDIT: Nach dem ich meinen MySQL-Server auf Version 5.5.23 angehoben habe (aktuellste Version) habe ich mittlerweile eine andere Fehlermeldung:



> ERROR 2026 (HY000): SSL connection error: protocol version mismatch



Wenn man danach googled, bekommt man nur sehr wenig Einträge mit dieser Meldung, alle zeigen auf einen Bug in MySQL: http://bugs.mysql.com/bug.php?id=64870

Ich denke, wir sind hier an einem Punkt angelangt, bei dem sich MySQL partout dagegen wehrt, Verbindungen über SSL anzunehmen. Ich habe keine weiteren Ideen mehr.


----------



## Profiler (29. April 2012)

Die Pfade sind in Wirklichkeit auch angegeben, ich hab sie nur hier weggelassen, damits übersichtlicher wird. Ich werde es noch weiter Versuchen, aber kennst du vielleicht Alternativen?

Zum Beispiel über Tomcat, eine serverseitige Java-Applikation und dann die normale "Java-SSL"-Library für die sichere Verbindung nutzen?

Auch wenn das Problem noch besteht, großen Danke für deine Hilfe


----------



## saftmeister (29. April 2012)

Wenn die Pfade bei dir passen, der MySQL-Server aber sagt, das er den Private-Key nicht laden konnte, könnte diese bereits von mir vorgeschlagene Seite weiterhelfen: http://forums.mysql.com/read.php?11,400856,401127#msg-401127


----------



## Profiler (29. April 2012)

Hab ich auch schon überprüft, ist alles so wie's sein sollte. Habs auch zum Testen mal geändert hat aber nichts bewirkt.


----------

