TLS Error: socket hang up in nodejs - node.js

I'am trying to connect on a server using tls in nodejs. Here is my code :
var options = {
rejectUnauthorized: false //self signed certificate
};
co = require("tls").connect(5200, "my_host", options, function(){
co.on("data", function(data) {
//do domething
})
}
This is simplified code. If I catch the error event, I have a ECONNRESET error, if I don't, I've got this trace :
Error: socket hang up
at SecurePair.error (tls.js:1001:23)
at EncryptedStream.CryptoStream._done (tls.js:697:22)
at EncryptedStream.read [as _read] (tls.js:493:12)
at EncryptedStream.Readable.read (_stream_readable.js:320:10)
at CleartextStream.onCryptoStreamFinish (tls.js:301:47)
at CleartextStream.g (events.js:175:14)
at CleartextStream.EventEmitter.emit (events.js:92:17)
at finishMaybe (_stream_writable.js:354:12)
at endWritable (_stream_writable.js:361:3)
at CleartextStream.Writable.end (_stream_writable.js:339:5)
If I connect directly to my server using openssl s_client -connect my_host:5200 it works great. Strange thing, with node version 0.10.*, it works on ubuntu 10.04, but not on my mac neither on ubuntu 12.04. My server is also a nodejs program running ubuntu 10.04. Not sure if all of this is related but any help would be great !
Cheers

Depending on what your client/server are doing, there may be a timing issue here. You want to set your event-handlers outside the callback to ensure they are setup before data is flowing. Try this:
var options = {
rejectUnauthorized: false //self signed certificate
};
co = require("tls").connect(5200, "my_host", options, function(){
//do something
});
co.on("data", function(data) {
//do something
});

Related

process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0 not working

I'm using the node sendmail package which is giving me this error:
Error on connectMx for: Error: self signed certificate
at TLSSocket.onConnectSecure (_tls_wrap.js:1515:34)
at TLSSocket.emit (events.js:400:28)
at TLSSocket._finishInit (_tls_wrap.js:937:8)
at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:709:12) {
code: 'DEPTH_ZERO_SELF_SIGNED_CERT'
}
So I put this in my code in like 5 places
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;
Node says this warning when I run it:
Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
Yet I still get the error message. It's coming from this code:
const {createConnection} = require('net');
createConnection(smtpPort, data[i].exchange); // problem code
sock.on('error', function (err) {
logger.error('Error on connectMx for: ', data[i], err);
tryConnect(++i)
});
Is this a bug in NodeJS, or am I messing something up? Thanks for the help.

Random SSL handshake error when connecting to ElastiCache with ioRedis

I am attempting to connect to an ElastiCache cluster that is encrypted in transit from a node script using ioRedis. Sometimes my script works, other times I get Error: 140736319218624:error:140940E5:SSL routines:ssl3_read_bytes:ssl handshake failure:../deps/openssl/openssl/ssl/s3_pkt.c:1216:
Here is all of my code:
var Redis = require('ioredis');
var nodes = [{
host: 'clustercfg.name.xxxxxx.region.cache.amazonaws.com',
port: '6379',
}];
var cluster = new Redis.Cluster(nodes,{
redisOptions: {
tls: {}
}});
cluster.set('aws', 'test');
cluster.get('aws', function (err, res) {
console.log(res);
if (err) {
console.error(err)
}
cluster.disconnect()
});
I believe the ssl handshake error is a side-effect of a race-condition bug in ioredis.
I have been banging my head over the same issue the last several days (ioredis version 4.0.0). I just couldn't reliably connect ioredis to our elasticache cluster. I would see the same intermittent error.
Error: 140618195700616:error:140940E5:SSL routines:ssl3_read_bytes:ssl
handshake failure:../deps/openssl/openssl/ssl/s3_pkt.c:1216:
You can view ioredis debug output by setting "DEBUG=ioredis:*" in your node environment. Once I did this I could see that when the error occurred it was accompanied by several messages similar to the following:
2018-10-06T18:24:38.287Z ioredis:cluster:connectionPool Disconnect
xxx.usw2.cache.amazonaws.com:6379 because the node does not hold any
slot
I tried node-redis and redis-clustr it works fine with elasticache.

Node: Can't bind to IPv6 localAddress while using https.request()

I can bind to localAddress just fine when using HTTP, but as soon as I switch to HTTPS I get an error: bind EINVAL. Please consider this code:
var http = require('http');
var https = require('https');
var options = { host:'icanhazip.com',path:'/',localAddress:'2604:a880:1:20::27:a00f',family:6 };
callback = function(response) {
var data = '';
response.on('data',function(chunk) { data+= chunk; });
response.on('error',function(error) { console.log("error: "+error.message); });
response.on('end',function() {
console.log(data);
});
}
http.request(options,callback).end(); // Works. IP:2604:a880:1:20::27:a00f
https.request(options,callback).end(); // Fails. IP:2604:a880:1:20::27:a00f
https.request({host:'icanhazip.com',path:'/',family:6},callback).end(); // Works. IP:2604:a880:1:20::27:a00f
Here's the error while running node v5.0.0:
Error: bind EINVAL 2604:a880:1:20::27:a00f
at Object.exports._errnoException (util.js:860:11)
at exports._exceptionWithHostPort (util.js:883:20)
at connect (net.js:809:16)
at net.js:984:7
at GetAddrInfoReqWrap.asyncCallback [as callback] (dns.js:63:16)
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:82:10)
The only difference between the working and the failing code is setting localAddress and ironically, the last example binds to the correct IP address, but won't let you do it using localAddress.
The problem here is I have to make a request from a completely separate IPv6 address under my use case, and it works fine with HTTP but I need this to work for HTTPS requests. Currently I can only make this work while using cURL. Could you please provide some insight as to why this is happening or how I could make this work without additional libraries?
I had same issue as you. Figured it out. Update your node to the latest stable. They fixed it. Check it with node --version I'm on 6.6.0 and it works great.
The version I got from doing an apt-get was way too old.

intern 2 configuration for BrowserStack behind a proxy

I'm unsure what the configuration should be running intern 2 tests against BrowserStack when running behind a proxy/firewall and currently seeing errors/timeouts.
My Current configuration is:
proxyPort : 9000,
proxyUrl : 'http://localhost:9000',
tunnel : 'BrowserStackLocal',
tunnelOptions : {
username : 'myusername',
accessKey : 'myaccesskey',
hostname : '<myproxyip>',
proxy : 'http://<myproxyip>:<myproxyport>'
}
I don't think I need hostname however if I remove that I immediately see the error getaddrinfo ENOTFOUND.
If use the above configuration it seems to get further, waits for a while then see:
Listening on 0.0.0.0:9000
Starting tunnel...
BrowserStackLocal v3.3
Connecting to BrowserStack using WebSocket protocol...
Connected.
Ready
Error: [POST http://(redacted)#<myproxyip>:4444/wd/hub/session] connect ETIMEDOUT
Error: connect ETIMEDOUT
at errnoException <net.js:904:11>
at Object.afterConnect [as oncomplete] <net.js:895:19>
FATAL ERROR
Error: [POST http://(redacted)#<myproxyip>:4444/wd/hub/session] connect ETIMEDOUT
Error: connect ETIMEDOUT
at errnoException <net.js:904:11>
The [POST http://(redacted)#<myproxyip>:4444/wd/hub/session] url doesn't seem right. Obviously I have this misconfigured & would appreciate any advice. I do struggle to understand intern's documentation when running behind a proxy.
It looks like you are behind some kind of proxy.
When you are behind proxy server, in order to use Intern with BrowserStack, you need to do two things:
Get Local Testing connection to work with your proxy, which you are doing, and you can see success message.
You have to make sure the node process that runs the Intern test works with your proxy. To enable proxy in a node application, the easiest option is to use global-tunnel npm package. There is a step-by-step guide available here.
Would love to answer any queries you might have! Do drop in a mail at support#browserstack.com
Umang,
BrowserStack Support.
I'm not sure but I think there is a bug in browserStack.js. Some proxy support is missing there I think. When I use configuration browserstack_conf.js as shown below tests run okay but there is an error message when Browserstack tries to publish the test results back to www.browserstack.com
[09:43:06] E/launcher - connect ETIMEDOUT 54.152.200.70:443
[09:43:06] E/launcher - Error: connect ETIMEDOUT 54.152.200.70:443
at Object.exports._errnoException (util.js:1018:11)
at exports._exceptionWithHostPort (util.js:1041:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1090:14)
[09:43:06] E/launcher - Process exited with error code 199
I can fix this error with following steps:
npm install -g http-proxy-agent
Edit browserStack.js (located for example in C:\Users\myuser\AppData\Romaing\npm\node_modules\protractor\built\driverProviders\ add a require for this and initialize a agent and add to request.
For example add require top of browserStack.js
var HttpProxyAgent = require('http-proxy-agent');
And change the section with options to
let options = {
hostname: 'www.browserstack.com',
port: 443,
path: '/automate/sessions/' + session.getId() + '.json',
method: 'GET',
headers: headers//,
agent: new HttpProxyAgent('http://myproxy:3128')
};
I start Protractor with configuration below
// browserstack.conf.js
var browserstack = require('browserstack-local');
exports.config = {
specs: ['spec.js'],
webDriverProxy: 'http://myproxy:3128',
browserstackUser: 'myuser',
browserstackKey: '*****',
capabilities: {
project: 'BrowserStack (beyond Proxy)',
browserName: 'Chrome',
browser_version: '50.0',
os: 'OS X',
os_version: 'Yosemite',
'browserstack.local': true,
'browserstack.debug': true
},
// Code to start browserstack local before start of test
beforeLaunch: function(){
console.log("Connecting local");
return new Promise(function(resolve, reject){
exports.bs_local = new browserstack.Local();
exports.bs_local.start({'key': '*****',
'proxyHost': 'myproxy', 'proxyPort': '3128',
'binarypath': 'C:\\Users\\myuser\\Downloads\\BrowserStackLocal-win32\\BrowserStackLocal.exe'},
function(error) {
if (error) return reject(error);
console.log('Connected. Now testing...');
resolve();
});
});
},
// Code to stop browserstack local after end of test
afterLaunch: function(){
return new Promise(function(resolve, reject){
exports.bs_local.stop(resolve);
});
}
};

Node.js getaddrinfo ENOTFOUND

When using Node.js to try and get the html content of the following web page:
eternagame.wikia.com/wiki/EteRNA_Dictionary
I get the following error:
events.js:72
throw er; // Unhandled 'error' event
^
Error: getaddrinfo ENOTFOUND
at errnoException (dns.js:37:11)
at Object.onanswer [as oncomplete] (dns.js:124:16)
I did already look up this error on stackoverflow, and realized that this is because node.js cannot find the server from DNS (I think). However, I am not sure why this would be, as my code works perfectly on www.google.com.
Here is my code (practically copied and pasted from a very similar question, except with the host changed):
var http = require("http");
var options = {
host: 'eternagame.wikia.com/wiki/EteRNA_Dictionary'
};
http.get(options, function (http_res) {
// initialize the container for our data
var data = "";
// this event fires many times, each time collecting another piece of the response
http_res.on("data", function (chunk) {
// append this chunk to our growing `data` var
data += chunk;
});
// this event fires *one* time, after all the `data` events/chunks have been gathered
http_res.on("end", function () {
// you can use res.send instead of console.log to output via express
console.log(data);
});
});
Here is the source where I copied and pasted from : How to make web service calls in Expressjs?
I am not using any modules with node.js.
Thanks for reading.
In Node.js HTTP module's documentation: http://nodejs.org/api/http.html#http_http_request_options_callback
You can either call http.get('http://eternagame.wikia.com/wiki/EteRNA_Dictionary', callback), the URL is then parsed with url.parse(); or call http.get(options, callback), where options is
{
host: 'eternagame.wikia.com',
port: 8080,
path: '/wiki/EteRNA_Dictionary'
}
Update
As stated in the comment by #EnchanterIO, the port field is also a separate option; and the protocol http:// shouldn't be included in the host field. Other answers also recommends the use of https module if SSL is required.
Another common source of error for
Error: getaddrinfo ENOTFOUND
at errnoException (dns.js:37:11)
at Object.onanswer [as oncomplete] (dns.js:124:16)
is writing the protocol (https, https, ...) when setting the host property in options
// DON'T WRITE THE `http://`
var options = {
host: 'http://yoururl.com',
path: '/path/to/resource'
};
in the options for the HTTP request, switch it to
var options = { host: 'eternagame.wikia.com',
path: '/wiki/EteRNA_Dictionary' };
I think that'll fix your problem.
My problem was that my OS X (Mavericks) DNS service needed to be restarted. On Catalina and Big Sur DNS cache can be cleared with:
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
Older macOS versions see here.
If you need to use https, then use the https library
https = require('https');
// options
var options = {
host: 'eternagame.wikia.com',
path: '/wiki/EteRNA_Dictionary'
}
// get
https.get(options, callback);
var http=require('http');
http.get('http://eternagame.wikia.com/wiki/EteRNA_Dictionary', function(res){
var str = '';
console.log('Response is '+res.statusCode);
res.on('data', function (chunk) {
str += chunk;
});
res.on('end', function () {
console.log(str);
});
});
I think http makes request on port 80, even though I mentioned the complete host url in options object. When I run the server application which has the API, on port 80, which I was running previously on port 3000, it worked. Note that to run an application on port 80 you will need root privilege.
Error with the request: getaddrinfo EAI_AGAIN localhost:3000:80
Here is a complete code snippet
var http=require('http');
var options = {
protocol:'http:',
host: 'localhost',
port:3000,
path: '/iso/country/Japan',
method:'GET'
};
var callback = function(response) {
var str = '';
//another chunk of data has been recieved, so append it to `str`
response.on('data', function (chunk) {
str += chunk;
});
//the whole response has been recieved, so we just print it out here
response.on('end', function () {
console.log(str);
});
}
var request=http.request(options, callback);
request.on('error', function(err) {
// handle errors with the request itself
console.error('Error with the request:', err.message);
});
request.end();
I fixed this error with this
$ npm info express --verbose
# Error message: npm info retry will retry, error on last attempt: Error: getaddrinfo ENOTFOUND registry.npmjs.org registry.npmjs.org:443
$ nslookup registry.npmjs.org
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
registry.npmjs.org canonical name = a.sni.fastly.net.
a.sni.fastly.net canonical name = prod.a.sni.global.fastlylb.net.
Name: prod.a.sni.global.fastlylb.net
Address: 151.101.32.162
$ sudo vim /etc/hosts
# Add "151.101.32.162 registry.npmjs.org` to hosts file
$ npm info express --verbose
# Works now!
Original source: https://github.com/npm/npm/issues/6686
Note that this issue can also occur if the domain you are referencing goes down (EG. no longer exists.)
in my case error was because of using incorrect host value
was
var options = {
host: 'graph.facebook.com/v2.12/',
path: path
}
should be
var options = {
host: 'graph.facebook.com',
path: path
}
so anything after .com or .net etc should be moved to path parameter value
In my case the problem was a malformed URL.
I had double slashes in the URL.
I tried it using the request module, and was able to print the body of that page out pretty easily. Unfortunately with the skills I have, I can't help other than that.
I got this error when going from development environment to production environment. I was obsessed with putting https:// on all links. This is not necessary, so it may be a solution for some.
I was getting the same error and used below below link to get help:
https://nodejs.org/api/http.html#http_http_request_options_callback
I was not having in my code:
req.end();
(NodeJs V: 5.4.0)
once added above req.end(); line, I was able to get rid of the error and worked fine for me.
Try using the server IP address rather than the hostname.
This worked for me. Hope it will work for you too.
I got rid of http and extra slash(/).
I just used this 'node-test.herokuapp.com' and it worked.
If still you are facing checkout for proxy setting, for me it was the proxy setting which were missing and was not able to make the request as direct http/https are blocked. So i configured the proxy from my organization while making the request.
npm install https-proxy-agent
or
npm install http-proxy-agent
const httpsProxyAgent = require('https-proxy-agent');
const agent = new httpsProxyAgent("http://yourorganzation.proxy.url:8080");
const options = {
hostname: 'encrypted.google.com',
port: 443,
path: '/',
method: 'GET',
agent: agent
};
I got this issue resolved by removing non-desirable characters from the password for the connection. For example, I had these characters: <##% and it caused the problem (most probably hash tag was the root cause of the problem).
My problem was we were parsing url and generating http_options for http.request();
I was using request_url.host which already had port number with domain name so had to use request_url.hostname.
var request_url = new URL('http://example.org:4444/path');
var http_options = {};
http_options['hostname'] = request_url.hostname;//We were using request_url.host which includes port number
http_options['port'] = request_url.port;
http_options['path'] = request_url.pathname;
http_options['method'] = 'POST';
http_options['timeout'] = 3000;
http_options['rejectUnauthorized'] = false;

Resources