我可以使用客户端 Javascript 执行 DNS 查找(主机名到 IP 地址)吗?

IT技术 javascript dns
2021-02-04 04:31:19

我想使用客户端 Javascript 来执行从客户端计算机看到的 DNS 查找(主机名到 IP 地址)。那可能吗?

6个回答

编辑:这个问题让我很头疼,所以我在 Google App Engine 上建立了一个 JSONP 网络服务来返回客户端的 ip 地址。用法:

<script type="application/javascript">
function getip(json){
  alert(json.ip); // alerts the ip address
}
</script>

<script type="application/javascript" src="http://jsonip.appspot.com/?callback=getip"> </script>

是的,不需要服务器代理。


纯 JS 不行。如果您在同一个域下有一个打印它的服务器脚本,您可以发送一个 XMLHttpRequest 来读取它。

您的网址似乎已关闭
2021-03-18 04:31:19
您可以将源发布到您的网络服务吗?运行一个实例会很好。
2021-04-06 04:31:19
抱歉,但不得不投反对票,因为我认为它实际上并没有回答原始问题。他们只想要标准的 DNS 查找,而不是用户的公共 IP。
2021-04-07 04:31:19

javascript 标准库中没有主机或 IP 地址的概念。所以你必须访问一些外部服务来为你查找主机名。

我建议托管一个 cgi-bin,它可以查找主机名的 ip 地址并通过 javascript 访问它。

有一个新提议的 Internet 标准允许您通过 HTTPS 发送 DNS 查询(请参阅此答案stackoverflow.com/a/58299823/9638991)。实际上,它的工作原理与 cgi-bin 脚本基本相同 :)(除了它已被 IETF 标准化并且大量大公司支持它)
2021-03-20 04:31:19
通过来自云的 CGI 的问题是发现内部网主机 ips,而这在外部是不可能的。您必须使用机器或 Intranet 上的本地服务。
2021-03-23 04:31:19
在撰写本文时(2008 年)确实如此。6 年后情况并非如此:请参阅我在同一页面中对 WebRTC 的评论。(不幸的是,在搜索 IP 地址问题的解决方案时,Google 仍然指向此线程,这可能会使人们误入歧途)。
2021-04-04 04:31:19
cgi-bin?那是老派。我喜欢!
2021-04-07 04:31:19
@earizon - 您的答案是针对另一个问题的 - 如何发现您自己的私有 IP 地址。
2021-04-10 04:31:19

我知道这个问题很久以前就有人问过了,但我想我会提供一个更新的答案。

DNS over HTTPS (DoH)

您可以通过 HTTPS 向支持它的 DNS 解析器发送 DNS 查询。DOH 的标准在RFC 8484 中有描述

这与所有其他答案的建议类似,只是 DoH 实际上是基于 HTTPS 的 DNS 协议。它也是一个“提议的”互联网标准,并且变得非常流行。例如,一些主要浏览器要么支持它,要么计划支持它(Chrome、Edge、Firefox),而微软正在将其构建到他们的操作系统中。

DoH 的目的之一是:

允许 Web 应用程序以与跨源资源共享 (CORS) 一致的安全方式通过现有浏览器 API 访问 DNS 信息

有一个开源工具,专门用于从名为dohjs 的Web 应用程序进行 DNS 查找通过 HTTPS (DoH) 线格式查询进行DNS,如RFC 8484 中所述它同时支持 GET 和 POST 方法。

完全披露:我是 dohjs 的贡献者。

在这里可以找到另一个具有类似功能的 JavaScript 库 - https://github.com/sc0Vu/doh-js-client我个人没有使用过这个,但我认为它也适用于客户端。

DNS over HTTPS JSON API

如果您不想打扰 DNS 线格式,Google 和 Cloudflare 都通过 HTTPS 为 DNS 提供 JSON API。

使用 Google 的 JSON DOH API 查找 example.com 的示例 Javascript 代码:

var response = await fetch('https://dns.google/resolve?name=example.com');
var json = await response.json();
console.log(json);

来自 RFC 的示例,用于 DOH GET 和 POST with wireformat

以下是 RFC 为 GET 和 POST 提供的示例(请参阅https://www.rfc-editor.org/rfc/rfc8484#section-4.1.1):

获取示例:

第一个示例请求使用 GET 来请求“www.example.com”。

:method = GET
:scheme = https
:authority = dnsserver.example.net
:path = /dns-query?dns=AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB
accept = application/dns-message

POST 示例:

使用 POST 方法对“www.example.com”的相同 DNS 查询是:

:method = POST
:scheme = https
:authority = dnsserver.example.net
:path = /dns-query
accept = application/dns-message
content-type = application/dns-message
content-length = 33

<以下十六进制编码表示的33个字节> 00 00 01 00 00 01 00 00 00 00 00 00 03 77 77 77 07 65 78 61 6d 70 6c 65 03 63 6f 00 0d 00

其他发送 DOH 查询的地方

您可以在以下几个地方找到一些支持 DNS over HTTPS 的公共 DNS 解析器列表:

在上述资源中,我想说 Curl 的 wiki 上的列表和 DNSCrypt 列表可能是最完整和更新最频繁的。Curl 的页面还包括 DoH 的开源工具列表(服务器、代理、客户端库等)。

很晚了,但我想很多人还是会通过“谷歌航空公司”降落在这里。一种现代方法是使用不需要服务器支持的 WebRTC。

https://hacking.ventures/local-ip-discovery-with-html5-webrtc-security-and-privacy-risk/

下一个代码是来自http://net.ipcalf.com/的复制和粘贴

// NOTE: window.RTCPeerConnection is "not a constructor" in FF22/23
var RTCPeerConnection = /*window.RTCPeerConnection ||*/ window.webkitRTCPeerConnection || window.mozRTCPeerConnection;

if (RTCPeerConnection) (function () {
    var rtc = new RTCPeerConnection({iceServers:[]});
    if (window.mozRTCPeerConnection) {      // FF needs a channel/stream to proceed
        rtc.createDataChannel('', {reliable:false});
    };  

    rtc.onicecandidate = function (evt) {
        if (evt.candidate) grepSDP(evt.candidate.candidate);
    };  
    rtc.createOffer(function (offerDesc) {
        grepSDP(offerDesc.sdp);
        rtc.setLocalDescription(offerDesc);
    }, function (e) { console.warn("offer failed", e); }); 


    var addrs = Object.create(null);
    addrs["0.0.0.0"] = false;
    function updateDisplay(newAddr) {
        if (newAddr in addrs) return;
        else addrs[newAddr] = true;
        var displayAddrs = Object.keys(addrs).filter(function (k) { return addrs[k]; }); 
        document.getElementById('list').textContent = displayAddrs.join(" or perhaps ") || "n/a";
    }   

    function grepSDP(sdp) {
        var hosts = []; 
        sdp.split('\r\n').forEach(function (line) { // c.f. http://tools.ietf.org/html/rfc4566#page-39
            if (~line.indexOf("a=candidate")) {     // http://tools.ietf.org/html/rfc4566#section-5.13
                var parts = line.split(' '),        // http://tools.ietf.org/html/rfc5245#section-15.1
                    addr = parts[4],
                    type = parts[7];
                if (type === 'host') updateDisplay(addr);
            } else if (~line.indexOf("c=")) {       // http://tools.ietf.org/html/rfc4566#section-5.7
                var parts = line.split(' '), 
                    addr = parts[2];
                updateDisplay(addr);
            }   
        }); 
    }   
})(); else {
    document.getElementById('list').innerHTML = "<code>ifconfig | grep inet | grep -v inet6 | cut -d\" \" -f2 | tail -n1</code>";
    document.getElementById('list').nextSibling.textContent = "In Chrome and Firefox your IP should display automatically, by the power of WebRTCskull.";
}   
非常非常有趣,这是一个错误或设计缺陷,无论如何它会在某个时候得到纠正,因此对长期项目没有好处
2021-03-24 04:31:19
这确实是 WebRTC 之前不存在的一项新功能 - 发现您自己的 IP 地址。但是@noahjacobson 提出了一个不同的问题 - 通过 javascript 中的主机名对 IP 进行 DNS 查找。
2021-03-27 04:31:19

托管的 JSONP 版本就像一个魅力,但它似乎在大多数日子(东部时间)的夜间检查它的资源,所以我不得不创建我自己的版本。

这就是我用 PHP 完成它的方式:

<?php
header('content-type: application/json; charset=utf-8');

$data = json_encode($_SERVER['REMOTE_ADDR']);
echo $_GET['callback'] . '(' . $data . ');';
?>

然后 Javascript 和以前完全一样,只是不是数组:

<script type="application/javascript">
function getip(ip){
    alert('IP Address: ' + ip);
}
</script>

<script type="application/javascript" src="http://www.anotherdomain.com/file.php?callback=getip"> </script>

就那么简单!

旁注:如果您在任何面向公众的环境中使用它,请务必清理您的 $_GET!

抱歉,但不得不投反对票,因为我认为它实际上并没有回答原始问题。他们只想要标准的 DNS 查找,而不是用户的公共 IP。
2021-03-12 04:31:19
我只是编辑了原始问题以使其更清楚,因为我最近正在研究相同的问题,但出于某种原因,这里的大多数答案实际上并不是原始海报所要求的,应该发布在不同的问题下。
2021-03-16 04:31:19
@SimonEast 呵呵。您修改了一个 7 岁问题的问题。做任何你需要满足自己的事情;-)
2021-03-17 04:31:19
等一下,为什么还要使用 $_GET 呢?就像你说的,这是一个漏洞。不能只使用: echo 'getip(' . $data . ');';
2021-03-27 04:31:19
谢谢你!正是我要找的:)
2021-04-03 04:31:19