NodeJS,绕过 linux hosts 文件

NodeJS, bypass linux hosts file

NodeJS 有没有办法绕过 linux 的 /etc/hosts 文件?

例如,如果我的主机文件中有一个条目,例如: 127.0.0.1example.com

如何从 NodeJS 访问 'real' example.com?

我暂时不想修改/etc/hosts来做这个,因为它会带来一些问题并且不是一个干净的解决方案。

提前致谢!

起初我认为这是不可能的,但后来我偶然发现了一种 ignore the hosts file on Linux. Additionally, I found a DNS API 内置到 Node 中的方法。基本上,默认情况下,Node 遵从操作系统进行 DNS 查找(它将从 /etc/hosts 读取,如果不需要,则根本不会进行 DNS 查询)。但是,Node 还公开了一种通过显式发出 DNS 请求来解析主机名的方法。这将为您提供所需的 IP 地址。

$ cat /etc/hosts
<snip>
127.0.0.1 google.com
$ ping google.com
PING google.com (127.0.0.1) 56(84) bytes of data.
...

这表明主机文件确实有效。

const dns = require('dns')

// This will use the hosts file.
dns.lookup('google.com', function (err, res) {
  console.log('This computer thinks Google is located at: ' + res)
})

dns.resolve4('google.com', function (err, res) {
  console.log('A real IP address of Google is: ' + res[0])
})

这会按预期输出不同的值:

$ node host.js
This computer thinks Google is located at: 127.0.0.1
A real IP address of Google is: 69.77.145.253

请注意,我使用最新的 Node v8.0.0 对此进行了测试。但是,我查看了一些较旧的文档,发现 API 至少从 v0.12 开始就存在,因此,假设没有发生重大变化,这应该适用于您碰巧 运行 的任何版本的 Node。此外,将主机名解析为 IP 地址可能只是成功的一半。如果您尝试直接通过 IP 访问某些网站,它们的行为会很奇怪(或根本不会)。

基于@supersam654 和 :我的解决方案(完整示例)带有 .get 请求(忽略 hosts 所有请求):

const dns = require("dns");
const url = require("url");

const req = (urlString, cb) => {
    const parsedUrl = url.parse(urlString);
    const hostname = parsedUrl.hostname;

    dns.resolve4(hostname, function(err, res) {
        if (err) throw err;
        console.log(`A real IP address of ${hostname} is: ${res[0]}`);
        const newUrl = urlString.replace(`${parsedUrl.protocol}//${hostname}`, `${parsedUrl.protocol}//${res[0]}`);

        https
            .get(
                newUrl,
                {
                    headers: { host: hostname },
                    servername: hostname
                },
                resp => {
                    let data = "";

                    // A chunk of data
                    resp.on("data", chunk => {
                        data += chunk;
                    });

                    // The whole response has been received. Print out the result.
                    resp.on("end", () => {
                        cb(data);
                    });
                }
            )
            .on("error", err => {
                console.log("Error request " + url + ": " + err.message);
            });
    });
};

// Example
req("https://google.com/", data => console.log(data));