Posso realizar uma pesquisa DNS (nome do host para endereço IP) usando Javascript do lado do cliente?

92

Eu gostaria de usar Javascript do lado do cliente para realizar uma pesquisa DNS (nome do host para endereço IP), visto do computador do cliente. Isso é possível?

Noah Jacobson
fonte
5
Muitas das respostas a esta pergunta parecem recomendar fazer a resolução do lado do servidor. Dependendo do caso de uso, isso pode não ser suficiente. Por exemplo, se o serviço que você está procurando está usando GSLB, ele pode retornar um IP diferente com base em onde o usuário está localizado; como resultado, a resposta que o código do lado do servidor recebe provavelmente será uma resposta diferente da que o navegador teria recebido. Dito isso, ainda não tenho uma solução alternativa para quem se preocupa com essa diferença.
Ilan Rabinovitch

Respostas:

34

Não há noção de hosts ou endereços IP na biblioteca padrão javascript. Portanto, você terá que acessar algum serviço externo para pesquisar nomes de host para você.

Eu recomendo hospedar um cgi-bin que procura o endereço IP de um nome de host e acessa-o via javascript.

Hans Sjunnesson
fonte
26
cgi-bin? Isso é velha escola. Eu gosto disso!
Andrew Hedges,
10
Isso era verdade no momento da escrita (2008). Isso não é verdade 6 anos depois: Veja meu comentário sobre WebRTC nesta mesma página. (Infelizmente, o Google ainda aponta para este tópico ao buscar uma solução para o problema do endereço IP e que pode colocar as pessoas na direção errada).
earizon
1
@earizon - sua resposta é para uma pergunta diferente - como descobrir seu próprio endereço IP privado.
Gene Vayngrib de
O problema via CGI da nuvem seria descobrir ips de host da intranet que não é possível de fora. Você teria que usar um serviço local na máquina ou intranet.
Tzahi Fadida de
Há um novo padrão de Internet proposto que permite enviar consultas DNS por HTTPS (consulte esta resposta stackoverflow.com/a/58299823/9638991 ). Em toda a realidade, basicamente funciona da mesma forma que um script cgi-bin :) (exceto que foi padronizado pela IETF e uma tonelada de grandes empresas o apóia)
kimbo
83

Edit : Esta questão me deu uma coceira, então eu coloquei um serviço da web JSONP no Google App Engine que retorna o endereço IP do cliente. 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>

Oba, não são necessários proxies de servidor.


JS puro não pode. Se você tiver um script de servidor no mesmo domínio que o imprime, poderá enviar um XMLHttpRequest para lê-lo.

Zach
fonte
4
Você poderia postar a fonte em seu serviço da web? Seria bom executar uma instância.
Will
18
Desculpe, mas tive que votar negativamente, pois não acho que realmente responda à pergunta original. Eles querem apenas uma pesquisa de DNS padrão, não o IP público do usuário.
Simon East
29

Muito tarde, mas acho que muitas pessoas ainda vão pousar aqui através do "Google Airlines". Uma abordagem moderada é usar WebRTC que não requer suporte de servidor.

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

O próximo código é copiar e colar 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
fonte
19
na verdade, esse é um novo recurso que não existia antes do WebRTC - descobrir seu próprio endereço IP. Mas @noahjacobson fez uma pergunta diferente - pesquisa DNS de IP pelo nome do host em javascript.
Gene Vayngrib de
2
Muito, muito interessante, é um bug ou falha de design, de qualquer forma, em algum momento será corrigido, portanto, não é bom para projetos de longo prazo
e-info128
14

A versão JSONP hospedada funciona perfeitamente, mas parece que gasta seus recursos durante a noite na maioria dos dias (horário do leste), então tive que criar minha própria versão.

Foi assim que fiz isso com o PHP:

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

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

Então, o Javascript é exatamente o mesmo de antes, mas não uma 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>

Simples assim!

Observação lateral: certifique-se de limpar seu $ _GET se estiver usando em qualquer ambiente voltado para o público!

tcole
fonte
Obrigado tcole! Exatamente o que eu estava procurando :)
jClark
Espere um minuto, por que usar $ _GET? como você disse, isso é uma vulnerabilidade. Não se poderia simplesmente usar: echo 'getip ('. $ Data. ');';
deweydb
7
Desculpe, mas tive que votar negativamente, pois não acho que realmente responda à pergunta original. Eles querem apenas uma pesquisa de DNS padrão, não o IP público do usuário.
Simon East
2
@SimonEast Heh. Você modificou a pergunta de uma pergunta de 7 anos. Faça o que for preciso para se satisfazer ;-)
tcole
2
Eu meramente editei a pergunta original para torná-la mais clara, já que recentemente estava pesquisando a mesma pergunta, mas por algum motivo a maioria das respostas aqui não é realmente o que o autor do pôster original estava pedindo e deveria ser postado em uma pergunta diferente.
Simon East
14

Sei que essa pergunta foi feita há muito tempo, mas decidi oferecer uma resposta mais recente.

DNS sobre HTTPS (DoH)

Você pode enviar consultas DNS por HTTPS para resolvedores de DNS que o suportam. O padrão para DOH é descrito no RFC 8484 .

Isso é semelhante ao que todas as outras respostas sugerem, apenas que DoH é na verdade o protocolo DNS sobre HTTPS. É também um padrão "proposto" da Internet e está se tornando bastante popular. Por exemplo, alguns dos principais navegadores o suportam ou têm planos de suportá-lo (Chrome, Edge, Firefox), e a Microsoft está em processo de integrá-lo em seu sistema operacional.

Um dos objetivos do DoH é:

permitindo que aplicativos da web acessem informações de DNS por meio de APIs de navegador existentes de maneira segura e consistente com o Cross Origin Resource Sharing (CORS)

Existe uma ferramenta de código aberto feita especialmente para fazer pesquisas de DNS em aplicativos da web chamada dohjs . Ele faz consultas em formato de fio DNS sobre HTTPS (DoH), conforme descrito em RFC 8484 . Ele suporta os métodos GET e POST.

Divulgação completa: eu contribuo com dohjs.

DNS sobre APIs JSON HTTPS

Se você não quiser se preocupar com o formato de cabo do DNS, o Google e o Cloudflare oferecem APIs JSON para DNS sobre HTTPS.

Exemplo de código Javascript para pesquisar example.com com a API JSON DOH do Google:

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

Exemplos do RFC para DOH GET e POST com wireformat

Aqui estão os exemplos que o RFC fornece para GET e POST (consulte https://tools.ietf.org/html/rfc8484#section-4.1.1 ):

Exemplo GET:

O primeiro exemplo de solicitação usa GET para solicitar "www.example.com".

: método = GET
: esquema = https
: autoridade = dnsserver.example.net
: caminho = / dns-query? dns = AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB
aceitar = aplicativo / dns-mensagem

Exemplo de POST:

A mesma consulta DNS para "www.example.com", usando o método POST seria:

: método = POST
: esquema = https
: autoridade = dnsserver.example.net
: caminho = / dns-query
aceitar = application / dns-message
content-type = application / dns-message
content-length = 33

<33 bytes representados pela seguinte codificação 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

Outros lugares para enviar consultas DOH

Você pode encontrar uma lista de alguns resolvedores de DNS públicos compatíveis com DNS sobre HTTPS em alguns lugares:

Dos recursos acima, eu diria que a lista no wiki do Curl e a lista DNSCrypt são provavelmente as mais completas e atualizadas com mais frequência. A página do Curl também inclui uma lista de ferramentas de código aberto para DoH (servidores, proxies, bibliotecas de cliente, etc).

kimbo
fonte
3

Sei que essa é uma questão antiga, mas minha solução pode ajudar outras pessoas.

Acho que os serviços JSON (P) que tornam isso fácil não duram para sempre, mas o JavaScript a seguir funciona bem para mim no momento em que escrevo.

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

O código acima escreve o IP do meu servidor na página em que está localizado, mas o script pode ser modificado para encontrar qualquer IP alterando 'zero.eu.org' para outro nome de domínio. Isso pode ser visto em ação na minha página: http://meon.zero.eu.org/

Neville Hillyer
fonte
Não consigo entender como encontrar meu próprio endereço IP usando este: <! - # echo var = "REMOTE_ADDR" -> de acordo com seu site.
George Carlin,
Este é um recurso padrão de 'eco' disponível na maioria dos servidores web. Consulte: google.co.uk/…
Neville Hillyer
1
Esta é possivelmente a única resposta que realmente aborda a questão original corretamente, muito bem. Infelizmente, ele não está de acordo com o visto da parte do computador do cliente , o que pode (ou não) ser um requisito importante.
Simon East
@Simon - Onde está escrito "visto do computador do cliente" e por que minha resposta não está de acordo com isso?
Neville Hillyer
1
@Simon - Bom ponto, mas como normalmente o JS do lado do cliente é fornecido pelo servidor, há uma boa chance de que o autor / proprietário do servidor esteja ciente dessa limitação de DNS - pode ser um problema para os autores que usam servidores de terceiros. Conforme indicado nas postagens aqui, a tecnologia existente se esforça para atender a todas as restrições desta. Minha contribuição foi destinada a transmitir a solução que considero mais prática em meu servidor.
Neville Hillyer
3

Existe um serviço de terceiros que fornece uma API REST compatível com CORS para realizar pesquisas de DNS a partir do navegador - https://exana.io/tools/dns/

user670908
fonte
1

Como muitas pessoas disseram, você precisa usar um serviço externo e ligar para ele. E isso só lhe dará a resolução DNS da perspectiva do servidor.

Se isso for bom o suficiente e você precisar apenas da resolução DNS, poderá usar o seguinte contêiner do Docker:

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

Endpoints:

[GET] /ipv6/[domain]: Execute uma resolução DNS para determinado domínio e retorne os endereços IPv6 associados.

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

[GET] /ipv4/[domain]: Execute uma resolução DNS para determinado domínio e retorne os endereços IPv4 associados.

 {
     "addresses": [
         "139.180.232.162"
     ]
 }

Minha recomendação é que você configure seu servidor web para reverter o proxy para o contêiner em um ponto de extremidade específico em seu servidor servindo seu Javascript e chamá-lo usando suas funções Ajax Javascript padrão.

Havok
fonte
0

Isso exigiria quebrar a sandbox do navegador. Tente deixar seu servidor fazer a pesquisa e solicitar isso do lado do cliente via XmlHttp.

Tomalak
fonte
0

Existe uma biblioteca javascript DNS-JS.com que faz exatamente isso.

DNS.Query("dns-js.com",
    DNS.QueryType.A,
    function(data) {
        console.log(data);
});
Fiach Reid
fonte
1
Ainda não da perspectiva do cliente. Essa biblioteca faz uma solicitação para dns-js.com/api.aspx para obter o endereço IP que então resolve o lado do servidor DNS.
wp-overwatch.com
-1

O Firefox tem uma API integrada para isso desde a v60, para WebExtensions:

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

Saturnus
fonte
Por alguma razão, browsernão existe no Firefox 64 beta, então eu me pergunto se ele foi removido.
Sawtaytoes de
3
@Sawtaytoes: Está exposto apenas para WebExtensions . Observe também que requer dnspermissão e o script não deve ser executado como um script de conteúdo (como novamente, browser.dnsnão seria exposto lá)
Saturnus
@Saturnus isso funciona bem para extensões do Firefox. Alguma chance de fazer o mesmo com as extensões do Chrome de alguma forma?
drk
-1

certeza de que você pode fazer isso sem usar qualquer adição, apenas javascript puro, usando este método de dns, browser.dns.resolve("example.com"); mas é compatível apenas com FIREFOX 60, você pode ver mais informações no MDN https://developer.mozilla.org/en-US/docs / Mozilla / Add-ons / WebExtensions / API / dns / resolve

Yassine Farroud
fonte
4
Este método está disponível apenas no contexto de um WebExtension. Não pode ser usado por uma página da web.
Crepúsculo-inativo-
-2

Não acho que isso seja permitido pela maioria dos navegadores por razões de segurança, em um contexto JavaScript puro, como a pergunta pede.

Nick Craver
fonte
5
Não é uma resposta. Isso deve ser um comentário!
trejder de
-3

Talvez eu tenha perdido o ponto, mas em resposta ao cara da MARINHA, aqui está como o navegador pode informar o endereço IP do 'solicitante' (embora talvez apenas o provedor de serviços).

Coloque uma tag de script na página a ser renderizada pelo cliente que chama (tem src apontando para) outro servidor que não está carregado balanceado (eu percebo que isso significa que você precisa de acesso a um segundo servidor, mas a hospedagem é barata hoje em dia e você pode configurar isso de forma fácil e barata).

Este é o tipo de código que precisa ser adicionado à página do cliente:

No outro servidor "someServerIown" você precisa ter a página ASP, ASPX ou PHP que;

----- contém o código do servidor como este:

"<% Response.Write (" var clientipaddress = '"& Request.ServerVariables (" REMOTE_ADDR ") &"'; ")%>" (sem as aspas dbl externas :-))

---- e grava este código de volta na tag de script:

   var clientipaddress = '178.32.21.45';

Isso cria efetivamente uma variável Javascript que você pode acessar com Javascript na página, nada menos.

Felizmente, você acessa essa var e grava o valor em um controle de formulário pronto para ser enviado de volta.

Quando o usuário postar ou receber a próxima solicitação, seu Javascript e / ou formulário enviará o valor da variável que "otherServerIown" preencheu para você, de volta ao servidor em que você gostaria.

É assim que consigo contornar o balanceador de carga burro que temos, que mascara o endereço IP do cliente e o faz parecer o do balanceador de carga ... burro ... burro burro burro!

Não dei a solução exata porque a situação de cada pessoa é um pouco diferente. O conceito é sólido, no entanto. Além disso, observe que se você estiver fazendo isso em uma página HTTPS, seu "otherServerIOwn" também deve ser entregue naquela forma segura, caso contrário, o Cliente será alertado sobre conteúdo misto. E se você tiver https, certifique-se de que TODOS os seus certificados são válidos, caso contrário, o cliente também receberá um aviso.

Espero que ajude alguém! Desculpe, demorou um ano para responder / contribuir. :-)

Contas
fonte
3
Desculpe, mas tive que votar negativamente, pois não acho que realmente responda à pergunta original. Eles querem apenas uma pesquisa de DNS padrão, não o IP público do usuário.
Simon East
-4

Minha versão é assim:

php no meu 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 na 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 em vários domínios. Ele poderia usar uma verificação de status. Trabalhando nisso.

Joeri
fonte
2
Desculpe, mas tive que votar negativamente, pois não acho que realmente responda à pergunta original. Eles querem apenas uma pesquisa de DNS padrão, não o IP público do usuário. Seu código também não limpa o $ _GET, o que é um grande problema de segurança.
Simon East
@Simon East, acho ainda pior. Parece que eles querem pesquisar qualquer IP pelo DNS.
Joeri
@SimonEast Você não pode provar que é um problema de segurança porque você não tem ideia de como eu compilei meu php. Seu rigor é simplesmente bobo.
Joeri
-10

Se o cliente tiver Java instalado, você pode fazer algo assim:

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

Fora isso, você provavelmente terá que usar um script do lado do servidor.

Alex Fort
fonte
8
Por que alguém está aprovando isso? java! = javascript, esta NÃO é uma resposta.
Sven Mawby
2
TOC Toc. Quem está aí? (... pausa longa) Applet Java
mike nelson