Can I perform a DNS lookup (hostname to IP address) using client-side Javascript?
Asked Answered
O

16

115

I would like to use client-side Javascript to perform a DNS lookup (hostname to IP address) as seen from the client's computer. Is that possible?

Overkill answered 19/9, 2008 at 15:6 Comment(1)
Many of the answers to this question seem to be recommending doing the resolution server side. Depending on the use case that may not be sufficient. For example, if the service you are looking up is using GSLB it might return a different IP based on where the user is located; as a result the response the server side code receives is quite likely to be a different response than what the browser would have received. That being said, I do not yet have an alternative solution for those that care about this difference.Aleuromancy
Y
40

There's no notion of hosts or ip-addresses in the javascript standard library. So you'll have to access some external service to look up hostnames for you.

I recommend hosting a cgi-bin which looks up the ip-address of a hostname and access that via javascript.

Yoo answered 19/9, 2008 at 15:13 Comment(5)
cgi-bin? That's old school. I like it!Cherri
This was true at the time of writing (2008). This is not true 6 years later: See my comment about WebRTC in this same page. (Unfortunatelly Google still points to this thread when searching for a solution to the IP address problem and that can put people in the wrong direction).Deeplaid
@Deeplaid - your answer is for a different question - how to discover your own private IP address.Mealtime
The problem via CGI from the cloud would be discovering intranet host ips which is not possible from the outside. You would have to use a local service on the machine or intranet.Solubilize
There's a new proposed Internet standard that allows you to send DNS queries over HTTPS (see this answer https://mcmap.net/q/74490/-can-i-perform-a-dns-lookup-hostname-to-ip-address-using-client-side-javascript). In all reality, it basically works the same as a cgi-bin script :) (except it's been standardized by the IETF and a ton of big companies support it)Rohr
N
73

Edit: This question gave me an itch, so I put up a JSONP webservice on Google App Engine that returns the clients ip address. Usage:

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

Yay, no server proxies needed.


Pure JS can't. If you have a server script under the same domain that prints it out you could send a XMLHttpRequest to read it.

Nugget answered 19/9, 2008 at 15:14 Comment(3)
Could you post the source to your web service? It would be nice to run an instance.Greyson
Sorry, but had to downvote since I don't think it actually answers the original question. They just want a standard DNS lookup, not the public IP of the user.Wendy
your url seems to be downCancan
R
61

I know this question was asked a very long time ago, but I figured I'd offer a more recent answer.

DNS over HTTPS (DoH)

You can send DNS queries over HTTPS to DNS resolvers that support it. The standard for DOH is described in RFC 8484.

This is a similar thing to what all the other answers suggest, only that DoH is actually the DNS protocol over HTTPS. It's also a "proposed" Internet standard and it's becoming quite popular. For example, some major browsers either support it or have plans to support it (Chrome, Edge, Firefox), and Microsoft is in the process of building it into their operating system.

One of the purposes of DoH is:

allowing web applications to access DNS information via existing browser APIs in a safe way consistent with Cross Origin Resource Sharing (CORS)

There's an open source tool made especially for doing DNS lookups from web applications called dohjs. It does DNS over HTTPS (DoH) wireformat queries as described in RFC 8484. It supports both GET and POST methods.

Full disclosure: I am a contributor to dohjs.

Another JavaScript library with similar features is found here - https://github.com/sc0Vu/doh-js-client. I haven't used this one personally, but I think it would work client side as well.

DNS over HTTPS JSON APIs

If you don't want to bother with DNS wireformat, both Google and Cloudflare offer JSON APIs for DNS over HTTPS.

Example Javascript code to lookup example.com with Google's JSON DOH API:

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

Examples from the RFC for DOH GET and POST with wireformat

Here are the examples the RFC gives for both GET and POST (see https://www.rfc-editor.org/rfc/rfc8484#section-4.1.1):

GET example:

The first example request uses GET to request "www.example.com".

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

POST example:

The same DNS query for "www.example.com", using the POST method would be:

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

<33 bytes represented by the following hex encoding> 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

Other places to send DOH queries

You can find a list of some public DNS resolvers that support DNS over HTTPS in a couple places:

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).

Rohr answered 9/10, 2019 at 8:18 Comment(2)
Are all of these services (e.g. - cloudflare-dns.com/dns-query?) subject to blocking by the same origin policy inside a browser? Or can JS code running inside a browser hit these DoH services as they like?Chandelier
Yes, they are all subject to CORS, so your mileage may vary depending on which server you’re hitting. If needed you can use a CORS proxy that allows anything.Rohr
Y
40

There's no notion of hosts or ip-addresses in the javascript standard library. So you'll have to access some external service to look up hostnames for you.

I recommend hosting a cgi-bin which looks up the ip-address of a hostname and access that via javascript.

Yoo answered 19/9, 2008 at 15:13 Comment(5)
cgi-bin? That's old school. I like it!Cherri
This was true at the time of writing (2008). This is not true 6 years later: See my comment about WebRTC in this same page. (Unfortunatelly Google still points to this thread when searching for a solution to the IP address problem and that can put people in the wrong direction).Deeplaid
@Deeplaid - your answer is for a different question - how to discover your own private IP address.Mealtime
The problem via CGI from the cloud would be discovering intranet host ips which is not possible from the outside. You would have to use a local service on the machine or intranet.Solubilize
There's a new proposed Internet standard that allows you to send DNS queries over HTTPS (see this answer https://mcmap.net/q/74490/-can-i-perform-a-dns-lookup-hostname-to-ip-address-using-client-side-javascript). In all reality, it basically works the same as a cgi-bin script :) (except it's been standardized by the IETF and a ton of big companies support it)Rohr
D
32

Very late, but I guess many people will still land here through "Google Airlines". A moderm approach is to use WebRTC that doesn't require server support.

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

Next code is a copy&paste from 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.";
}   
Deeplaid answered 21/9, 2014 at 17:58 Comment(2)
this indeed is a new capability which did not exist prior to WebRTC - to discover your own IP address. But @noahjacobson asked a different question - DNS lookup of IP by the hostname from javascript.Mealtime
Very, very interesting, it is a bug or design flaw, anyway at some point it will be corrected so no good for long-term projectsMugwump
G
12

The hosted JSONP version works like a charm, but it seems it goes over its resources during night time most days (Eastern Time), so I had to create my own version.

This is how I accomplished it with PHP:

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

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

Then the Javascript is exactly the same as before, just not an array:

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

Simple as that!

Side note: Be sure to clean your $_GET if you're using this in any public-facing environment!

Gossipry answered 18/8, 2011 at 20:8 Comment(5)
Wait a minute, why even use $_GET? like you said this is a vulnerability. Couldn't one just use: echo 'getip(' . $data . ');';Hypogenous
@deweydb If you control both the client and server, then you could do that. If not, then what tcole is the appropriate way to setup a JSONP callback with a configurable function name (which is very standard).Sacristan
Sorry, but had to downvote since I don't think it actually answers the original question. They just want a standard DNS lookup, not the public IP of the user.Wendy
@SimonEast Heh. You modified the question of a 7 year old question. Do whatever you need to satisfy yourself ;-)Gossipry
I merely edited the original question to make it clearer, as I was recently researching the same question, yet for some reason most answers here are not actually what the original poster was asking for and should be posted under a different question.Wendy
M
4

There's a third-party service which provides a CORS-friendly REST API to perform DNS lookups from the browser - https://exana.io/tools/dns/

Manifestative answered 6/7, 2017 at 20:15 Comment(1)
Is that subject to blocking by the browser due to same origin policy? Or does CORS let it through for any JS code inside any browser?Chandelier
K
2

I am aware this is an old question but my solution may assist others.

I find that the JSON(P) services which make this easy do not last forever but the following JavaScript works well for me at the time of writing.

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

The above writes my server's IP on the page it is located but the script can be modified to find any IP by changing 'zero.eu.org' to another domain name. This can be seen in action on my page at: http://meon.zero.eu.org/

Knudson answered 22/4, 2015 at 9:24 Comment(7)
I can't understand how to find my own ip address using this: <!--#echo var="REMOTE_ADDR"--> according to your website.Schilit
This is a standard 'echo' facility available on most web servers. See: google.co.uk/…Knudson
This is possibly the only answer that actually tackles the original question correctly, well done. Unfortunately it does not adhere to the as seen from the client's computer part, which may (or may not) be an important requirement.Wendy
@Simon - Where does it say "as seen from the client's computer" & why does my answer not comply with this?Knudson
@NevilleHillyer - Sorry, that phrase was included in the original question but when I tweaked it yesterday for clarity I actually removed it. I've re-added it as it may have been an important requirement.Wendy
@NevilleHillyer - and the reason your answer misses that particular aspect is that the browser is asking ip-api.com to perform the DNS lookup and return the result via JSONP. While this may work fine for many situations, if the hostname you're resolving uses geographical DNS resolution, different locations around the world may see a different IP address returned from the lookup. As such the IP the client sees may be different from the IP that ip-api.com sees. It might be worth adding that note to your answer.Wendy
@Simon - Good point but since normally client-side JS is server supplied there is a good chance that the author/server owner would be aware of this DNS limitation - could be an issue for authors using third party servers. As indicated in the posts here existing technology struggles to meet all the constraints on this one. My input was intended to convey the solution I have found most practical on my server.Knudson
Q
2

There is a javascript library DNS-JS.com that does just this.

DNS.Query("dns-js.com",
    DNS.QueryType.A,
    function(data) {
        console.log(data);
});
Quiteria answered 14/8, 2019 at 16:21 Comment(1)
Still not from the client's perspective. That library makes a request to dns-js.com/api.aspx to obtain the IP address which then resolves the DNS server-side.Sepulchre
B
1

As many people said you need to use an external service and call it. And that will only get you the DNS resolution from the server perspective.

If that's good enough and if you just need DNS resolution you can use the following Docker container:

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

Endpoints:

[GET] /ipv6/[domain]: Perform a DNS resolution for given domain and return the associated IPv6 addresses.

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

[GET] /ipv4/[domain]: Perform a DNS resolution for given domain and return the associated IPv4 addresses.

 {
     "addresses": [
         "139.180.232.162"
     ]
 }

My recommendation is that you setup your web server to reverse proxy to the container on a particular endpoint in your server serving your Javascript and call it using your standard Javascript Ajax functions.

Brinson answered 17/1, 2018 at 9:19 Comment(0)
C
0

Doing this would require to break the browser sandbox. Try to let your server do the lookup and request that from the client side via XmlHttp.

Coff answered 19/9, 2008 at 15:14 Comment(0)
F
0

Firefox has a built-in API for this since v60, for WebExtensions:

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

Felicafelicdad answered 4/11, 2018 at 22:11 Comment(4)
For whatever reason, browser doesn't exist in Firefox 64 beta so I wonder if that was removed.Privateer
@Sawtaytoes: It is exposed for WebExtensions only. Also note it requires dns permission and the script shall not run as a content script (as again, browser.dns would not be exposed there)Felicafelicdad
@Felicafelicdad this works fine for Firefox extensions. Any chance to do the same with Chrome extensions somehow?Schematism
This is the best solution for web extensions that only need A or TXT records for example, but isn't viable for most other records like SRV.Lunsford
G
-2

I don't think this is allowed by most browsers for security reasons, in a pure JavaScript context as the question asks.

Gemology answered 19/9, 2008 at 15:12 Comment(1)
It is not an answer. This should be a comment!Munda
G
-2

sure you can do that without using any addition, just pure javascript, by using this method of dns browser.dns.resolve("example.com"); but it is compatible just with FIREFOX 60 you can see more information on MDN https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/dns/resolve

Girandole answered 2/4, 2019 at 13:15 Comment(1)
This method is only available in the context of a WebExtension. It cannot be used by a web page.Blastosphere
B
-3

Maybe I missed the point but in reply to NAVY guy here is how the browser can tell you the 'requestor's' IP address (albeit maybe only their service provider).

Place a script tag in the page to be rendered by the client that calls (has src pointing to) another server that is not loaded balanced (I realize that this means you need access to a 2nd server but hosting is cheap these days and you can set this up easily and cheaply).

This is the kind of code that needs to be added to client page:

On the other server "someServerIown" you need to have the ASP, ASPX or PHP page that;

----- contains server code like this:

"<% Response.Write("var clientipaddress = '" & Request.ServerVariables("REMOTE_ADDR") & "';") %>" (without the outside dbl quotes :-))

---- and writes this code back to script tag:

   var clientipaddress = '178.32.21.45';

This effectively creates a Javascript variable that you can access with Javascript on the page no less.

Hopefully, you access this var and write the value to a form control ready for sending back.

When the user posts or gets on the next request your Javascript and/or form sends the value of the variable that the "otherServerIown" has filled in for you, back to the server you would like it on.

This is how I get around the dumb load balancer we have that masks the client IP address and makes it appear as that of the Load balancer .... dumb ... dumb dumb dumb!

I haven't given the exact solution because everyone's situation is a little different. The concept is sound, however. Also, note if you are doing this on an HTTPS page your "otherServerIOwn" must also deliver in that secure form otherwise Client is alerted to mixed content. And if you do have https then make sure ALL your certs are valid otherwise client also gets a warning.

Hope it helps someone! Sorry, it took a year to answer/contribute. :-)

Bona answered 5/9, 2013 at 22:13 Comment(1)
Sorry, but had to downvote since I don't think it actually answers the original question. They just want a standard DNS lookup, not the public IP of the user.Wendy
V
-4

My version is like this:

php on my server:

<?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 on the page:

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

}).done( function( json ) {

    self.ip = json;

});

It works cross domain. It could use a status check. Working on that.

Ventilate answered 29/5, 2014 at 16:17 Comment(3)
Sorry, but had to downvote since I don't think it actually answers the original question. They just want a standard DNS lookup, not the public IP of the user. Your code also does not sanitize the $_GET which is a big security issue.Wendy
@Simon East I think it's even worse. Looks like they want to look up any IP by DNS.Ventilate
@SimonEast You can't prove it's a security issue as you have no idea how I compiled my php. Your strictness is just silly.Ventilate
O
-14

If the client has Java installed, you could do something like this:

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

Other than that, you will probably have to use a server side script.

Onagraceous answered 19/9, 2008 at 15:12 Comment(1)
Why is somebody upvoting this? java != javascript, this is NOT an answer.Carmelinacarmelita

© 2022 - 2024 — McMap. All rights reserved.