get all external ips
This commit is contained in:
		
							parent
							
								
									c41fdbc906
								
							
						
					
					
						commit
						0a3b457583
					
				
							
								
								
									
										16
									
								
								index.js
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								index.js
									
									
									
									
									
								
							@ -1,7 +1,6 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
var PromiseA = require('bluebird');
 | 
			
		||||
var requestAsync = PromiseA.promisify(require('request'));
 | 
			
		||||
 | 
			
		||||
module.exports.create = function (args) {
 | 
			
		||||
  var promises = [];
 | 
			
		||||
@ -14,17 +13,16 @@ module.exports.create = function (args) {
 | 
			
		||||
  // TODO determine if we have a AAAA local ip or not
 | 
			
		||||
  // TODO get A and AAAA records
 | 
			
		||||
  if (-1 !== args.protocols.indexOf('none')) {
 | 
			
		||||
    promises.push(PromiseA.some(args.ipifyUrls.map(function (ipifyUrl) {
 | 
			
		||||
      return requestAsync('https://' + ipifyUrl).then(function (resp) {
 | 
			
		||||
        var ip = (resp.body || '').toString('ascii');
 | 
			
		||||
 | 
			
		||||
        if (!/\d+\.\d+\.\d+\.\d+/.test(ip) && !/\w+\:\w+/.test(ip)) {
 | 
			
		||||
          return PromiseA.reject(new Error("bad response '" + resp.body + "'"));
 | 
			
		||||
        }
 | 
			
		||||
    promises.push(PromiseA.any(args.ipifyUrls.map(function (ipifyUrl) {
 | 
			
		||||
      var getIp = require('./lib/external-ip');
 | 
			
		||||
 | 
			
		||||
      return getIp({ hostname: ipifyUrl, debug: args.debug });
 | 
			
		||||
    })).then(function (ips) {
 | 
			
		||||
      return ips.map(function (ip) {
 | 
			
		||||
        // TODO attempt loopback
 | 
			
		||||
        return ip;
 | 
			
		||||
      });
 | 
			
		||||
    }), 1));
 | 
			
		||||
    }));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return PromiseA.all(promises).then(function (results) {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										144
									
								
								lib/external-ip.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								lib/external-ip.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,144 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
var PromiseA = require('bluebird');
 | 
			
		||||
//var dns = PromiseA.promisifyAll(require('dns'));
 | 
			
		||||
var https = PromiseA.promisifyAll(require('https'));
 | 
			
		||||
var os = require('os');
 | 
			
		||||
 | 
			
		||||
function requestAsync(opts) {
 | 
			
		||||
  return new PromiseA(function (resolve, reject) {
 | 
			
		||||
    var req = https.request(opts, function (res) {
 | 
			
		||||
      var data = '';
 | 
			
		||||
 | 
			
		||||
      res.on('error', function (err) {
 | 
			
		||||
        if (opts.debug) {
 | 
			
		||||
          console.error('[Error] HP: bad request:');
 | 
			
		||||
          console.error(err);
 | 
			
		||||
        }
 | 
			
		||||
        reject(err);
 | 
			
		||||
      });
 | 
			
		||||
      res.on('data', function (chunk) {
 | 
			
		||||
        if (opts.debug > 2) {
 | 
			
		||||
          console.log('HP: request chunk:');
 | 
			
		||||
          console.log(chunk);
 | 
			
		||||
        }
 | 
			
		||||
        data += chunk.toString('utf8');
 | 
			
		||||
      });
 | 
			
		||||
      res.on('end', function () {
 | 
			
		||||
        if (opts.debug > 2) {
 | 
			
		||||
          console.log('HP: request complete:');
 | 
			
		||||
          console.log(data);
 | 
			
		||||
        }
 | 
			
		||||
        resolve(data);
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    req.on('error', reject);
 | 
			
		||||
    req.end();
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = function (opts) {
 | 
			
		||||
  var promises = [];
 | 
			
		||||
  var interfaces = os.networkInterfaces();
 | 
			
		||||
  var ifacenames = Object.keys(interfaces).filter(function (ifacename) {
 | 
			
		||||
    // http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/
 | 
			
		||||
    // https://wiki.archlinux.org/index.php/Network_configuration#Device_names
 | 
			
		||||
    // we do not include tun and bridge devices because we're trying
 | 
			
		||||
    // to see if any physical interface is internet-connected first
 | 
			
		||||
    return /^(en|sl|wl|ww|eth|net|lan|wifi|inet)/.test(ifacename);
 | 
			
		||||
  });
 | 
			
		||||
  var ifaces = ifacenames.reduce(function (all, ifacename) {
 | 
			
		||||
    var ifs = interfaces[ifacename];
 | 
			
		||||
 | 
			
		||||
    ifs.forEach(function (iface) {
 | 
			
		||||
      if (!iface.internal && !/^fe80/.test(iface.address)) {
 | 
			
		||||
        all.push(iface);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return all;
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
  // TODO how to support servername
 | 
			
		||||
  promises.push(dns.resolve4Async(hostname).then(function (ips) {
 | 
			
		||||
    return ips.map(function (ip) {
 | 
			
		||||
      return {
 | 
			
		||||
        address: ip
 | 
			
		||||
      , family: 'IPv4'
 | 
			
		||||
      };
 | 
			
		||||
    });
 | 
			
		||||
  }));
 | 
			
		||||
 | 
			
		||||
  promises.push(dns.resolve6Async(hostname).then(function (ips) {
 | 
			
		||||
    return ips.map(function (ip) {
 | 
			
		||||
      return {
 | 
			
		||||
        address: ip
 | 
			
		||||
      , family: 'IPv6'
 | 
			
		||||
      };
 | 
			
		||||
    });
 | 
			
		||||
  }));
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  function parseIp(ip) {
 | 
			
		||||
    if (!/\d+\.\d+\.\d+\.\d+/.test(ip) && !/\w+\:\w+/.test(ip)) {
 | 
			
		||||
      return PromiseA.reject(new Error("bad response '" + ip + "'"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ip;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function ignoreEinval(err) {
 | 
			
		||||
    if ('EINVAL' === err.code) {
 | 
			
		||||
      if (opts.debug) {
 | 
			
		||||
        console.warn('[HP] tried to bind to invalid address:');
 | 
			
		||||
        console.warn(err.stack);
 | 
			
		||||
      }
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return PromiseA.reject(err);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (opts.debug) {
 | 
			
		||||
    console.log('[HP] external ip opts:');
 | 
			
		||||
    console.log(opts);
 | 
			
		||||
 | 
			
		||||
    console.log('[HP] external ifaces:');
 | 
			
		||||
    console.log(ifaces);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ifaces.forEach(function (iface) {
 | 
			
		||||
    promises.push(requestAsync({
 | 
			
		||||
      family: iface.family
 | 
			
		||||
    , method: 'GET'
 | 
			
		||||
    , headers: {
 | 
			
		||||
        Host: opts.hostname
 | 
			
		||||
      }
 | 
			
		||||
    , localAddress: iface.address
 | 
			
		||||
    , servername: opts.hostname   // is this actually sent to tls.connect()?
 | 
			
		||||
    , hostname: opts.hostname     // if so we could do the DNS ourselves
 | 
			
		||||
                                  // and use the ip address here
 | 
			
		||||
    , port: opts.port || 443
 | 
			
		||||
    , pathname: opts.pathname || opts.path || '/'
 | 
			
		||||
    }).then(parseIp, ignoreEinval).then(function (addr) {
 | 
			
		||||
      return {
 | 
			
		||||
        family: iface.family
 | 
			
		||||
      , address: addr
 | 
			
		||||
      };
 | 
			
		||||
    }));
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return PromiseA.all(promises).then(function (results) {
 | 
			
		||||
    if (opts.debug) {
 | 
			
		||||
      console.log('[HP] got all ip address types');
 | 
			
		||||
      console.log(results);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return results;
 | 
			
		||||
  }, function (err) {
 | 
			
		||||
    console.error('[HP] error');
 | 
			
		||||
    console.error(err);
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user