Node.js - 如何在node.js应用程序中获取我的外部IP地址?

31

我正在使用node.js,需要获取由ISP提供的外部IP地址。

是否有一种方法可以在不使用 http://myexternalip.com/raw 这样的服务的情况下实现此目的?

谢谢。


3
如果你在NAT后面,就不行。 - Xophmeister
我想这是我的情况。我的笔记本电脑IP地址是192.168.1.3,我的WiFi路由器是192.168.1.1,而由ISP提供的调制解调器IP地址是201.15.1XX.XXX。我只想获取最后一个。 - fonini
这是一个网络路由的问题,不能仅通过主机进行确定,必须要连接外部才能得出结论。 - Joe
16个回答

39
可以像在Python中一样做,获取外部IP地址,连接到某个网站,并从套接字连接获取您的详细信息。
const net = require('net');
const client = net.connect({port: 80, host:"google.com"}, () => {
  console.log('MyIP='+client.localAddress);
  console.log('MyPORT='+client.localPort);
});

很遗憾无法找到原始的 Python 示例作为参考。
更新2019: 使用内置的http库和来自https://whatismyipaddress.com/api的公共API。
const http = require('http');

var options = {
  host: 'ipv4bot.whatismyipaddress.com',
  port: 80,
  path: '/'
};

http.get(options, function(res) {
  console.log("status: " + res.statusCode);

  res.on("data", function(chunk) {
    console.log("BODY: " + chunk);
  });
}).on('error', function(e) {
  console.log("error: " + e.message);
});

在亚马逊AWS服务器上使用Node.js v0.10.48进行测试。
--
更新于2021年
ipv4bot已关闭,这里有另一个公共API:
var http = require('http');

http.get({'host': 'api.ipify.org', 'port': 80, 'path': '/'}, function(resp) {
  resp.on('data', function(ip) {
    console.log("My public IP address is: " + ip);
  });
});

--
更新2022年
ChatGPT使用ipify和json编写了更长的示例:*是的,我已经测试过。 https://gist.github.com/unitycoder/745a58d562180994a3025afcb84c1753

更多信息请参见https://www.ipify.org/


3
这无法为我输出外部 IP。 - pixelfreak
@pixelfreak,使用哪个Node版本?我仍然可以使用v4.4.5。 - mgear
这会输出我的本地网络/路由器的192.168.xxx地址,而不是公共地址。 - laggingreflex
@laggingreflex 哇,是啊,我想知道它以前是否正常工作过?那时我在生产服务器上使用了它来做某些事情...现在添加了新的替代方案,使用公共API。 - mgear
1
截至2021年11月10日,ipv4bot已关闭其公共API,请参见公告。我按照@jtlindsey的建议切换到public-ip - Erik Vullings
2
挑剔一点,resp 是一个流,因此您不能依赖于单个 data 事件,认为您将接收服务器发送的整个 data 数据包。对于这样小的数据,如果连接真的非常拥堵,您可能只会得到一半的 IP。您必须依靠 data 进行连接,并依靠 end 来获得通知,表示已经接收到了整个 IP。 - Jorge Fuentes González

16

这里执行 npm install --save public-ip 命令。

然后

publicIp.v4().then(ip => {
  console.log("your public ip address", ip);
});

如果您需要获取本地机器IP,则可以使用这个


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

每次IPv4查询都失败了。"查询超时"。 - Tyguy7

10

13
将几行代码打包成另一个包有点儿愚蠢。请参考Ade Yahya的回答,了解这个包的内容。 - Codebeat
8
建议每个人都使用将用户IP信息发送到中国大陆的包并不是很妥当。 - Ethan Standel
流行的替代方案: https://github.com/sindresorhus/public-ip - Damien Golding

4

编辑: 此文章写于2013年...该网站已不存在。如果没有人抱怨,我会暂时保留示例请求代码,但请参考被接受的答案。


http://fugal.net/ip.cgi和这个网站类似。

或者你可以

require('http').request({
    hostname: 'fugal.net',
    path: '/ip.cgi',
    agent: false
    }, function(res) {
    if(res.statusCode != 200) {
        throw new Error('non-OK status: ' + res.statusCode);
    }
    res.setEncoding('utf-8');
    var ipAddress = '';
    res.on('data', function(chunk) { ipAddress += chunk; });
    res.on('end', function() {
        // ipAddress contains the external IP address
    });
    }).on('error', function(err) {
    throw err;
}).end();

参考文献:http://www.nodejs.org/api/http.html#http_http_request_options_callback

这个链接是有关 Node.js 的 HTTP 请求的,可参考官方文档。

2
好的开始,但你错过了一个必要的东西:调用 end。任何试用这个脚本的人,不要忘记将最后一行更改为:}).end(); - Domi
网站已经下线。 - fonini

3

这应该可以在没有任何外部依赖的情况下良好运行(除了ipify.org):

var https = require('https');

var callback = function(err, ip){
    if(err){
        return console.log(err);
    }
    console.log('Our public IP is', ip);
    // do something here with the IP address
};

https.get({
    host: 'api.ipify.org',
}, function(response) {
    var ip = '';
    response.on('data', function(d) {
        ip += d;
    });
    response.on('end', function() {
        if(ip){
            callback(null, ip);
        } else {
            callback('could not get public ip address :(');
        }
    });
});

你也可以使用 https://httpbin.org
GET https://httpbin.org/ip

2

另一个小的节点模块是ext-ip。不同之处在于,您可以使用不同的响应选项来匹配您的编码风格。它已经准备好直接使用...

Promise

let extIP = require('ext-ip')();

extIP.get().then(ip => {
    console.log(ip);
})
.catch(err => {
    console.error(err);
});

事件

let extIP = require('ext-ip')();

extIP.on("ip", ip => {
    console.log(ip);
});

extIP.on("err", err => {
    console.error(err);
});

extIP();

回调函数

let extIP = require('ext-ip')();

extIP((err, ip) => {
    if( err ){
        throw err;
    }

    console.log(ip);
});

2

只需使用 superagent

var superagent = require('superagent');
var getip = function () {
  superagent
    .get('http://ip.cn/')
    .set('User-Agent', 'curl/7.37.1')
    .end(function (err, res) {
      if (err) {
        console.log(err);
      }
      var ip = res.text.match(/\d+\.\d+\.\d+\.\d+/)[0];
      console.log(ip)
      // Here is the result
    });
};

2
根据经验,最简单的答案是,在大多数情况下,由于您通常会处于NAT后面或受到防火墙保护,因此无法获得外部IP而不使用外部服务。我说在大多数情况下,因为可能存在可以从路由器获取它的情况,但这太具体了,无法提供一般性的答案。
您需要做的就是选择NodeJS中喜欢的http客户端,并找到一个维护的服务器,该服务器仅在正文中响应IP地址。您也可以使用软件包,但应查看是否仍在使用维护的远程服务器。
虽然已经有很多示例,但以下是首先尝试IPv6,然后退回到IPv4的示例。它利用axios,因为我对它很熟悉。此外,除非将可选参数“debug”设置为true,否则结果要么是值,要么未定义。
const axios = require('axios');

// replace these URLs with whatever is good for you
const remoteIPv4Url = 'http://ipv4bot.whatismyipaddress.com/';
const remoteIPv6Url = 'http://ipv6bot.whatismyipaddress.com/';

// Try getting an external IPv4 address.
async function getExternalIPv4(debug = false) {
  try {
    const response = await axios.get(remoteIPv4Url);
    if (response && response.data) {
      return response.data;
    }
  } catch (error) {
    if (debug) {
      console.log(error);
    }
  }
  return undefined;
}

// Try getting an external IPv6 address.
async function getExternalIPv6(debug = false) {
  try {
    const response = await axios.get(remoteIPv6Url);
    if (response && response.data) {
      return response.data;
    }
  } catch (error) {
    if (debug) {
      console.log(error);
    }
  }
  return undefined;
}

async function getExternalIP(debug = false) {
  let address;
  // Try IPv6 and then IPv4
  address = await getExternalIPv6(debug);
  if (!address) {
    address = await getExternalIPv4(debug);
  }
  return address;
}

module.exports { getExternalIP, getExternalIPv4, getExternalIPv6 }

欢迎提出改进意见。


1
您可以使用 request-ip 包:
const requestIp = require('request-ip');

// inside middleware handler
const ipMiddleware = function(req, res, next) {
    const clientIp = requestIp.getClientIp(req); 
    next();
};

这是“如何从请求中获取IP地址”的内容,而不是最初所询问的。 - Coco

1
测试并且正常运行;
async function myIP() {
  const response = await fetch("https://api.ipify.org/");
  return await response.text();
}

在async await中调用它,就像这样
const ip = await myIP();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接