¿Puedo realizar una búsqueda de DNS (nombre de host a dirección IP) usando Javascript del lado del cliente?

92

Me gustaría usar Javascript del lado del cliente para realizar una búsqueda de DNS (nombre de host a dirección IP) como se ve desde la computadora del cliente. ¿Es eso posible?

Noah Jacobson
fuente
5
Muchas de las respuestas a esta pregunta parecen recomendar hacer la resolución del lado del servidor. Dependiendo del caso de uso, puede que no sea suficiente. Por ejemplo, si el servicio que está buscando utiliza GSLB, podría devolver una IP diferente según la ubicación del usuario; como resultado, es muy probable que la respuesta que reciba el código del lado del servidor sea una respuesta diferente a la que habría recibido el navegador. Dicho esto, todavía no tengo una solución alternativa para aquellos que se preocupan por esta diferencia.
Ilan Rabinovitch

Respuestas:

35

No hay noción de hosts o direcciones IP en la biblioteca estándar de JavaScript. Por lo tanto, tendrá que acceder a algún servicio externo para buscar nombres de host por usted.

Recomiendo alojar un cgi-bin que busque la dirección IP de un nombre de host y acceda a él a través de javascript.

Hans Sjunnesson
fuente
26
cgi-bin? Eso es la vieja escuela. ¡Me gusta!
Andrew Hedges
10
Esto era cierto en el momento de escribir este artículo (2008). Esto no es cierto 6 años después: vea mi comentario sobre WebRTC en esta misma página. (Desafortunadamente, Google todavía apunta a este hilo cuando busca una solución al problema de la dirección IP y eso puede poner a las personas en la dirección equivocada).
earizon
1
@earizon: su respuesta es para una pregunta diferente: cómo descubrir su propia dirección IP privada.
Gene Vayngrib
El problema a través de CGI desde la nube sería descubrir ips de host de intranet, lo que no es posible desde el exterior. Tendría que utilizar un servicio local en la máquina o intranet.
Tzahi Fadida
Hay un nuevo estándar de Internet propuesto que le permite enviar consultas de DNS a través de HTTPS (consulte esta respuesta stackoverflow.com/a/58299823/9638991 ). En realidad, básicamente funciona igual que un script cgi-bin :) (excepto que ha sido estandarizado por el IETF y un montón de grandes empresas lo apoyan)
kimbo
83

Editar : esta pregunta me dio comezón, así que puse un servicio web JSONP en Google App Engine que devuelve la dirección IP de los clientes. Uso:

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

Sí, no se necesitan servidores proxy.


Pure JS no puede. Si tiene un script de servidor en el mismo dominio que lo imprime, puede enviar un XMLHttpRequest para leerlo.

Zach
fuente
4
¿Podría publicar la fuente en su servicio web? Sería bueno ejecutar una instancia.
Will el
18
Lo siento, pero tuve que votar en contra ya que no creo que realmente responda a la pregunta original. Solo quieren una búsqueda de DNS estándar, no la IP pública del usuario.
Simon East
30

Muy tarde, pero supongo que mucha gente todavía aterrizará aquí a través de "Google Airlines". Un enfoque moderno es utilizar WebRTC que no requiere soporte de servidor.

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

El siguiente código es copiar y pegar 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.";
}   
earizon
fuente
19
De hecho, esta es una nueva capacidad que no existía antes de WebRTC: descubrir su propia dirección IP. Pero @noahjacobson hizo una pregunta diferente: búsqueda de DNS de IP por el nombre de host de javascript.
Gene Vayngrib
2
Muy, muy interesante, es un error o falla de diseño, de todos modos en algún momento se corregirá, por lo que no es bueno para proyectos a largo plazo
e-info128
16

Sé que esta pregunta se hizo hace mucho tiempo, pero pensé que ofrecería una respuesta más reciente.

DNS sobre HTTPS (DoH)

Puede enviar consultas de DNS a través de HTTPS a los resolutores de DNS que lo admitan. El estándar para DOH se describe en RFC 8484 .

Esto es similar a lo que sugieren todas las otras respuestas, solo que DoH es en realidad el protocolo DNS sobre HTTPS. También es un estándar de Internet "propuesto" y se está volviendo bastante popular. Por ejemplo, algunos de los principales navegadores lo admiten o tienen planes de admitirlo (Chrome, Edge, Firefox), y Microsoft está en proceso de integrarlo en su sistema operativo.

Uno de los propósitos del DoH es:

Permitir que las aplicaciones web accedan a la información del DNS a través de las API de navegador existentes de una manera segura de acuerdo con Cross Origin Resource Sharing (CORS)

Existe una herramienta de código abierto creada especialmente para realizar búsquedas de DNS desde aplicaciones web llamadas dohjs . Realiza consultas de formato de cable DNS sobre HTTPS (DoH) como se describe en RFC 8484 . Es compatible con los métodos GET y POST.

Divulgación completa: soy colaborador de dohjs.

DNS sobre HTTPS JSON API

Si no quiere molestarse con el formato de cable de DNS, tanto Google como Cloudflare ofrecen API JSON para DNS sobre HTTPS.

Ejemplo de código Javascript para buscar example.com con la API JSON DOH de Google:

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

Ejemplos de RFC para DOH GET y POST con formato de cable

Estos son los ejemplos que ofrece el RFC tanto para GET como para POST (consulte https://tools.ietf.org/html/rfc8484#section-4.1.1 ):

OBTENER ejemplo:

La primera solicitud de ejemplo usa GET para solicitar "www.example.com".

: método = OBTENER
: esquema = https
: autoridad = dnsserver.example.net
: ruta = / dns-query? dns = AAABAAABAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB
accept = application / dns-message

Ejemplo de POST:

La misma consulta de DNS para "www.example.com", utilizando el método POST sería:

: método = POST
: esquema = https
: autoridad = dnsserver.example.net
: ruta = / dns-query
accept = application / dns-message
content-type = application / dns-message
content-length = 33

<33 bytes representados por la siguiente codificación hexadecimal> 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

Otros lugares para enviar consultas DOH

Puede encontrar una lista de algunos solucionadores de DNS públicos que admiten DNS sobre HTTPS en un par de lugares:

De los recursos anteriores, diría que la lista en la wiki de Curl y la lista de DNSCrypt son probablemente las más completas y las que se actualizan con mayor frecuencia. La página de Curl también incluye una lista de herramientas de código abierto para DoH (servidores, proxies, bibliotecas de clientes, etc.).

kimbo
fuente
14

La versión JSONP alojada funciona de maravilla, pero parece que pasa por encima de sus recursos durante la noche la mayoría de los días (hora del este), así que tuve que crear mi propia versión.

Así es como lo logré con PHP:

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

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

Entonces el Javascript es exactamente el mismo que antes, pero no una matriz:

<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 como eso!

Nota al margen: ¡asegúrese de limpiar su $ _GET si lo está utilizando en cualquier entorno público!

tcole
fuente
Gracias tcole! Justo lo que estaba buscando :)
jClark
Espera un minuto, ¿por qué usar $ _GET? como dijiste, esto es una vulnerabilidad. ¿No se podría simplemente usar: echo 'getip ('. $ Data. ');';
deweydb
7
Lo siento, pero tuve que votar en contra ya que no creo que realmente responda a la pregunta original. Solo quieren una búsqueda de DNS estándar, no la IP pública del usuario.
Simon East
2
@SimonEast Heh. Modificó la pregunta de una pregunta de 7 años. Haz lo que necesites para satisfacerte ;-)
tcole
2
Simplemente edité la pregunta original para aclararla, ya que recientemente estuve investigando la misma pregunta, pero por alguna razón la mayoría de las respuestas aquí no son en realidad las que pedía el póster original y deberían publicarse con una pregunta diferente.
Simon East
3

Soy consciente de que esta es una pregunta antigua, pero mi solución puede ayudar a otros.

Encuentro que los servicios JSON (P) que facilitan esto no duran para siempre, pero el siguiente JavaScript funciona bien para mí en el momento de escribir este artículo.

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

Lo anterior escribe la IP de mi servidor en la página en la que se encuentra, pero el script se puede modificar para encontrar cualquier IP cambiando 'zero.eu.org' a otro nombre de dominio. Esto se puede ver en acción en mi página en: http://meon.zero.eu.org/

Neville Hillyer
fuente
No puedo entender cómo encontrar mi propia dirección IP usando esto: <! - # echo var = "REMOTE_ADDR" -> de acuerdo con su sitio web.
George Carlin
Esta es una función estándar de 'eco' disponible en la mayoría de los servidores web. Ver: google.co.uk/…
Neville Hillyer
1
Esta es posiblemente la única respuesta que realmente aborda la pregunta original correctamente, bien hecho. Desafortunadamente, no se adhiere a lo visto desde la parte de la computadora del cliente , lo que puede (o no) ser un requisito importante.
Simon East
@Simon - ¿Dónde dice "visto desde la computadora del cliente" y por qué mi respuesta no cumple con esto?
Neville Hillyer
1
@Simon: buen punto, pero dado que normalmente JS del lado del cliente es suministrado por el servidor, existe una buena posibilidad de que el autor / propietario del servidor esté al tanto de esta limitación de DNS; podría ser un problema para los autores que utilizan servidores de terceros. Como se indica en las publicaciones aquí, la tecnología existente lucha por cumplir con todas las limitaciones de esta. Mi entrada tenía como objetivo transmitir la solución que he encontrado más práctica en mi servidor.
Neville Hillyer
3

Hay un servicio de terceros que proporciona una API REST compatible con CORS para realizar búsquedas de DNS desde el navegador: https://exana.io/tools/dns/

usuario670908
fuente
1

Como han dicho muchas personas, es necesario utilizar un servicio externo y llamarlo. Y eso solo le dará la resolución de DNS desde la perspectiva del servidor.

Si eso es lo suficientemente bueno y si solo necesita una resolución de DNS, puede usar el siguiente contenedor de Docker:

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

Puntos finales:

[GET] /ipv6/[domain]: Realiza una resolución de DNS para un dominio determinado y devuelve las direcciones IPv6 asociadas.

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

[GET] /ipv4/[domain]: Realiza una resolución de DNS para un dominio determinado y devuelve las direcciones IPv4 asociadas.

 {
     "addresses": [
         "139.180.232.162"
     ]
 }

Mi recomendación es que configure su servidor web para invertir el proxy al contenedor en un punto final particular en su servidor que sirve su Javascript y lo llame usando sus funciones estándar de Javascript Ajax.

Havok
fuente
1

Hay una biblioteca de JavaScript DNS-JS.com que hace precisamente esto.

DNS.Query("dns-js.com",
    DNS.QueryType.A,
    function(data) {
        console.log(data);
});
Fiach Reid
fuente
1
Todavía no desde la perspectiva del cliente. Esa biblioteca realiza una solicitud a dns-js.com/api.aspx para obtener la dirección IP que luego resuelve el lado del servidor DNS.
wp-overwatch.com
0

Hacer esto requeriría romper la caja de arena del navegador. Intente dejar que su servidor realice la búsqueda y solicítelo desde el lado del cliente a través de XmlHttp.

Tomalak
fuente
-1

Firefox tiene una API incorporada para esto desde v60, para WebExtensions:

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

Saturno
fuente
Por alguna razón, browserno existe en Firefox 64 beta, así que me pregunto si se eliminó.
Kevin Ghadyani
3
@Sawtaytoes: se expone solo para WebExtensions . También tenga en cuenta que requiere dnspermiso y el script no se ejecutará como un script de contenido (como nuevamente, browser.dnsno estaría expuesto allí)
Saturnus
@Saturnus esto funciona bien para las extensiones de Firefox. ¿Alguna posibilidad de hacer lo mismo con las extensiones de Chrome de alguna manera?
drk
-2

No creo que esto esté permitido por la mayoría de los navegadores por razones de seguridad, en un contexto de JavaScript puro, como pregunta la pregunta.

Nick Craver
fuente
5
No es una respuesta. ¡Esto debería ser un comentario!
trejder
-3

Tal vez no entendí el punto, pero en respuesta a NAVY guy, aquí está cómo el navegador puede decirle la dirección IP del 'solicitante' (aunque tal vez solo su proveedor de servicios).

Coloque una etiqueta de secuencia de comandos en la página para que la procese el cliente que llama (tiene src apuntando a) otro servidor que no está cargado equilibrado (me doy cuenta de que esto significa que necesita acceso a un segundo servidor, pero el alojamiento es barato en estos días y puede configúrelo de manera fácil y económica).

Este es el tipo de código que debe agregarse a la página del cliente:

En el otro servidor "someServerIown" necesita tener la página ASP, ASPX o PHP que;

----- contiene código de servidor como este:

"<% Response.Write (" var clientipaddress = '"& Request.ServerVariables (" REMOTE_ADDR ") &"'; ")%>" (sin las comillas dbl externas :-))

---- y escribe este código en la etiqueta del script:

   var clientipaddress = '178.32.21.45';

Esto crea efectivamente una variable de Javascript a la que puede acceder con Javascript en la página nada menos.

Con suerte, acceda a esta var y escriba el valor en un control de formulario listo para enviar.

Cuando el usuario publica o recibe la siguiente solicitud, su Javascript y / o formulario envía el valor de la variable que "otherServerIown" ha completado para usted, de regreso al servidor en el que le gustaría.

Así es como me muevo por el tonto balanceador de carga que tenemos que enmascara la dirección IP del cliente y hace que parezca la del balanceador de carga .... tonto ... tonto tonto tonto!

No he dado la solución exacta porque la situación de todos es un poco diferente. Sin embargo, el concepto es sólido. Además, tenga en cuenta que si está haciendo esto en una página HTTPS, su "otherServerIOwn" también debe entregarse en esa forma segura, de lo contrario, el Cliente recibirá una alerta sobre contenido mixto. Y si tiene https, asegúrese de que TODOS sus certificados sean válidos; de lo contrario, el cliente también recibirá una advertencia.

¡Espero que ayude a alguien! Lo siento, me tomó un año responder / contribuir. :-)

Bill S
fuente
3
Lo siento, pero tuve que votar en contra ya que no creo que realmente responda a la pregunta original. Solo quieren una búsqueda de DNS estándar, no la IP pública del usuario.
Simon East
-4

Mi versión es así:

php en mi servidor:

<?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 en la página:

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

}).done( function( json ) {

    self.ip = json;

});

Funciona en dominios cruzados. Podría usar una verificación de estado. Trabajando en ello.

Joeri
fuente
2
Lo siento, pero tuve que votar en contra ya que no creo que realmente responda a la pregunta original. Solo quieren una búsqueda de DNS estándar, no la IP pública del usuario. Su código tampoco desinfecta el $ _GET, que es un gran problema de seguridad.
Simon East
@Simon East Creo que es aún peor. Parece que quieren buscar cualquier IP por DNS.
Joeri
@SimonEast No puedes probar que es un problema de seguridad ya que no tienes idea de cómo compilé mi archivo php. Tu rigor es una tontería.
Joeri
-10

Si el cliente tiene Java instalado, puede hacer algo como esto:

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

Aparte de eso, probablemente tendrá que usar un script del lado del servidor.

Alex Fort
fuente
8
¿Por qué alguien vota a favor de esto? java! = javascript, esto NO es una respuesta.
Sven Mawby
2
TOC Toc. ¿Quién está ahí? (... pausa larga) Applet de Java
mike nelson