Puis-je effectuer une recherche DNS (nom d'hôte vers adresse IP) à l'aide de Javascript côté client?

92

Je voudrais utiliser Javascript côté client pour effectuer une recherche DNS (nom d'hôte vers adresse IP) comme vu de l'ordinateur du client. Est-ce possible?

Noah Jacobson
la source
5
Beaucoup de réponses à cette question semblent recommander de faire du côté serveur de résolution. Selon le cas d'utilisation, cela peut ne pas être suffisant. Par exemple, si le service que vous recherchez utilise GSLB, il peut renvoyer une adresse IP différente en fonction de l'emplacement de l'utilisateur; par conséquent, la réponse que le code côté serveur reçoit est très probablement une réponse différente de celle que le navigateur aurait reçue. Cela étant dit, je n'ai pas encore de solution alternative pour ceux qui se soucient de cette différence.
Ilan Rabinovitch

Réponses:

34

Il n'y a aucune notion d'hôtes ou d'adresses IP dans la bibliothèque standard javascript. Vous devrez donc accéder à un service externe pour rechercher les noms d'hôte à votre place.

Je recommande d'héberger un cgi-bin qui recherche l'adresse IP d'un nom d'hôte et y accède via javascript.

Hans Sjunnesson
la source
26
cgi-bin? C'est la vieille école. Je l'aime!
Andrew Hedges
10
C'était vrai au moment de la rédaction (2008). Ce n'est pas vrai 6 ans plus tard: voir mon commentaire sur WebRTC dans cette même page. (Malheureusement, Google pointe toujours vers ce fil lors de la recherche d'une solution au problème d'adresse IP et qui peut mettre les gens dans la mauvaise direction).
earizon le
1
@earizon - votre réponse est pour une question différente - comment découvrir votre propre adresse IP privée.
Gene Vayngrib
Le problème via CGI à partir du cloud serait de découvrir les ips de l'hôte intranet, ce qui n'est pas possible de l'extérieur. Vous devrez utiliser un service local sur la machine ou l'intranet.
Tzahi Fadida
Il existe une nouvelle norme Internet proposée qui vous permet d'envoyer des requêtes DNS via HTTPS (voir cette réponse stackoverflow.com/a/58299823/9638991 ). Dans toute la réalité, cela fonctionne fondamentalement de la même manière qu'un script cgi-bin :) (sauf qu'il a été normalisé par l'IETF et qu'une tonne de grandes entreprises le supportent)
kimbo
82

Edit : Cette question m'a donné une démangeaison, alors j'ai mis en place un service Web JSONP sur Google App Engine qui renvoie l'adresse IP du client. 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>

Oui, aucun proxy de serveur n'est nécessaire.


Pure JS ne peut pas. Si vous avez un script serveur sous le même domaine qui l'imprime, vous pouvez envoyer un XMLHttpRequest pour le lire.

Zach
la source
4
Pourriez-vous publier la source sur votre service Web? Ce serait bien d'exécuter une instance.
Sera
18
Désolé, mais j'ai dû voter contre car je ne pense pas qu'il réponde réellement à la question initiale. Ils veulent juste une recherche DNS standard, pas l'adresse IP publique de l'utilisateur.
Simon East
29

Très tard, mais je suppose que beaucoup de gens atterriront encore ici via "Google Airlines". Une approche moderm consiste à utiliser WebRTC qui ne nécessite pas de support serveur.

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

Le code suivant est un copier-coller de 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.";
}   
Erizon
la source
19
c'est en effet une nouvelle capacité qui n'existait pas avant WebRTC - pour découvrir votre propre adresse IP. Mais @noahjacobson a posé une question différente - la recherche DNS de l'IP par le nom d'hôte de javascript.
Gene Vayngrib
2
Très, très intéressant, c'est un bug ou un défaut de conception, de toute façon à un moment donné, il sera corrigé donc pas bon pour les projets à long terme
e-info128
14

La version hébergée de JSONP fonctionne comme un charme, mais il semble qu'elle dépasse ses ressources pendant la nuit la plupart des jours (heure de l'Est), j'ai donc dû créer ma propre version.

Voici comment je l'ai accompli avec PHP:

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

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

Ensuite, le Javascript est exactement le même qu'avant, mais pas un tableau:

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

Aussi simple que cela!

Remarque: assurez-vous de nettoyer votre $ _GET si vous l'utilisez dans un environnement public!

tcole
la source
Merci tcole! Juste ce que je cherchais :)
jClark
Attendez une minute, pourquoi même utiliser $ _GET? comme vous l'avez dit, c'est une vulnérabilité. On ne pourrait pas simplement utiliser: echo 'getip ('. $ Data. ');';
deweydb
7
Désolé, mais j'ai dû voter contre car je ne pense pas qu'il réponde réellement à la question initiale. Ils veulent juste une recherche DNS standard, pas l'adresse IP publique de l'utilisateur.
Simon East
2
@SimonEast Heh. Vous avez modifié la question d'une question vieille de 7 ans. Faites tout ce dont vous avez besoin pour vous satisfaire ;-)
tcole
2
J'ai simplement modifié la question originale pour la rendre plus claire, car je recherchais récemment la même question, mais pour une raison quelconque, la plupart des réponses ici ne sont pas réellement ce que l'affiche originale demandait et devraient être publiées sous une question différente.
Simon East
14

Je sais que cette question a été posée il y a très longtemps, mais j'ai pensé que je proposerais une réponse plus récente.

DNS sur HTTPS (DoH)

Vous pouvez envoyer des requêtes DNS via HTTPS aux résolveurs DNS qui le prennent en charge. La norme pour DOH est décrite dans la RFC 8484 .

C'est une chose similaire à ce que suggèrent toutes les autres réponses, seulement que DoH est en fait le protocole DNS sur HTTPS. C'est aussi une norme Internet «proposée» et elle devient très populaire. Par exemple, certains grands navigateurs le prennent en charge ou prévoient de le prendre en charge (Chrome, Edge, Firefox), et Microsoft est en train de l'intégrer à leur système d'exploitation.

L'un des objectifs de DoH est:

permettant aux applications Web d'accéder aux informations DNS via les API de navigateur existantes d'une manière sûre et cohérente avec le partage de ressources Cross Origin (CORS)

Il existe un outil open source spécialement conçu pour effectuer des recherches DNS à partir d'applications Web appelées dohjs . Il effectue des requêtes de format filaire DNS sur HTTPS (DoH) comme décrit dans la RFC 8484 . Il prend en charge les méthodes GET et POST.

Divulgation complète: je contribue aux dohjs.

DNS sur les API JSON HTTPS

Si vous ne voulez pas vous soucier du format filaire DNS, Google et Cloudflare proposent des API JSON pour DNS sur HTTPS.

Exemple de code Javascript à rechercher sur example.com avec l'API JSON DOH de Google:

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

Exemples de la RFC pour DOH GET et POST avec wireformat

Voici les exemples que la RFC donne pour GET et POST (voir https://tools.ietf.org/html/rfc8484#section-4.1.1 ):

GET exemple:

Le premier exemple de demande utilise GET pour demander "www.example.com".

: method = GET
: schéma = https
: autorité = dnsserver.example.net
: chemin = / dns-query? dns = AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB
accept = application / dns-message

Exemple POST:

La même requête DNS pour "www.example.com", en utilisant la méthode POST serait:

: method = POST
: schéma = https
: autorité = dnsserver.example.net
: chemin = / dns-query
accept = application / dns-message
content-type = application / dns-message
content-length = 33

<33 octets représentés par le codage hexadécimal suivant> 00 00 01 00 00 01 00 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

Autres endroits pour envoyer des requêtes DOH

Vous pouvez trouver une liste de certains résolveurs DNS publics qui prennent en charge DNS sur HTTPS à quelques endroits:

Parmi les ressources ci-dessus, je dirais que la liste sur le wiki de Curl et la liste DNSCrypt sont probablement les plus complètes et les plus fréquemment mises à jour. La page de Curl comprend également une liste d'outils open source pour DoH (serveurs, proxies, bibliothèques client, etc.).

Kimbo
la source
3

Je suis conscient que c'est une vieille question, mais ma solution peut aider les autres.

Je trouve que les services JSON (P) qui rendent cela facile ne durent pas éternellement, mais le JavaScript suivant fonctionne bien pour moi au moment de la rédaction.

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

Ce qui précède écrit l'adresse IP de mon serveur sur la page où il se trouve, mais le script peut être modifié pour trouver n'importe quelle adresse IP en remplaçant «zero.eu.org» par un autre nom de domaine. Cela peut être vu en action sur ma page à: http://meon.zero.eu.org/

Neville Hillyer
la source
Je ne comprends pas comment trouver ma propre adresse IP en utilisant ceci: <! - # echo var = "REMOTE_ADDR" -> en fonction de votre site Web.
George Carlin
Il s'agit d'une fonction «écho» standard disponible sur la plupart des serveurs Web. Voir: google.co.uk/...
Neville Hillyer
1
C'est peut-être la seule réponse qui aborde correctement la question initiale, bravo. Malheureusement, il ne respecte pas la vue de la partie ordinateur du client , ce qui peut (ou non) être une exigence importante.
Simon East
@Simon - Où est-il dit "vu de l'ordinateur du client" et pourquoi ma réponse n'est-elle pas conforme à cela?
Neville Hillyer du
1
@Simon - Bon point mais puisque normalement JS côté client est fourni par le serveur, il y a de fortes chances que l'auteur / propriétaire du serveur soit au courant de cette limitation DNS - pourrait être un problème pour les auteurs utilisant des serveurs tiers. Comme indiqué dans les articles ici, la technologie existante peine à répondre à toutes les contraintes de celle-ci. Ma contribution visait à transmettre la solution que j'ai trouvée la plus pratique sur mon serveur.
Neville Hillyer
3

Il existe un service tiers qui fournit une API REST compatible CORS pour effectuer des recherches DNS à partir du navigateur - https://exana.io/tools/dns/

user670908
la source
1

Comme beaucoup de gens l'ont dit, vous devez utiliser un service externe et l'appeler. Et cela ne vous donnera la résolution DNS que du point de vue du serveur.

Si cela suffit et si vous avez juste besoin d'une résolution DNS, vous pouvez utiliser le conteneur Docker suivant:

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

Points de terminaison:

[GET] /ipv6/[domain]: Effectuez une résolution DNS pour un domaine donné et renvoyez les adresses IPv6 associées.

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

[GET] /ipv4/[domain]: Effectuez une résolution DNS pour un domaine donné et renvoyez les adresses IPv4 associées.

 {
     "addresses": [
         "139.180.232.162"
     ]
 }

Ma recommandation est de configurer votre serveur Web pour inverser le proxy vers le conteneur sur un point de terminaison particulier de votre serveur servant votre Javascript et de l'appeler en utilisant vos fonctions Javascript Ajax standard.

Havok
la source
0

Cela nécessiterait de casser le bac à sable du navigateur. Essayez de laisser votre serveur faire la recherche et demandez cela du côté client via XmlHttp.

Tomalak
la source
0

Il existe une bibliothèque javascript DNS-JS.com qui fait exactement cela.

DNS.Query("dns-js.com",
    DNS.QueryType.A,
    function(data) {
        console.log(data);
});
Fiach Reid
la source
1
Toujours pas du point de vue du client. Cette bibliothèque fait une demande à dns-js.com/api.aspx pour obtenir l'adresse IP qui résout ensuite le serveur DNS.
wp-overwatch.com
-1

Firefox a une API intégrée pour cela depuis la v60, pour les WebExtensions:

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

Saturnus
la source
Pour une raison quelconque, browsern'existe pas dans Firefox 64 beta, donc je me demande si cela a été supprimé.
Sawtaytoes
3
@Sawtaytoes: il n'est exposé que pour les WebExtensions . Notez également qu'il nécessite une dnsautorisation et que le script ne doit pas s'exécuter en tant que script de contenu (comme encore une fois, browser.dnsil n'y serait pas exposé)
Saturnus
@Saturnus cela fonctionne bien pour les extensions Firefox. Avez-vous une chance de faire de même avec les extensions Chrome?
drk
-1

bien sûr que vous pouvez le faire sans utiliser d'ajout, juste du javascript pur, en utilisant cette méthode de DNS browser.dns.resolve("example.com"); mais elle est compatible uniquement avec FIREFOX 60, vous pouvez voir plus d'informations sur MDN https://developer.mozilla.org/en-US/docs / Mozilla / Modules complémentaires / WebExtensions / API / dns / resolution

Yassine Farroud
la source
4
Cette méthode n'est disponible que dans le contexte d'une WebExtension. Il ne peut pas être utilisé par une page Web.
duskwuff -inactif-
-2

Je ne pense pas que cela soit autorisé par la plupart des navigateurs pour des raisons de sécurité, dans un contexte purement JavaScript comme le demande la question.

Nick Craver
la source
5
Ce n'est pas une réponse. Cela devrait être un commentaire!
trejder
-3

Peut-être que j'ai manqué le point, mais en réponse à NAVY guy, voici comment le navigateur peut vous dire l'adresse IP du `` demandeur '' (bien que peut-être seulement leur fournisseur de services).

Placez une balise de script dans la page à rendre par le client qui appelle (a src pointant vers) un autre serveur qui n'est pas chargé équilibré (je me rends compte que cela signifie que vous avez besoin d'accéder à un 2ème serveur mais l'hébergement est bon marché de nos jours et vous pouvez installez-le facilement et à moindre coût).

Voici le type de code qui doit être ajouté à la page client:

Sur l'autre serveur "someServerIown", vous devez avoir la page ASP, ASPX ou PHP qui;

----- contient un code serveur comme celui-ci:

"<% Response.Write (" var clientipaddress = '"& Request.ServerVariables (" REMOTE_ADDR ") &"'; ")%>" (sans les guillemets extérieurs de la dbl :-))

---- et réécrit ce code dans la balise script:

   var clientipaddress = '178.32.21.45';

Cela crée effectivement une variable Javascript à laquelle vous pouvez accéder avec Javascript sur la page pas moins.

J'espère que vous accédez à cette variable et écrivez la valeur dans un contrôle de formulaire prêt à être renvoyé.

Lorsque l'utilisateur poste ou reçoit la prochaine requête, votre Javascript et / ou votre formulaire envoie la valeur de la variable que le "otherServerIown" a renseignée pour vous, retournez au serveur sur lequel vous le souhaitez.

C'est ainsi que je contourne l'équilibreur de charge stupide que nous avons qui masque l'adresse IP du client et la fait apparaître comme celle de l'équilibreur de charge .... stupide ... stupide stupide stupide!

Je n'ai pas donné la solution exacte car la situation de chacun est un peu différente. Le concept est cependant solide. Notez également que si vous faites cela sur une page HTTPS, votre «otherServerIOwn» doit également fournir sous cette forme sécurisée, sinon le client est alerté du contenu mixte. Et si vous avez https, assurez-vous que TOUS vos certificats sont valides, sinon le client reçoit également un avertissement.

J'espère que cela aide quelqu'un! Désolé, il a fallu un an pour répondre / contribuer. :-)

Factures
la source
3
Désolé, mais j'ai dû voter contre car je ne pense pas qu'il réponde réellement à la question initiale. Ils veulent juste une recherche DNS standard, pas l'adresse IP publique de l'utilisateur.
Simon East
-4

Ma version est comme ça:

php sur mon serveur:

<?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 sur la page:

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

}).done( function( json ) {

    self.ip = json;

});

Cela fonctionne dans plusieurs domaines. Il pourrait utiliser une vérification de l'état. Travailler là-dessus.

Joeri
la source
2
Désolé, mais j'ai dû voter contre car je ne pense pas qu'il réponde réellement à la question initiale. Ils veulent juste une recherche DNS standard, pas l'adresse IP publique de l'utilisateur. Votre code ne nettoie pas non plus le $ _GET, ce qui est un gros problème de sécurité.
Simon East
@Simon East, je pense que c'est encore pire. On dirait qu'ils veulent rechercher n'importe quelle adresse IP par DNS.
Joeri
@SimonEast Vous ne pouvez pas prouver que c'est un problème de sécurité car vous n'avez aucune idée de la façon dont j'ai compilé mon php. Votre rigueur est tout simplement stupide.
Joeri
-10

Si Java est installé sur le client, vous pouvez faire quelque chose comme ceci:

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

En dehors de cela, vous devrez probablement utiliser un script côté serveur.

Alex Fort
la source
8
Pourquoi quelqu'un vote-t-il pour cela? java! = javascript, ce n'est PAS une réponse.
Sven Mawby le
2
Toc Toc. Qui est là? (... longue pause) Java Applet
mike nelson