101

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

4

16 回答 16

79

编辑:这个问题让我很痒,所以我在 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 来读取它。

于 2008-09-19T15:14:55.637 回答
43

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

HTTPS 上的 DNS (DoH)

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

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

DoH 的目的之一是:

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

有一个开源工具专门用于从称为dohjs的 Web 应用程序中进行 DNS 查找。它执行RFC 8484中所述的DNS over HTTPS (DoH) 有线格式查询。它同时支持 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);

DOH GET 和 POST 的 RFC 中带有线格式的示例

以下是 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 方法对“www.example.com”进行相同的 DNS 查询将是:

:method = POST
:scheme = https
:authority = dnsserver.example.net
:path = /dns-query
接受 = 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 6d 00 00 01 00 01

其他发送 DOH 查询的地方

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

Of the above resources, I'd say that the list on Curl's wiki and the DNSCrypt list are are probably the most complete and the most frequently updated. Curl's page also includes a list of open source tools for DoH (servers, proxies, client libs, etc).

于 2019-10-09T08:18:48.517 回答
38

javascript 标准库中没有主机或 IP 地址的概念。因此,您必须访问一些外部服务才能为您查找主机名。

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

于 2008-09-19T15:13:49.867 回答
33

很晚了,但我想很多人还是会通过“谷歌航空”登陆这里。一种现代方法是使用不需要服务器支持的 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.";
}   
于 2014-09-21T17:58:54.130 回答
13

托管的 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!

于 2011-08-18T20:08:43.080 回答
3

有一个第三方服务提供了一个 CORS 友好的 REST API 来从浏览器执行 DNS 查找 - https://exana.io/tools/dns/

于 2017-07-06T20:15:24.270 回答
2

我知道这是一个老问题,但我的解决方案可能会对其他人有所帮助。

我发现让这一切变得简单的 JSON(P) 服务不会永远持续下去,但在撰写本文时,以下 JavaScript 对我来说效果很好。

<script type="text/javascript">function z (x){ document.getElementById('y').innerHTML=x.query }</script>
<script type='text/javascript' src='http://ip-api.com/json/zero.eu.org?callback=z'></script>

上面将我的服务器的 IP 写在它所在的页面上,但是可以通过将“zero.eu.org”更改为另一个域名来修改脚本以查找任何 IP。这可以在我的页面上看到:http: //meon.zero.eu.org/

于 2015-04-22T09:24:07.003 回答
1

正如许多人所说,您需要使用外部服务并调用它。这只会从服务器的角度为您提供 DNS 解析。

如果这足够好,并且您只需要 DNS 解析,您可以使用以下 Docker 容器:

https://github.com/kuralabs/docker-webaiodns

端点:

[GET] /ipv6/[domain]:对给定域执行 DNS 解析并返回关联的 IPv6 地址。

 {
     "addresses": [
         "2a01:91ff::f03c:7e01:51bd:fe1f"
     ]
 }

[GET] /ipv4/[domain]:对给定域执行 DNS 解析并返回相关的 IPv4 地址。

 {
     "addresses": [
         "139.180.232.162"
     ]
 }

我的建议是您将 Web 服务器设置为反向代理到服务器中为您的 Javascript 提供服务的特定端点上的容器,并使用您的标准 Javascript Ajax 函数调用它。

于 2018-01-17T09:19:30.530 回答
1

有一个 JavaScript 库DNS-JS.com就是这样做的。

DNS.Query("dns-js.com",
    DNS.QueryType.A,
    function(data) {
        console.log(data);
});
于 2019-08-14T16:21:42.323 回答
0

这样做需要破坏浏览器沙箱。尝试让您的服务器进行查找并通过 XmlHttp 从客户端请求。

于 2008-09-19T15:14:02.893 回答
0

自 v60 以来,Firefox 有一个内置的 API,用于 WebExtensions:

https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/dns/resolve

于 2018-11-04T22:11:15.940 回答
0

确保您可以通过使用这种 dns 方法而无需使用任何添加,只需纯 javascript,browser.dns.resolve("example.com"); 但它仅与 FIREFOX 60 兼容,您可以在 MDN https://developer.mozilla.org/en-US/docs上查看更多信息/Mozilla/附加组件/WebExtensions/API/dns/resolve

于 2019-04-02T13:15:05.283 回答
-2

出于安全原因,我认为大多数浏览器都不允许这样做,正如问题所要求的那样,在纯 JavaScript 上下文中。

于 2008-09-19T15:12:22.023 回答
-3

也许我错过了重点,但在这里回复 NAVY 的人是浏览器如何告诉你“请求者”的 IP 地址(尽管可能只有他们的服务提供商)。

在页面中放置一个脚本标签,由调用(有 src 指向)另一个负载不平衡的服务器的客户端呈现(我意识到这意味着您需要访问第二台服务器,但是这些天托管很便宜,您可以轻松且便宜地进行设置)。

这是需要添加到客户端页面的代码类型:

在另一台服务器“someServerIown”上,您需要拥有 ASP、ASPX 或 PHP 页面;

----- 包含这样的服务器代码:

"<% Response.Write("var clientipaddress = '" & Request.ServerVariables("REMOTE_ADDR") & "';") %>" (没有外部 dbl 引号 :-))

---- 并将这段代码写回脚本标签:

   var clientipaddress = '178.32.21.45';

这有效地创建了一个 Javascript 变量,您可以在页面上使用 Javascript 访问该变量。

希望您访问此 var 并将值写入准备发送回的表单控件。

当用户发布或收到下一个请求时,您的 Javascript 和/或表单将“otherServerIown”为您填写的变量的值发送回您想要的服务器。

这就是我如何绕过我们拥有的愚蠢的负载均衡器,它掩盖了客户端 IP 地址并使其看起来像负载均衡器的地址......愚蠢......愚蠢愚蠢愚蠢!

我没有给出确切的解决方案,因为每个人的情况都有点不同。然而,这个概念是合理的。另外,请注意,如果您在 HTTPS 页面上执行此操作,您的“otherServerIOwn”也必须以该安全形式交付,否则客户端会收到混合内容的警报。如果您确实有 https,请确保您的所有证书都有效,否则客户端也会收到警告。

希望它可以帮助某人!抱歉,花了一年的时间来回答/贡献。:-)

于 2013-09-05T22:13:02.870 回答
-4

我的版本是这样的:

我的服务器上的php:

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

    $data = json_encode($_SERVER['REMOTE_ADDR']);


    $callback = filter_input(INPUT_GET, 
                 'callback',
                 FILTER_SANITIZE_STRING, 
                 FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW);
    echo $callback . '(' . $data . ');';
?>

页面上的 jQuery:

var self = this;
$.ajax({
    url: this.url + "getip.php",
    data: null,
    type: 'GET',
    crossDomain: true,
    dataType: 'jsonp'

}).done( function( json ) {

    self.ip = json;

});

它可以跨域工作。它可以使用状态检查。正在努力。

于 2014-05-29T16:17:51.080 回答
-13

如果客户端安装了 Java,您可以执行以下操作:

ipAddress = java.net.InetAddress.getLocalHost().getHostAddress();

除此之外,您可能必须使用服务器端脚本。

于 2008-09-19T15:12:50.057 回答