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


92

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


5
这个问题的许多答案似乎都是建议在解析服务器端进行。取决于用例,可能还不够。例如,如果您要查找的服务正在使用GSLB,则它可能会根据用户所在的位置返回不同的IP;结果,服务器端代码收到的响应很可能是与浏览器收到的响应不同的响应。话虽如此,对于那些关心这种差异的人,我还没有替代解决方案。
Ilan Rabinovitch 2012年

Answers:


34

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

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


26
cgi-bin?那是老学校。我喜欢!
Andrew Hedges

10
在撰写本文时(2008年),情况确实如此。6年后的情况并非如此:请在同一页面上查看我对WebRTC的评论。(不幸的是,在寻找IP地址问题的解决方案时,Google仍然会指向该线程,这可能会使人们误入歧途)。
earizon

1
@earizon-您的答案是一个不同的问题-如何发现您自己的私有IP地址。
Gene Vayngrib 2015年

通过CGI从云中获取的问题将是发现Intranet主机ip,而这在外部是不可能的。您将必须在计算机或Intranet上使用本地服务。
Tzahi Fadida

有一个新的提议的Internet标准,它允许您通过HTTPS发送DNS查询(请参阅此答案stackoverflow.com/a/58299823/9638991)。在实际上,它基本上与cgi-bin脚本相同:)(除了IETF对其进行了标准化,并且有很多大公司支持它)
kimbo

83

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


4
您可以将源发布到Web服务吗?最好运行一个实例。
2012年

18
抱歉,但是我不得不拒绝投票,因为我认为它实际上并不能回答原始问题。他们只需要标准的DNS查找,而不是用户的公共IP。
西蒙·伊斯特

29

很晚了,但我想仍有很多人会通过“ Google Airlines”降落在这里。一种现代的方法是使用不需要服务器支持的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.";
}   

19
这确实是WebRTC之前不存在的一项新功能-查找您自己的IP地址。但是@noahjacobson提出了另一个问题-通过javascript通过主机名查找IP的DNS。
Gene Vayngrib 2015年

2
非常,非常有趣,这是一个错误或设计缺陷,反正在某些时候它会被纠正,从而不利于长期项目
电子info128

14

托管的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,请确保清洁它!


谢谢tcole!我一直在寻找:)
jClark

等一下,为什么还要使用$ _GET?就像您说的那样,这是一个漏洞。不能一个人使用:echo'getip('。$ data。');';
deweydb

7
抱歉,但是我不得不拒绝投票,因为我认为它实际上并不能回答原始问题。他们只需要标准的DNS查找,而不是用户的公共IP。
西蒙·伊斯特

2
@SimonEast嘿。您修改了一个已有7年历史的问题。做任何您需要让自己满意的事情;-)
tcole 2016年

2
我刚刚编辑了原始问题,以使其更加清晰,因为我最近正在研究同一问题,但是由于某些原因,此处的大多数答案实际上并不是原始海报所要的,因此应该张贴在另一个问题下。
西蒙·伊斯特

14

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

通过HTTPS的DNS(DoH)

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

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

DoH的目的之一是:

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

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

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

通过HTTPS JSON API进行DNS

如果您不想打扰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中使用Wireformat的DOH GET和POST的示例

这是RFC为GET和POST提供的示例(请参阅https://tools.ietf.org/html/rfc8484#section-4.1.1):

GET示例:

第一个示例请求使用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 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解析器的列表:

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


3

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

我发现使此操作变得容易的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/


我无法理解如何使用此地址来找到我自己的IP地址:<!-#echo var =“ REMOTE_ADDR”->根据您的网站。
乔治·卡林

这是大多数Web服务器上可用的标准“回显”功能。请参阅:google.co.uk/…–
内维尔·希耶尔

1
这可能是唯一能够正确,正确地解决原始问题的答案。不幸的是,它没有遵守从客户端计算机部分看到的,这可能是(或可能不是)重要的要求。
西蒙·伊斯特

@Simon-它在哪里说“从客户的计算机看”,为什么我的答案不符合此要求?
内维尔·希尔耶

1
@Simon-很好,但是由于通常由服务器提供客户端JS,因此作者/服务器所有者很可能知道此DNS限制-对于使用第三方服务器的作者来说可能是个问题。正如帖子中指出的那样,现有技术难以满足这一要求的所有限制。我的输入旨在传达我发现在服务器上最实用的解决方案。
内维尔·希尔耶


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函数调用它。


0

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



-1

自v60以来,Firefox为此WebExtensions内置了一个API:

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


无论出于什么原因,browserFirefox 64 beta中都不存在,所以我想知道是否已将其删除。
Sawtaytoes

3
@Sawtaytoes:仅对WebExtensions公开。还要注意,它需要dns许可,并且脚本不得作为内容脚本运行(同样,browser.dns不会在此处显示)
Saturnus

@Saturnus对于Firefox扩展来说很好用。有机会以某种方式对Chrome扩展程序做同样的事情吗?
drk


-2

我不认为出于安全原因,大多数浏览器都允许在纯JavaScript上下文中使用该问题。


5
这不是答案。这应该是评论!
trejder

-3

也许我错过了重点,但是在回答NAVY家伙时,浏览器可以告诉您“请求者”的IP地址(尽管可能只是他们的服务提供商)。

将脚本标记放在要由客户端调用(具有src指向)未负载均衡的另一台服务器的客户端呈现的页面中(我意识到这意味着您需要访问第二台服务器,但如今托管成本很低,您可以轻松,廉价地进行设置)。

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

在另一台服务器“ someServerIown”上,您需要具有以下ASP,ASPX或PHP页面:

-----包含如下服务器代码:

“ <%Response.Write(” var clientipaddress ='“&Request.ServerVariables(” REMOTE_ADDR“)&”';“)%>”(不带外部dbl引号:-))

----并将此代码写回到script标签:

   var clientipaddress = '178.32.21.45';

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

希望您可以访问此变量,并将其值写入准备发送回的表单控件。

当用户发布或进入下一个请求时,您的Javascript和/或表单会将“ otherServerIown”已为您填写的变量的值发送回您希望使用的服务器。

这就是我绕过哑负载均衡器的方法,该负载均衡器会掩盖客户端IP地址,并使它显示为负载均衡器的IP地址....哑...哑哑哑!

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

希望它能对某人有所帮助!抱歉,花了一年时间回答/发表意见。:-)


3
抱歉,但是我不得不拒绝投票,因为我认为它实际上并不能回答原始问题。他们只需要标准的DNS查找,而不是用户的公共IP。
西蒙·伊斯特

-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;

});

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


2
抱歉,但是我不得不拒绝投票,因为我认为它实际上并不能回答原始问题。他们只需要标准的DNS查找,而不是用户的公共IP。您的代码也没有清除$ _GET这是一个很大的安全问题。
西蒙·伊斯特

@Simon East我认为情况甚至更糟。看起来他们想通过DNS查找任何IP。
Joeri,2015年

@SimonEast您无法证明这是一个安全问题,因为您不知道我如何编译我的php。你的严格性很愚蠢。
Joeri,2016年

-10

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

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

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


8
为什么有人对此表示反对?java!= javascript,这不是答案。
斯文·莫比2015年

2
敲敲。谁在那儿?(...长时间停顿)Java Applet
迈克·内尔森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.