(vernünftige) WebSockets Lib (mit SSL/TLS)

Howdy :slight_smile:

Ich nutze derzeit **java_websocket **(GitHub - TooTallNate/Java-WebSocket: A barebones WebSocket client and server implementation written in 100% Java.) in einer Serverseitigen Java-Anwendung.
Jetzt habe ich aber das Problem mittels SSL/TLS (Zertifikate vorhanden).

Clientseitig (HTML5) wird halt anstatt ws:// halt wss:// als Protokoll gesetzt, das ist ja wohl Logisch. Nur Serverseitig gibt es da einige Probleme.

Ich muss Clientseitig einen SSL-Handshake erzwingen, was grob zu sagen über den WebSocket selbst funktioniert:
Anstatt nun über Javascript die Connection zum WebSocket beispielsweise mittels wss://domain.tld:1234 zu öffnen, muss ich zuvor dem Nutzer zu https://domain.tld:1234 leiten, damit ein SSL-Handshake stattfindet.

Nur ist das ganze sehr unschön.

Ein Freund von mir (der auch die gleiche Lib bei unseren privaten Projekten nutzt) hatte zwar auch noch nie mit WSS gearbeitet gehabt, er meinte aber, dass man wohl mit einer Methode das Zertifikat setzen muss - Nur bin ich:
a.) Zu dumm die „besagte Methode“ dafür zu finden
b.) Habe beim „Hersteller/Autor“ in alle deren zur verfügung gestellten Infos auf GitHub keine nennenswerte Methode gefunden, zumal es auch dort heißt:

WSS Support
If the websocket server url is wss://localhost:8000 visit the url https://localhost:8000 with your browser. The browser will recognize the handshake and allow you to accept the certificate. This technique is also demonstrated in this video.

Also kann das ganze nun nicht stimmen, was mein Freund da sagt, zumal ich KEINE einzige Methode dafür finde, so wie er es beschrieben hat.
Ich hab ihm das bereits schon mehrfach gesagt, aber er will einfach nicht einsehen dass ich recht habe mit dem was ich nun alles schon probiert hatte - Er ist halt eher der rechthaberische Typ und will immer recht haben :smiley:

Jetzt die Special Frage:
Welche anderen Libs kann man sich auch mal anschauen die von vornerein SSL mittels Cert-Anhang funktionieren?
Mit welchen Libs nutzt ihr?

Was ist der Use-Case für so etwas?

Biete dein JS-File einfach per HTTPS an und leite die HTTP-Umfrage auf HTTPS um. Problem gelöst, oder verstehe ich da was falsch? Oder verwendest du auch auf der Client-Seite Java? (Wofür dann Websockets?)

Edit:/
Sorry, deine Frage wurde jetzt gar nicht beantwortet. :smiley:

Prinzipiell möglich ist es, siehe auch Protocol Switch. Allerdings ist das ganze SSL-Zeugs bei deiner Lib noch so neu, dass es sehr wohl sein kann, dass das nicht auf der Java-Seite unterstützt wird. Siehe die Startseite.

Ich glaube ich erklär das ganze mal ein wenig.
Ich habe vor ungefähr 2 Jahren ein SiteBuilder in PHP programmiert gehabt, der es einem Nutzer ermöglicht via Drag & Drop eine Internetseite zu erstellen.

Ich bin derzeit an einer komplett neuen Version dran und achte diesbezüglich diesmals mehr auf Performance, etc.
Im alten System was schon gut über 1 Jahr bei einem Provider läuft, habe ich Ajax genutzt gehabt um Inhalte auszutauschen damit die Seite nicht ständig reloaded wird (logisch).

Nun möchte ich zwar Ajax beibehalten, das ganze aber eher als Fallback, wenn keine WebSockets genutzt werden können.
Ich bin also derzeit daran, in Java ein WebSocket Server zu schreiben, der vorwiegend dazu genutzt werden soll, dass die Daten ausgetauscht werden (Hat halt gewisse vorteile: Schneller, es wird nur eine Connection benötigt anstatt ständig mit Ajax HTTP-Requests zu machen, etc…).

Da das System (wie das alte auch) über SSL laufen soll/muss/kann, muss natürlich dies beim WebSocket beachtet werden.

Und inwiefern ist das ein Problem? Warum willst du die Seite per HTTP anbieten aber den Websockets-Service per HTTPS? Wenn dann geht doch beides über HTTPS bzw. HTTP. Und wenn nicht würde mein oben genannter Workaround den Handshake erzwingen.

Aber prinzipiell solltest du dir die Arbeit nicht antun und das ganze noch einmal implementieren was es samt Fallback bereits gibt: Atmosphere Framework.

Guck dir mal Autobahn an http://autobahn.ws/
oder https://github.com/AsyncHttpClient/async-http-client

Den ersteren finde ich schöner hat aber probleme mit SSL, der andere läuft auf jeden Fall

Und inwiefern ist das ein Problem? Warum willst du die Seite per HTTP anbieten aber den Websockets-Service per HTTPS?

Das Problem habe ich doch geschildert. Nein es wird nie mixed Requests zwischen HTTP und HTTPS geben, ist auch gar nicht möglich ohne das der Browser irgendwelche Fehler spuckt.

Wenn dann geht doch beides über HTTPS bzw. HTTP.

Richtig, so sollte es auch sein. Entweder beides auf HTTP oder eben beides auf HTTPS.

Und wenn nicht würde mein oben genannter Workaround den Handshake erzwingen.

Es gibt ja ein „Workaround“, indem man eben die Webseite über https aufruft und gleichzeitig den WebSocket Port mit angibt, wie aber bereits im Eingangspost beschrieben ist dies ein eher blöder Workaround. Ich will nicht ständig den Nutzer dafür Redirecten lassen, wenn er die Seite „betritt“.

Danke @EagleEye , hier gibt es aber auch wieder „probleme“.
Autobahn.ws ist anscheinend was Node.js-Mäßiges, richtig? Ich möchte gerne Serverseitig Java verwenden und kein JS/Node.js
async-HTTP-Client ist auch wiederrum komplett Java. Clientseitig im Browser soll ausschließlich HTML5/JS/CSS3 genutzt werden. Außerdem ist hier die Frage in wie fern die WebSocket-Protokolle unterstützt werden. Ich möchte ungern mich darum kümmern.

Abgesehen davon, dass das den Browser nicht ein bisschen juckt wenn das per JS passiert (bei einem trusted Zertifikat allerdings), check’ ich das Problem nach wie vor nicht. Wenn’s von Anfang an eh HTTP bzw. HTTPS ist, dann ist der Handshake sowieso schon erledigt. Irgendwoher muss das Javascript ja kommen dass dann die Websocket-Kommunikation abwickelt. Und das wird dann ja eh per HTTP bzw. HTTPS ausgeliefert.

Im JS selbst kannst du dann prüfen ob der Benutzer gerade auf einer HTTP bzw. HTTPS Seite ist und dementsprechend den richtigen Socket für die Verbindung wählen. Der Handshake ist da doch schon lang erledigt? (Abgesehen davon, dass die ganze Problematik bei einem nicht self-signed Zertifikat sowieso keine Rolle spielen sollte.)

Warum nicht? Das wäre am saubersten. Dann hättest du immer eine HTTPS-Kommunikation so garantierst du einen Mindeststandard an Sicherheit und kannst dir sicher sein, dass nicht irgendwelche Token in den POST-Requests abgegriffen werden.

Hast du dir das Atmosphere schon angeschaut?

nein Autobahn gibts auch für JS ist aber plain Java :wink:

Der Handshake ist da doch schon lang erledigt?

Vom Webbrowser beim laden der Seite ja, aber nicht für des WebSocket.
Hier muss ich beispielsweise per Redirect (.htaccess/VHost) den Nutzer mittels HTTPS & Port des Websockets weiterleiten, hörst du mir nicht zu?

(Abgesehen davon, dass die ganze Problematik bei einem nicht self-signed Zertifikat sowieso keine Rolle spielen sollte.)

Es spielt hier überhaupt keine Rolle ob selfsigned oder nicht. Wir können davon ausgehen das des Zertifikat nicht selfsigned ist.

Warum nicht? Das wäre am saubersten. Dann hättest du immer eine HTTPS-Kommunikation so garantierst du einen Mindeststandard an Sicherheit und kannst dir sicher sein, dass nicht irgendwelche Token in den POST-Requests abgegriffen werden.

Was soll an den anderen Methoden denn nicht sicher/unsicher sein? Es wird doch jedeglich nur festgelegt WIE der Handhake zur Stande kommt, und das soll definitiv nicht per Redirect auf den WSS-Port geschehen.
Generell kann man davon ausgehen: Entweder das System läuft immer auf HTTPS oder eben immer nur auf HTTP. Entweder oder. Was anderes gibt es nicht. Nur entscheide ich nicht, für welches Verfahren man sich entscheidet. Dies entscheided der Hosting-Provider, also unsere Kunden.

Hast du dir das Atmosphere schon angeschaut?

Ja, kommt aber nicht in Frage. Verständlich wenn ich nun sagen würde „Unsinnig ganze Frameworks einzubinden wo man von jedem Framework immer nur eine Funktion benötigt“.
Das ganze wird auch Mobil genutzt, ich kann es mir nicht leisten, dass 5.000 Scripts/Stylesheets geladen werden.

*** Edit ***

Habs nun.

nach ein wenig fummeln, funktioniert’s - Auch mit meiner Lib.
Leider existieren sehr wenige Infos dadrüber:

public void setSSL() {
		String ssl_password						= config.getString("ssl_password"); // SLL Passphrase/Password

		try {
			KeyStore store						= KeyStore.getInstance("PKCS12");
			File keyFile						= new File(config.getString("ssl_certificate")); // File to .p12 Cert
			store.load(new FileInputStream(keyFile), ssl_password.toCharArray());
	
			KeyManagerFactory keyFactory		= KeyManagerFactory.getInstance("SunX509");
			keyFactory.init(store, ssl_password.toCharArray());
			TrustManagerFactory trustFactory	= TrustManagerFactory.getInstance("SunX509");
			trustFactory.init(store);
	
			SSLContext sslContext = SSLContext.getInstance(config.getString("ssl_type")); // SSL or TLS
			sslContext.init(keyFactory.getKeyManagers(), trustFactory.getTrustManagers(), null);
			DefaultSSLWebSocketServerFactory fac = new DefaultSSLWebSocketServerFactory(sslContext);
			setWebSocketFactory(fac);
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

Nope. Ich lese :wink:

Ich hatte angenommen, dass das Zertifikat auch für den anderen Port als angenommen gilt wenn der Benutzer die Seite geladen hat, da das Zertifikat sich ja nicht ändert. Das war mein Denkfehler.

Wobei es mich nach wie vor wundert warum das bei dir nicht geht. Das simple Echo-Test-Skript hier funktioniert problemlos auch mit WSS.

Indem Fall wäre es schon sinnvoll, da du so den ganzen Client seitigen Code bereits getestet bekämst u. nicht selbst schreiben müsstest. Aber wenn er dir zu groß ist, ist das OK. Da das ganze Framework nur den Zweck der Server/Client-Kommunikation hat, hätte ich es jetzt nicht als zu groß eingeordnet. Aber das ist deine Sache.

Edit:/
Passt, Problem gelöst.

Wobei es mich nach wie vor wundert warum das bei dir nicht geht. Das simple Echo-Test-Skript hier funktioniert problemlos auch mit WSS.

Ja, weil des wohl auch das Zertifikat Serverseitig „beigefügt“ wird (was ich ja nurch meinen letzen Post auch hinbekommen habe).

Indem Fall wäre es schon sinnvoll, da du so den ganzen Client seitigen Code bereits getestet bekämst u. nicht selbst schreiben müsstest.

Clientseitig ist/war ja auch nie das Problem vorhanden. Ich arbeite damit ja schon etwas länger, nur halt eben Serverseitig mit SSL war mir noch Neuland.

Passt, Problem gelöst.

Genau :slight_smile: