未加星标

Unable to connect socket.io in node.js with tls

字体大小 | |
[前端(javascript) 所属分类 前端(javascript) | 发布者 店小二05 | 时间 2018 | 作者 红领巾 ] 0人收藏点击收藏

I have googled and search in stackoverflow, any thread related to socket.io+tls, or node.js +tls, or ssl, an so on... but I cannot find any way of building what I need:

Anode.jsserver connected to the client through socket.io and using tls (only server authentication is needed)

So far I have connect the server and the client without using tls.

When I create my node.js server (listening at port 3000) and using tls I can use the command:

openssl s_client -connect localhost:3000

and everthing seems to be ok, but went I try to connect my socket.io client I got always an error.

Here is my simple server code:

var tls = require('tls'); var fs = require('fs'); var options = { key: fs.readFileSync('evServer-key.pem'), cert: fs.readFileSync('evServer-cert.pem'), requestCert: false, }; var server = tls.createServer(options, function(cleartextStream) { console.log('server connected', cleartextStream.authorized ? 'authorized' : 'unauthorized'); cleartextStream.write("welcome!\n"); cleartextStream.setEncoding('utf8'); cleartextStream.pipe(cleartextStream); }); io = require('socket.io').listen(server); server.listen(3000, function() { console.log('server bound'); }); io.sockets.on('connection', function (socket) { // When new users join socket.on('join', function (data, fn) { console.log("User connected"); socket.set('socketname', 'name', function () { socket.emit('Connection received') ; // for the current socket }); }); // --------------- client events socket.on('clientjoin', function (data) { client_socket = socket; console.log("BT Client joined"); }); socket.on('hello', function (data) { client_socket = socket; console.log("Hello received"); socket.emit('Hi there!'); }); // When a client disconnects socket.on('disconnect', function () { socket.get('nickname', function (err, nickname) { console.log(nickname + " logged out") }); }); });

and this is the connection in the client:

socket = new SocketIO("http://"+this.serverIpAddress+":3000/");

If I use:

http://localhost:3000

I get a connection refuse error:

02-22 15:37:41.702: W/System.err(621): io.socket.SocketIOException: Error while handshaking 02-22 15:37:41.702: W/System.err(621): at io.socket.IOConnection.handshake(IOConnection.java:322) 02-22 15:37:41.702: W/System.err(621): at io.socket.IOConnection.access$600(IOConnection.java:39) 02-22 15:37:41.702: W/System.err(621): at io.socket.IOConnection$ConnectThread.run(IOConnection.java:199) 02-22 15:37:41.702: W/System.err(621): Caused by: java.net.ConnectException: localhost/127.0.0.1:3000 - Connection refused 02-22 15:37:41.702: W/System.err(621): at org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:207) 02-22 15:37:41.712: W/System.err(621): at org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:437) 02-22 15:37:41.712: W/System.err(621): at java.net.Socket.connect(Socket.java:983) 02-22 15:37:41.712: W/System.err(621): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>(HttpConnection.java:75) 02-22 15:37:41.712: W/System.err(621): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>(HttpConnection.java:48) 02-22 15:37:41.712: W/System.err(621): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection$Address.connect(HttpConnection.java:322) 02-22 15:37:41.712: W/System.err(621): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnectionPool.get(HttpConnectionPool.java:89) 02-22 15:37:41.712: W/System.err(621): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getHttpConnection(HttpURLConnectionImpl.java:285) 02-22 15:37:41.712: W/System.err(621): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.makeConnection(HttpURLConnectionImpl.java:267) 02-22 15:37:41.712: W/System.err(621): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.retrieveResponse(HttpURLConnectionImpl.java:1018) 02-22 15:37:41.712: W/System.err(621): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:512) 02-22 15:37:41.742: W/System.err(621): at io.socket.IOConnection.handshake(IOConnection.java:313) 02-22 15:37:41.742: W/System.err(621): ... 2 more 02-22 15:37:41.742: I/io.socket(621): Cleanup 02-22 15:55:57.352: I/dalvikvm(621): Jit: resizing JitTable from 512 to 1024 02-22 16:00:54.763: I/AsyncTask(621): onPreExecute 02-22 16:00:54.772: I/ClientActivity(621): C: Connecting... 02-22 16:00:54.782: I/AsyncTask(621): onPostExecute: Completed. 02-22 16:00:54.792: I/AsyncTask(621): an Error occured 02-22 16:00:54.792: W/System.err(621): io.socket.SocketIOException: Error while handshaking . . .

and if I use

https://localhost:3000

I get this other null pointer error:

02-22 16:06:06.432: I/AsyncTask(666): onPreExecute 02-22 16:06:06.442: I/ClientActivity(666): C: Connecting... 02-22 16:06:06.503: I/AsyncTask(666): onPostExecute: Completed. 02-22 16:06:06.512: I/AsyncTask(666): an Error occured 02-22 16:06:06.512: W/System.err(666): io.socket.SocketIOException: Error while handshaking 02-22 16:06:06.512: W/System.err(666): at io.socket.IOConnection.handshake(IOConnection.java:322) 02-22 16:06:06.512: W/System.err(666): at io.socket.IOConnection.access$600(IOConnection.java:39) 02-22 16:06:06.512: W/System.err(666): at io.socket.IOConnection$ConnectThread.run(IOConnection.java:199) 02-22 16:06:06.523: W/System.err(666): Caused by: java.lang.NullPointerException 02-22 16:06:06.523: W/System.err(666): at io.socket.IOConnection.handshake(IOConnection.java:301) 02-22 16:06:06.523: W/System.err(666): ... 2 more

I have tried also writing my external IP address instead of localhost or 127.0.0.1 but it still does not work, is it impossible what I want to do? any idea or advise?

Thank you in advance.

UPDATE:

I have been working on it but I do not achieve to connect client and server yet. What I have tried in the client side (android), as I am using Gottox's socket.io library and I could not use the solution proposed by user568109, is to add this to my client's code:

CertificateFactory cf = CertificateFactory.getInstance("X.509"); InputStream caInput = new BufferedInputStream(new FileInputStream("/sdcard/cacert.crt")); Certificate ca; try { ca = cf.generateCertificate(caInput); } finally { caInput.close(); } // Create a KeyStore containing our trusted CAs String keyStoreType = KeyStore.getDefaultType(); KeyStore keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(null, null); keyStore.setCertificateEntry("ca", ca); SocketIO.setDefaultSSLSocketFactory(SSLContext.getInstance("SSL")); socket = new SocketIO("https://"+this.serverIpAddress+":3000/");

Where, cacert.crt is a certificate of a certification authority that I have created and that I have used to sign the key of the server.

I can connect with the web browser to my server through https without problem but my android application throws the following error:

02-26 16:39:18.420: I/AsyncTask(27913): onPreExecute 02-26 16:39:18.420: I/ClientActivity(27913): C: Connecting... 02-26 16:39:18.445: E/ClientActivity(27913): C: Error 02-26 16:39:18.445: E/ClientActivity(27913): java.security.cert.CertificateException: org.apache.harmony.security.asn1.ASN1Exception: ASN.1 sequence identifier expected at [0], got 43 02-26 16:39:18.445: E/ClientActivity(27913): at org.apache.harmony.security.provider.cert.X509CertImpl.<init>(X509CertImpl.java:106) 02-26 16:39:18.445: E/ClientActivity(27913): at org.apache.harmony.security.provider.cert.X509CertFactoryImpl.getCertificate(X509CertFactoryImpl.java:656) 02-26 16:39:18.445: E/ClientActivity(27913): at org.apache.harmony.security.provider.cert.X509CertFactoryImpl.engineGenerateCertificate(X509CertFactoryImpl.java:109) 02-26 16:39:18.445: E/ClientActivity(27913): at java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:195) 02-26 16:39:18.445: E/ClientActivity(27913): at com.android.locaalton.CommTask.doInBackground(CommTask.java:61) 02-26 16:39:18.445: E/ClientActivity(27913): at com.android.locaalton.CommTask.doInBackground(CommTask.java:1) 02-26 16:39:18.445: E/ClientActivity(27913): at android.os.AsyncTask$2.call(AsyncTask.java:287) 02-26 16:39:18.445: E/ClientActivity(27913): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) 02-26 16:39:18.445: E/ClientActivity(27913): at java.util.concurrent.FutureTask.run(FutureTask.java:137) 02-26 16:39:18.445: E/ClientActivity(27913): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 02-26 16:39:18.445: E/ClientActivity(27913): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) 02-26 16:39:18.445: E/ClientActivity(27913): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569) 02-26 16:39:18.445: E/ClientActivity(27913): at java.lang.Thread.run(Thread.java:856) 02-26 16:39:18.445: E/ClientActivity(27913): Caused by: org.apache.harmony.security.asn1.ASN1Exception: ASN.1 sequence identifier expected at [0], got 43 02-26 16:39:18.445: E/ClientActivity(27913): at org.apache.harmony.security.asn1.BerInputStream.expected(BerInputStream.java:464) 02-26 16:39:18.445: E/ClientActivity(27913): at org.apache.harmony.security.asn1.BerInputStream.readSequence(BerInputStream.java:502) 02-26 16:39:18.445: E/ClientActivity(27913): at org.apache.harmony.security.asn1.DerInputStream.readSequence(DerInputStream.java:105) 02-26 16:39:18.445: E/ClientActivity(27913): at org.apache.harmony.security.asn1.ASN1Sequence.decode(ASN1Sequence.java:40) 02-26 16:39:18.445: E/ClientActivity(27913): at org.apache.harmony.security.asn1.ASN1Type.decode(ASN1Type.java:91) 02-26 16:39:18.445: E/ClientActivity(27913): at org.apache.harmony.security.provider.cert.X509CertImpl.<init>(X509CertImpl.java:101) 02-26 16:39:18.445: E/ClientActivity(27913): ... 12 more

Any idea about this new issue?

Problem courtesy of: Javi

Solution

The solution to my update is to create a certification authority, use it to sign the certificates of the server and also install the certificate in the android phone.

After solving that I had to face new problems, the ones treated here:

https://github.com/Gottox/socket.io-java-client/issues/14

The solution is also inside the link

Hope this helps someone!

Solution courtesy of: Javi

Discussion

Web sockets can be unencrypted ws:// or encrypted wss:// (ws+ssl). Socket.io allows to choose between the two using the secure option like this:

<script src="http://localhost:3000/socket.io/socket.io.js"></script> socket = io.connect('http://localhost:3000', {secure:true}); //encrypted socket = io.connect('http://localhost:3000', {secure:false}); //unencrypted

This should do all your websocket encryption requirements. Whatever errors you are getting are because you are trying to use your tls server as http/https server. openssl s_client -connect localhost:3000 is the right way to access it. http://localhost:3000 will require http server running at that address, but your server is tls ( http://nodejs.org/api/tls.html#tls_tls_ssl ).

You should use it as https server. It is a subclass of tls.Server and emits events same as http.Server. http://nodejs.org/api/https.html#https_class_https_server

var https = require('https'); //tls changed to https var server = https.createServer(options, function(cleartextStream) { console.log('server connected',

Your server is now https and your https://localhost:3000 should work. Try connecting to it using openssl s_client to check if it is working.

Update after comment

user1249517 you should specify the source of errors when asking the question. You tagged it under node.js ,ssl and socket.io but it should have been java, android and socket. socket.io is javascript library whereas you are using gottox java library for socket.io.

Anyways, when you use browser to view the site, the certificates are managed by browser itself, when you use java app, it should handle the certificates. The error that you are getting :

Caused by: org.apache.harmony.security.asn1.ASN1Exception: ASN.1 sequence identifier expected at [0], got 43

ASN.1 is a encoding format for X.509 certificates. ASN.1 sequence identifier expected would mean that your certificate is corrupt/invalid ASN.1 format. You should not use your certificate directly but convert it to ASN.1 format with openssl . Try something like this .

openssl asn1parse -in mycert.pem

Specify the input format of the certficate and validate it before parsing. If all certificates are valid, then there is some error in the code.

Discussion courtesy of: user568109

This recipe can be found in it's original form on Stack Over Flow .

本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程

代码区博客精选文章
分页:12
转载请注明
本文标题:Unable to connect socket.io in node.js with tls
本站链接:https://www.codesec.net/view/621250.html


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 前端(javascript) | 评论(0) | 阅读(32)