镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

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

Description

@jaggedsoft

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! ♥️

Activity

  1. changed the title [-]Possible Bug: Binding to IPv6 localAddress while using HTTPS[/-] [+]Possible Bug: Can't bind to IPv6 localAddress while using https.request()[/+] on Dec 3, 2015
  2. 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()[/+] on Dec 3, 2015
  3. added
    httpsIssues and PRs related to the https subsystem.
    on Dec 4, 2015
  4. jaggedsoft commented on Dec 4, 2015

    @jaggedsoft
    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._

  5. evanlucas commented on Dec 4, 2015

    @evanlucas
    Contributor

    Possibly related to #3625

  6. jasnell commented on Apr 22, 2016

    @jasnell
    Member

    @nodejs/crypto

  7. bnoordhuis commented on Apr 22, 2016

    @bnoordhuis
    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.

  8. jaggedsoft commented on May 24, 2016

    @jaggedsoft
    Author

    @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();
    
  9. bnoordhuis commented on May 25, 2016

    @bnoordhuis
    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.)

  10. jaggedsoft commented on May 25, 2016

    @jaggedsoft
    Author

    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 +++
    
  11. bnoordhuis commented on May 25, 2016

    @bnoordhuis
    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.

  12. jaggedsoft commented on May 25, 2016

    @jaggedsoft
    Author

    @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.

  13. bnoordhuis commented on May 27, 2016

    @bnoordhuis
    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.

  14. jaggedsoft commented on May 27, 2016

    @jaggedsoft
    Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    httpsIssues and PRs related to the https subsystem.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions