开发者

Get local IP address in Node.js

开发者 https://www.devze.com 2023-01-14 20:39 出处:网络
I have a simple Node.js program running on my machine and I want to get 开发者_运维问答the local IP address of a PC on which my program is running. How do I get it with Node.js?This information can be

I have a simple Node.js program running on my machine and I want to get 开发者_运维问答the local IP address of a PC on which my program is running. How do I get it with Node.js?


This information can be found in os.networkInterfaces(), — an object, that maps network interface names to its properties (so that one interface can, for example, have several addresses):

'use strict';

const { networkInterfaces } = require('os');

const nets = networkInterfaces();
const results = Object.create(null); // Or just '{}', an empty object

for (const name of Object.keys(nets)) {
    for (const net of nets[name]) {
        // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses
        // 'IPv4' is in Node <= 17, from 18 it's a number 4 or 6
        const familyV4Value = typeof net.family === 'string' ? 'IPv4' : 4
        if (net.family === familyV4Value && !net.internal) {
            if (!results[name]) {
                results[name] = [];
            }
            results[name].push(net.address);
        }
    }
}
// 'results'
{
  "en0": [
    "192.168.1.101"
  ],
  "eth0": [
    "10.0.0.101"
  ],
  "<network name>": [
    "<ip>",
    "<ip alias>",
    "<ip alias>",
    ...
  ]
}
// results["en0"][0]
"192.168.1.101"


Running programs to parse the results seems a bit iffy. Here's what I use.

require('dns').lookup(require('os').hostname(), function (err, add, fam) {
  console.log('addr: ' + add);
})

This should return your first network interface local IP address.


https://github.com/indutny/node-ip

var ip = require("ip");
console.dir ( ip.address() );


Any IP address of your machine you can find by using the os module - and that's native to Node.js:

var os = require('os');

var networkInterfaces = os.networkInterfaces();

console.log(networkInterfaces);

All you need to do is call os.networkInterfaces() and you'll get an easy manageable list - easier than running ifconfig by leagues.


Here's my utility method for getting the local IP address, assuming you are looking for an IPv4 address and the machine only has one real network interface. It could easily be refactored to return an array of IP addresses for multi-interface machines.

function getIPAddress() {
  var interfaces = require('os').networkInterfaces();
  for (var devName in interfaces) {
    var iface = interfaces[devName];

    for (var i = 0; i < iface.length; i++) {
      var alias = iface[i];
      if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal)
        return alias.address;
    }
  }
  return '0.0.0.0';
}


Install a module called ip like:

npm install ip

Then use this code:

var ip = require("ip");
console.log(ip.address());


Use the npm ip module:

var ip = require('ip');

console.log(ip.address());

> '192.168.0.117'


Here is a snippet of Node.js code that will parse the output of ifconfig and (asynchronously) return the first IP address found:

(It was tested on Mac OS X v10.6 (Snow Leopard) only; I hope it works on Linux too.)

var getNetworkIP = (function () {
    var ignoreRE = /^(127\.0\.0\.1|::1|fe80(:1)?::1(%.*)?)$/i;

    var exec = require('child_process').exec;
    var cached;
    var command;
    var filterRE;

    switch (process.platform) {
        // TODO: implement for OSes without the ifconfig command
        case 'darwin':
             command = 'ifconfig';
             filterRE = /\binet\s+([^\s]+)/g;
             // filterRE = /\binet6\s+([^\s]+)/g; // IPv6
             break;
        default:
             command = 'ifconfig';
             filterRE = /\binet\b[^:]+:\s*([^\s]+)/g;
             // filterRE = /\binet6[^:]+:\s*([^\s]+)/g; // IPv6
             break;
    }

    return function (callback, bypassCache) {
        // Get cached value
        if (cached && !bypassCache) {
            callback(null, cached);
            return;
        }

        // System call
        exec(command, function (error, stdout, sterr) {
            var ips = [];
            // Extract IP addresses
            var matches = stdout.match(filterRE);

            // JavaScript doesn't have any lookbehind regular expressions, so we need a trick
            for (var i = 0; i < matches.length; i++) {
                ips.push(matches[i].replace(filterRE, '$1'));
            }

            // Filter BS
            for (var i = 0, l = ips.length; i < l; i++) {
                if (!ignoreRE.test(ips[i])) {
                    //if (!error) {
                        cached = ips[i];
                    //}
                    callback(error, ips[i]);
                    return;
                }
            }
            // Nothing found
            callback(error, null);
        });
    };
})();

Usage example:

getNetworkIP(function (error, ip) {
    console.log(ip);
    if (error) {
        console.log('error:', error);
    }
}, false);

If the second parameter is true, the function will execute a system call every time; otherwise the cached value is used.


Updated version

Returns an array of all local network addresses.

Tested on Ubuntu 11.04 (Natty Narwhal) and Windows XP 32

var getNetworkIPs = (function () {
    var ignoreRE = /^(127\.0\.0\.1|::1|fe80(:1)?::1(%.*)?)$/i;

    var exec = require('child_process').exec;
    var cached;
    var command;
    var filterRE;

    switch (process.platform) {
        case 'win32':
        //case 'win64': // TODO: test
            command = 'ipconfig';
            filterRE = /\bIPv[46][^:\r\n]+:\s*([^\s]+)/g;
            break;
        case 'darwin':
            command = 'ifconfig';
            filterRE = /\binet\s+([^\s]+)/g;
            // filterRE = /\binet6\s+([^\s]+)/g; // IPv6
            break;
        default:
            command = 'ifconfig';
            filterRE = /\binet\b[^:]+:\s*([^\s]+)/g;
            // filterRE = /\binet6[^:]+:\s*([^\s]+)/g; // IPv6
            break;
    }

    return function (callback, bypassCache) {
        if (cached && !bypassCache) {
            callback(null, cached);
            return;
        }

        // System call
        exec(command, function (error, stdout, sterr) {
            cached = [];
            var ip;
            var matches = stdout.match(filterRE) || [];
            //if (!error) {
            for (var i = 0; i < matches.length; i++) {
                ip = matches[i].replace(filterRE, '$1')
                if (!ignoreRE.test(ip)) {
                    cached.push(ip);
                }
            }
            //}
            callback(error, cached);
        });
    };
})();

Usage Example for updated version

getNetworkIPs(function (error, ip) {
console.log(ip);
if (error) {
    console.log('error:', error);
}
}, false);


Calling ifconfig is very platform-dependent, and the networking layer does know what IP addresses a socket is on, so best is to ask it.

Node.js doesn't expose a direct method of doing this, but you can open any socket, and ask what local IP address is in use. For example, opening a socket to www.google.com:

var net = require('net');
function getNetworkIP(callback) {
  var socket = net.createConnection(80, 'www.google.com');
  socket.on('connect', function() {
    callback(undefined, socket.address().address);
    socket.end();
  });
  socket.on('error', function(e) {
    callback(e, 'error');
  });
}

Usage case:

getNetworkIP(function (error, ip) {
    console.log(ip);
    if (error) {
        console.log('error:', error);
    }
});


Your local IP address is always 127.0.0.1.

Then there is the network IP address, which you can get from ifconfig (*nix) or ipconfig (win). This is only useful within the local network.

Then there is your external/public IP address, which you can only get if you can somehow ask the router for it, or you can setup an external service which returns the client IP address whenever it gets a request. There are also other such services in existence, like whatismyip.com.

In some cases (for instance if you have a WAN connection) the network IP address and the public IP are the same, and can both be used externally to reach your computer.

If your network and public IP addresses are different, you may need to have your network router forward all incoming connections to your network IP address.


Update 2013:

There's a new way of doing this now. You can check the socket object of your connection for a property called localAddress, e.g. net.socket.localAddress. It returns the address on your end of the socket.

The easiest way is to just open a random port and listen on it, and then get your address and close the socket.


Update 2015:

The previous doesn't work anymore.


The correct one-liner for both Underscore.js and Lodash is:

var ip = require('underscore')
    .chain(require('os').networkInterfaces())
    .values()
    .flatten()
    .find({family: 'IPv4', internal: false})
    .value()
    .address;


Here's what might be the cleanest, simplest answer without dependencies & that works across all platforms.

const { lookup } = require('dns').promises;
const { hostname } = require('os');

async function getMyIPAddress(options) {
  return (await lookup(hostname(), options))
    .address;
}


All I know is I wanted the IP address beginning with 192.168.. This code will give you that:

function getLocalIp() {
    const os = require('os');

    for(let addresses of Object.values(os.networkInterfaces())) {
        for(let add of addresses) {
            if(add.address.startsWith('192.168.')) {
                return add.address;
            }
        }
    }
}

Of course you can just change the numbers if you're looking for a different one.


I was able to do this using just Node.js.

As Node.js:

var os = require( 'os' );
var networkInterfaces = Object.values(os.networkInterfaces())
    .reduce((r,a) => {
        r = r.concat(a)
        return r;
    }, [])
    .filter(({family, address}) => {
        return family.toLowerCase().indexOf('v4') >= 0 &&
            address !== '127.0.0.1'
    })
    .map(({address}) => address);
var ipAddresses = networkInterfaces.join(', ')
console.log(ipAddresses);

As Bash script (needs Node.js installed)

function ifconfig2 ()
{
    node -e """
        var os = require( 'os' );
        var networkInterfaces = Object.values(os.networkInterfaces())
            .reduce((r,a)=>{
                r = r.concat(a)
                return r;
            }, [])
            .filter(({family, address}) => {
                return family.toLowerCase().indexOf('v4') >= 0 &&
                    address !== '127.0.0.1'
            })
            .map(({address}) => address);
        var ipAddresses = networkInterfaces.join(', ')
        console.log(ipAddresses);
    """
}


I probably came late to this question, but in case someone wants to a get a one liner ES6 solution to get array of IP addresses then this should help you:

Object.values(require("os").networkInterfaces())
    .flat()
    .filter(({ family, internal }) => family === "IPv4" && !internal)
    .map(({ address }) => address)

As

Object.values(require("os").networkInterfaces())

will return an array of arrays, so flat() is used to flatten it into a single array

.filter(({ family, internal }) => family === "IPv4" && !internal)

Will filter the array to include only IPv4 Addresses and if it's not internal

Finally

.map(({ address }) => address)

Will return only the IPv4 address of the filtered array

so result would be [ '192.168.xx.xx' ]

you can then get the first index of that array if you want or change filter condition

OS used is Windows


Here's a simplified version in vanilla JavaScript to obtain a single IP address:

function getServerIp() {

  var os = require('os');
  var ifaces = os.networkInterfaces();
  var values = Object.keys(ifaces).map(function(name) {
    return ifaces[name];
  });
  values = [].concat.apply([], values).filter(function(val){
    return val.family == 'IPv4' && val.internal == false;
  });

  return values.length ? values[0].address : '0.0.0.0';
}


I wrote a Node.js module that determines your local IP address by looking at which network interface contains your default gateway.

This is more reliable than picking an interface from os.networkInterfaces() or DNS lookups of the hostname. It is able to ignore VMware virtual interfaces, loopback, and VPN interfaces, and it works on Windows, Linux, Mac OS, and FreeBSD. Under the hood, it executes route.exe or netstat and parses the output.

var localIpV4Address = require("local-ipv4-address");

localIpV4Address().then(function(ipAddress){
    console.log("My IP address is " + ipAddress);
    // My IP address is 10.4.4.137 
});


For Linux and macOS uses, if you want to get your IP addresses by a synchronous way, try this:

var ips = require('child_process').execSync("ifconfig | grep inet | grep -v inet6 | awk '{gsub(/addr:/,\"\");print $2}'").toString().trim().split("\n");
console.log(ips);

The result will be something like this:

['192.168.3.2', '192.168.2.1']


One liner for macOS first localhost address only.

When developing applications on macOS, and you want to test it on the phone, and need your app to pick the localhost IP address automatically.

require('os').networkInterfaces().en0.find(elm => elm.family=='IPv4').address

This is just to mention how you can find out the ip address automatically. To test this you can go to terminal hit

node
os.networkInterfaces().en0.find(elm => elm.family=='IPv4').address

output will be your localhost IP address.


For anyone interested in brevity, here are some "one-liners" that do not require plugins/dependencies that aren't part of a standard Node.js installation:

Public IPv4 and IPv6 address of eth0 as an array:

var ips = require('os').networkInterfaces().eth0.map(function(interface) {
    return interface.address;
});

First public IP address of eth0 (usually IPv4) as a string:

var ip = require('os').networkInterfaces().eth0[0].address;


The following solution works for me

const ip = Object.values(require("os").networkInterfaces())
        .flat()
        .filter((item) => !item.internal && item.family === "IPv4")
        .find(Boolean).address;


Google directed me to this question while searching for "Node.js get server IP", so let's give an alternative answer for those who are trying to achieve this in their Node.js server program (may be the case of the original poster).

In the most trivial case where the server is bound to only one IP address, there should be no need to determine the IP address since we already know to which address we bound it (for example, the second parameter passed to the listen() function).

In the less trivial case where the server is bound to multiple IP addresses, we may need to determine the IP address of the interface to which a client connected. And as briefly suggested by Tor Valamo, nowadays, we can easily get this information from the connected socket and its localAddress property.

For example, if the program is a web server:

var http = require("http")

http.createServer(function (req, res) {
    console.log(req.socket.localAddress)
    res.end(req.socket.localAddress)
}).listen(8000)

And if it's a generic TCP server:

var net = require("net")

net.createServer(function (socket) {
    console.log(socket.localAddress)
    socket.end(socket.localAddress)
}).listen(8000)

When running a server program, this solution offers very high portability, accuracy and efficiency.

For more details, see:

  • http://nodejs.org/api/net.html
  • http://nodejs.org/api/http.html


Based on a comment, here's what's working for the current version of Node.js:

var os = require('os');
var _ = require('lodash');

var ip = _.chain(os.networkInterfaces())
  .values()
  .flatten()
  .filter(function(val) {
    return (val.family == 'IPv4' && val.internal == false)
  })
  .pluck('address')
  .first()
  .value();

The comment on one of the answers above was missing the call to values(). It looks like os.networkInterfaces() now returns an object instead of an array.


Here is a variation of the previous examples. It takes care to filter out VMware interfaces, etc. If you don't pass an index it returns all addresses. Otherwise, you may want to set it default to 0 and then just pass null to get all, but you'll sort that out. You could also pass in another argument for the regex filter if so inclined to add.

function getAddress(idx) {

    var addresses = [],
        interfaces = os.networkInterfaces(),
        name, ifaces, iface;

    for (name in interfaces) {
        if(interfaces.hasOwnProperty(name)){
            ifaces = interfaces[name];
            if(!/(loopback|vmware|internal)/gi.test(name)){
                for (var i = 0; i < ifaces.length; i++) {
                    iface = ifaces[i];
                    if (iface.family === 'IPv4' &&  !iface.internal && iface.address !== '127.0.0.1') {
                        addresses.push(iface.address);
                    }
                }
            }
        }
    }

    // If an index is passed only return it.
    if(idx >= 0)
        return addresses[idx];
    return addresses;
}


If you're into the whole brevity thing, here it is using Lodash:

var os = require('os');
var _ = require('lodash');
var firstLocalIp = _(os.networkInterfaces()).values().flatten().where({ family: 'IPv4', internal: false }).pluck('address').first();

console.log('First local IPv4 address is ' + firstLocalIp);


var ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress 


Here's my variant that allows getting both IPv4 and IPv6 addresses in a portable manner:

/**
 * Collects information about the local IPv4/IPv6 addresses of
 * every network interface on the local computer.
 * Returns an object with the network interface name as the first-level key and
 * "IPv4" or "IPv6" as the second-level key.
 * For example you can use getLocalIPs().eth0.IPv6 to get the IPv6 address
 * (as string) of eth0
 */
getLocalIPs = function () {
    var addrInfo, ifaceDetails, _len;
    var localIPInfo = {};
    //Get the network interfaces
    var networkInterfaces = require('os').networkInterfaces();
    //Iterate over the network interfaces
    for (var ifaceName in networkInterfaces) {
        ifaceDetails = networkInterfaces[ifaceName];
        //Iterate over all interface details
        for (var _i = 0, _len = ifaceDetails.length; _i < _len; _i++) {
            addrInfo = ifaceDetails[_i];
            if (addrInfo.family === 'IPv4') {
                //Extract the IPv4 address
                if (!localIPInfo[ifaceName]) {
                    localIPInfo[ifaceName] = {};
                }
                localIPInfo[ifaceName].IPv4 = addrInfo.address;
            } else if (addrInfo.family === 'IPv6') {
                //Extract the IPv6 address
                if (!localIPInfo[ifaceName]) {
                    localIPInfo[ifaceName] = {};
                }
                localIPInfo[ifaceName].IPv6 = addrInfo.address;
            }
        }
    }
    return localIPInfo;
};

Here's a CoffeeScript version of the same function:

getLocalIPs = () =>
    ###
    Collects information about the local IPv4/IPv6 addresses of
      every network interface on the local computer.
    Returns an object with the network interface name as the first-level key and
      "IPv4" or "IPv6" as the second-level key.
    For example you can use getLocalIPs().eth0.IPv6 to get the IPv6 address
      (as string) of eth0
    ###
    networkInterfaces = require('os').networkInterfaces();
    localIPInfo = {}
    for ifaceName, ifaceDetails of networkInterfaces
        for addrInfo in ifaceDetails
            if addrInfo.family=='IPv4'
                if !localIPInfo[ifaceName]
                    localIPInfo[ifaceName] = {}
                localIPInfo[ifaceName].IPv4 = addrInfo.address
            else if addrInfo.family=='IPv6'
                if !localIPInfo[ifaceName]
                    localIPInfo[ifaceName] = {}
                localIPInfo[ifaceName].IPv6 = addrInfo.address
    return localIPInfo

Example output for console.log(getLocalIPs())

{ lo: { IPv4: '127.0.0.1', IPv6: '::1' },
  wlan0: { IPv4: '192.168.178.21', IPv6: 'fe80::aa1a:2eee:feba:1c39' },
  tap0: { IPv4: '10.1.1.7', IPv6: 'fe80::ddf1:a9a1:1242:bc9b' } }


Similar to other answers but more succinct:

'use strict';

const interfaces = require('os').networkInterfaces();

const addresses = Object.keys(interfaces)
  .reduce((results, name) => results.concat(interfaces[name]), [])
  .filter((iface) => iface.family === 'IPv4' && !iface.internal)
  .map((iface) => iface.address);


Many times I find there are multiple internal and external facing interfaces available (example: 10.0.75.1, 172.100.0.1, 192.168.2.3) , and it's the external one that I'm really after (172.100.0.1).

In case anyone else has a similar concern, here's one more take on this that hopefully may be of some help...

const address = Object.keys(os.networkInterfaces())
    // flatten interfaces to an array
    .reduce((a, key) => [
        ...a,
        ...os.networkInterfaces()[key]
    ], [])
    // non-internal ipv4 addresses only
    .filter(iface => iface.family === 'IPv4' && !iface.internal)
    // project ipv4 address as a 32-bit number (n)
    .map(iface => ({...iface, n: (d => ((((((+d[0])*256)+(+d[1]))*256)+(+d[2]))*256)+(+d[3]))(iface.address.split('.'))}))
    // set a hi-bit on (n) for reserved addresses so they will sort to the bottom
    .map(iface => iface.address.startsWith('10.') || iface.address.startsWith('192.') ? {...iface, n: Math.pow(2,32) + iface.n} : iface)
    // sort ascending on (n)
    .sort((a, b) => a.n - b.n)
    [0]||{}.address;


Use:

var os = require('os');
var networkInterfaces = os.networkInterfaces();
var arr = networkInterfaces['Local Area Connection 3']
var ip = arr[1].address;
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号