Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Can't bind to IPv6 localAddress while using https.request() #4139

Closed
jaggedsoft opened this issue Dec 3, 2015 · 11 comments
Closed

Bug: Can't bind to IPv6 localAddress while using https.request() #4139

jaggedsoft opened this issue Dec 3, 2015 · 11 comments
Labels
https Issues or PRs related to the https subsystem.

Comments

@jaggedsoft
Copy link

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 here? Please help! ♥️

@jaggedsoft jaggedsoft changed the title Possible Bug: Binding to IPv6 localAddress while using HTTPS Possible Bug: Can't bind to IPv6 localAddress while using https.request() Dec 3, 2015
@jaggedsoft jaggedsoft changed the title Possible Bug: Can't bind to IPv6 localAddress while using https.request() Bug: Can't bind to IPv6 localAddress while using https.request() Dec 3, 2015
@mscdex mscdex added the https Issues or PRs related to the https subsystem. label Dec 4, 2015
@jaggedsoft
Copy link
Author

Here's some working code using node-libcurl just to prove I'm not crazy:

var Curl = require('node-libcurl').Curl, curl = new Curl();
curl.setOpt(Curl.option.URL,'https://icanhazip.com');
curl.setOpt(Curl.option.INTERFACE, '2604:a880:1:20::27:a00f');
curl.setOpt(Curl.option.IPRESOLVE, 2);
curl.setOpt(Curl.option.FOLLOWLOCATION, 1);
curl.setOpt(Curl.option.DNS_CACHE_TIMEOUT, 86400);
curl.on('end',function(statusCode, data, headers) {
    //console.info( statusCode );
    console.info(data);
    console.info(this.getInfo( 'TOTAL_TIME'));
    this.close();
});
curl.on('error', curl.close.bind(curl));
curl.perform();

_HTTPS https.request() only has the issue when using IPv6. HTTP http.request() and localAddress work fine._

@evanlucas
Copy link
Contributor

Possibly related to #3625

@jasnell
Copy link
Member

jasnell commented Apr 22, 2016

@nodejs/crypto

@bnoordhuis
Copy link
Member

The EINVAL error most likely means that you need to specify the interface to bind to, e.g. 2604:a880:1:20::27:a00f%eth0 instead of just 2604:a880:1:20::27:a00f. I suspect libcurl simply tries interfaces until it finds one that accepts the address but node doesn't do that for you.

@jaggedsoft
Copy link
Author

jaggedsoft commented May 24, 2016

@bnoordhuis, thanks for the suggestion. Didn't know you could do that. However, I can confirm that on node v5.5.0 and v6.2.0 that doesn't work: (eth0 is correct)

events.js:160
      throw er; // Unhandled 'error' event
      ^

Error: bind EINVAL 2604:a880:1:20::27:a006%eth0
    at Object.exports._errnoException (util.js:953:11)
    at exports._exceptionWithHostPort (util.js:976:20)
    at connect (net.js:839:18)
    at net.js:1003:7
    at GetAddrInfoReqWrap.asyncCallback [as callback] (dns.js:65:16)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:84:10)
var https = require('https');
var options = { host:'icanhazip.com',path:'/',localAddress:'2604:a880:1:20::27:a006%eth0',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);
  });
}
https.request(options,callback).end();

@bnoordhuis
Copy link
Member

@jaggedsoft Can you post the output of strace -e bind node script.js?

(I assume you're using Linux because the interface is eth0.)

@jaggedsoft
Copy link
Author

jaggedsoft commented May 25, 2016

Hi @bnoordhuis,
The only difference I see is +++ exited with 1 +++

strace -e bind node ipv6.js
events.js:160
      throw er; // Unhandled 'error' event
      ^

Error: bind EINVAL 2604:a880:1:20::27:a00f%eth0
    at Object.exports._errnoException (util.js:953:11)
    at exports._exceptionWithHostPort (util.js:976:20)
    at connect (net.js:839:18)
    at net.js:1003:7
    at GetAddrInfoReqWrap.asyncCallback [as callback] (dns.js:65:16)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:84:10)
+++ exited with 1 +++

Running Node v6.2.0 and Debian:
Linux 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt20-1+deb8u4 (2016-02-29) x86_64 GNU/Linux

Thank you for helping to look into this. Here is the output when I use 'http' instead of 'https' module:

strace -e bind node ipv6.js
bind(12, {sa_family=AF_INET6, sin6_port=htons(0), inet_pton(AF_INET6, "2604:a880:1:20::27:a00f", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
request took: 121.931ms
http works, returned ip: 2604:a880:1:20::27:a00f

+++ exited with 0 +++

@bnoordhuis
Copy link
Member

Okay, can you try strace -e \!mmap,munmap,mprotect,brk,futex,rt_sigaction node script.js? Add -o trace.log to write it to a file.

@jaggedsoft
Copy link
Author

jaggedsoft commented May 25, 2016

@bnoordhuis Good luck with this, and thank you again for your help:
http://pastebin.com/raw/QtquexbR

Edit: I also tried process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; with the same result.

@bnoordhuis
Copy link
Member

It turns out this is the same bug as #6440, for which I have a fix in #6654. Unfortunately, that pull request is blocked on CI configuration issues.

@jaggedsoft
Copy link
Author

Excellent! Been wondering about this for 7 months, and @bnoordhuis comes to the rescue and solves the problem in a day. Thank you!! 👍

Fishrock123 pushed a commit to Fishrock123/node that referenced this issue May 30, 2016
Respect the `{ family: 6 }` address family property when connecting to
a remote peer over TLS.

Fixes: nodejs#4139
Fixes: nodejs#6440
PR-URL: nodejs#6654
Reviewed-By: Colin Ihrig <[email protected]>
rvagg pushed a commit that referenced this issue Jun 2, 2016
Respect the `{ family: 6 }` address family property when connecting to
a remote peer over TLS.

Fixes: #4139
Fixes: #6440
PR-URL: #6654
Reviewed-By: Colin Ihrig <[email protected]>
MylesBorins pushed a commit that referenced this issue Jun 29, 2016
Respect the `{ family: 6 }` address family property when connecting to
a remote peer over TLS.

Fixes: #4139
Fixes: #6440
PR-URL: #6654
Reviewed-By: Colin Ihrig <[email protected]>
MylesBorins pushed a commit that referenced this issue Jul 12, 2016
Respect the `{ family: 6 }` address family property when connecting to
a remote peer over TLS.

Fixes: #4139
Fixes: #6440
PR-URL: #6654
Reviewed-By: Colin Ihrig <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
https Issues or PRs related to the https subsystem.
Projects
None yet
Development

No branches or pull requests

5 participants