Czy mogę przeprowadzić wyszukiwanie DNS (nazwa hosta na adres IP) przy użyciu JavaScript po stronie klienta?

92

Chciałbym użyć JavaScript po stronie klienta do wyszukania DNS (nazwa hosta do adresu IP) widzianego z komputera klienta. Czy to jest możliwe?

Noah Jacobson
źródło
5
Wiele odpowiedzi na to pytanie wydaje się zalecać wykonanie po stronie serwera rozdzielczości. W zależności od przypadku użycia może to być niewystarczające. Na przykład, jeśli wyszukiwana usługa korzysta z GSLB, może zwrócić inny adres IP na podstawie lokalizacji użytkownika; w rezultacie odpowiedź, którą otrzyma kod po stronie serwera, będzie prawdopodobnie inną odpowiedzią niż ta, którą otrzymałaby przeglądarka. Mimo to nie mam jeszcze alternatywnego rozwiązania dla tych, którym zależy na tej różnicy.
Ilan Rabinovitch

Odpowiedzi:

35

W standardowej bibliotece javascript nie ma pojęcia o hostach ani adresach IP. Będziesz więc musiał uzyskać dostęp do zewnętrznej usługi, aby wyszukać nazwy hostów.

Polecam hosting cgi-bin, który wyszukuje adres IP nazwy hosta i uzyskuje do niego dostęp za pomocą javascript.

Hans Sjunnesson
źródło
26
cgi-bin? To stara szkoła. Lubię to!
Andrew Hedges,
10
Było to prawdą w momencie pisania (2008). To nieprawda 6 lat później: zobacz mój komentarz na temat WebRTC na tej samej stronie. (Niestety Google nadal wskazuje na ten wątek, szukając rozwiązania problemu z adresem IP, co może skierować ludzi w złym kierunku).
earizon
1
@earizon - Twoja odpowiedź dotyczy innego pytania - jak odkryć swój prywatny adres IP.
Gene Vayngrib
Problem poprzez CGI z chmury polegałby na wykrywaniu adresów IP hostów intranetowych, co nie jest możliwe z zewnątrz. Musiałbyś skorzystać z usługi lokalnej na komputerze lub w intranecie.
Tzahi Fadida
Jest nowy proponowany standard internetowy, który umożliwia wysyłanie zapytań DNS przez HTTPS (zobacz odpowiedź stackoverflow.com/a/58299823/9638991 ). W rzeczywistości działa w zasadzie tak samo jak skrypt cgi-bin :) (z wyjątkiem tego, że został ustandaryzowany przez IETF i obsługuje go mnóstwo dużych firm)
kimbo
83

Edycja : to pytanie przyprawiło mnie o swędzenie, więc uruchomiłem usługę internetową JSONP w Google App Engine, która zwraca adresy IP klientów. Stosowanie:

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

Tak, nie są potrzebne żadne serwery proxy.


Czysty JS nie może. Jeśli masz skrypt serwera w tej samej domenie, który go drukuje, możesz wysłać XMLHttpRequest, aby go przeczytać.

Zach
źródło
4
Czy możesz opublikować źródło w swojej usłudze internetowej? Byłoby miło uruchomić instancję.
Will
18
Przepraszam, ale musiałem zagłosować przeciw, ponieważ nie sądzę, aby to faktycznie odpowiadało na pierwotne pytanie. Chcą tylko standardowego wyszukiwania DNS, a nie publicznego adresu IP użytkownika.
Simon East
30

Bardzo późno, ale myślę, że wiele osób nadal będzie tu lądować przez „Google Airlines”. Moderm podejście polega na użyciu WebRTC, który nie wymaga obsługi serwera.

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

Następny kod to skopiuj i wklej z 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
źródło
19
jest to rzeczywiście nowa możliwość, która nie istniała przed WebRTC - aby odkryć własny adres IP. Ale @noahjacobson zadał inne pytanie - wyszukiwanie adresu IP w DNS według nazwy hosta z javascript.
Gene Vayngrib
2
Bardzo, bardzo interesujące, to błąd lub wada projektowa, w każdym razie w pewnym momencie zostanie poprawiona, więc nie nadaje się do długoterminowych projektów
e-info128
15

Wiem, że to pytanie zostało zadane bardzo dawno temu, ale pomyślałem, że dam bardziej aktualną odpowiedź.

DNS przez HTTPS (DoH)

Możesz wysyłać zapytania DNS przez HTTPS do resolverów DNS, które to obsługują. Standard dla DOH jest opisany w RFC 8484 .

To jest podobne do tego, co sugerują wszystkie inne odpowiedzi, tylko że DoH jest w rzeczywistości protokołem DNS przez HTTPS. Jest to również „proponowany” standard internetowy i staje się dość popularny. Na przykład niektóre główne przeglądarki obsługują go lub planują go obsługiwać (Chrome, Edge, Firefox), a firma Microsoft jest w trakcie wbudowywania go w swój system operacyjny.

Jednym z celów DoH jest:

umożliwienie aplikacjom internetowym dostępu do informacji DNS za pośrednictwem istniejących interfejsów API przeglądarek w bezpieczny sposób zgodny z Cross Origin Resource Sharing (CORS)

Istnieje narzędzie typu open source stworzone specjalnie do wyszukiwania DNS z aplikacji internetowych o nazwie dohjs . Czyni DNS za pośrednictwem protokołu HTTPS (DOH) wireformat zapytań w sposób opisany w dokumencie RFC 8484 . Obsługuje metody GET i POST.

Pełne ujawnienie: jestem współtwórcą dohjs.

DNS przez HTTPS JSON API

Jeśli nie chcesz zawracać sobie głowy formatem drutu DNS, zarówno Google, jak i Cloudflare oferują interfejsy API JSON dla DNS przez HTTPS.

Przykładowy kod JavaScript do wyszukania example.com za pomocą Google JSON DOH API:

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

Przykłady z dokumentu RFC dla DOH GET i POST z wireformatem

Oto przykłady podane przez RFC dla GET i POST (patrz https://tools.ietf.org/html/rfc8484#section-4.1.1 ):

POBIERZ przykład:

Pierwsze przykładowe żądanie używa GET do żądania „www.example.com”.

: metoda = GET
: schemat = https
: urząd = dnsserver.example.net
: ścieżka = / dns-query? dns = AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB
accept = application / dns-message

Przykład POST:

To samo zapytanie DNS dla „www.example.com” przy użyciu metody POST wyglądałoby tak:

: metoda = POST
: schemat = https
: urząd = dnsserver.example.net
: ścieżka = / dns-query
accept = application / dns-message
content-type = application / dns-message
content-length = 33

<33 bajty reprezentowane przez następujące kodowanie szesnastkowe> 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

Inne miejsca do wysyłania zapytań DOH

Listę niektórych publicznych programów rozpoznawania nazw DNS, które obsługują DNS przez HTTPS, można znaleźć w kilku miejscach:

Spośród powyższych zasobów, powiedziałbym, że lista na wiki Curla i lista DNSCrypt są prawdopodobnie najbardziej kompletne i najczęściej aktualizowane. Strona Curl zawiera również listę narzędzi open source dla DoH (serwery, proxy, biblioteki klienta itp.).

kimbo
źródło
14

Hostowana wersja JSONP działa jak marzenie, ale wygląda na to, że przez większość dni przegląda swoje zasoby w nocy (czas wschodni), więc musiałem stworzyć własną wersję.

Tak to zrobiłem z PHP:

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

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

Następnie JavaScript jest dokładnie taki sam jak poprzednio, ale nie jest tablicą:

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

Proste!

Uwaga dodatkowa: pamiętaj, aby wyczyścić swój $ _GET, jeśli używasz go w jakimkolwiek publicznym środowisku!

tcole
źródło
Dzięki tcole! Właśnie tego szukałem :)
jClark
Poczekaj chwilę, po co w ogóle używać $ _GET? tak jak powiedziałeś, to jest luka. Nie można po prostu użyć: echo 'getip ('. $ Data. ');';
deweydb
7
Przepraszam, ale musiałem zagłosować przeciw, ponieważ nie sądzę, aby to faktycznie odpowiadało na pierwotne pytanie. Chcą tylko standardowego wyszukiwania DNS, a nie publicznego adresu IP użytkownika.
Simon East
2
@SimonEast Heh. Zmodyfikowałeś pytanie 7-letniego pytania. Zrób wszystko, co musisz, aby się zadowolić ;-)
tcole
2
Po prostu zredagowałem oryginalne pytanie, aby było jaśniejsze, ponieważ ostatnio badałem to samo pytanie, ale z jakiegoś powodu większość odpowiedzi tutaj nie jest w rzeczywistości tym, o co prosił oryginalny plakat i powinno się je zamieścić pod innym pytaniem.
Simon East,
3

Wiem, że to stare pytanie, ale moje rozwiązanie może pomóc innym.

Uważam, że usługi JSON (P), które to ułatwiają, nie trwają wiecznie, ale następujący JavaScript działa dobrze dla mnie w momencie pisania.

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

Powyższe zapisuje adres IP mojego serwera na stronie, na której się znajduje, ale skrypt można zmodyfikować, aby znaleźć dowolny adres IP, zmieniając „zero.eu.org” na inną nazwę domeny. Można to zobaczyć w akcji na mojej stronie pod adresem : http://meon.zero.eu.org/

Neville Hillyer
źródło
Nie mogę pojąć, jak znaleźć własny adres IP, używając tego: <! - # echo var = "REMOTE_ADDR" -> zgodnie z Twoją witryną.
George Carlin
Jest to standardowa funkcja „echa” dostępna na większości serwerów WWW. Zobacz: google.co.uk/…
Neville Hillyer
1
Jest to prawdopodobnie jedyna odpowiedź, która właściwie rozwiązuje pierwotne pytanie, dobra robota. Niestety nie spełnia on tego, co widać z części komputera klienta , co może (ale nie musi) być ważnym wymaganiem.
Simon East
@Simon - gdzie jest napisane „widziane z komputera klienta” i dlaczego moja odpowiedź jest niezgodna z tym?
Neville Hillyer
1
@Simon - słuszna uwaga, ale ponieważ zwykle JS po stronie klienta jest dostarczany przez serwer, istnieje duża szansa, że ​​autor / właściciel serwera byłby świadomy tego ograniczenia DNS - może to stanowić problem dla autorów korzystających z serwerów stron trzecich. Jak wskazano w postach tutaj, istniejąca technologia stara się sprostać wszystkim ograniczeniom związanym z tym. Mój wkład miał na celu przedstawienie rozwiązania, które uznałem za najbardziej praktyczne na moim serwerze.
Neville Hillyer
3

Istnieje usługa innej firmy, która zapewnia przyjazny dla CORS interfejs API REST do wykonywania wyszukiwań DNS z przeglądarki - https://exana.io/tools/dns/

user670908
źródło
1

Jak wiele osób powiedziało, że musisz skorzystać z usługi zewnętrznej i zadzwonić do niej. A to zapewni ci rozpoznawanie nazw DNS tylko z perspektywy serwera.

Jeśli to wystarczy i potrzebujesz tylko rozpoznawania nazw DNS, możesz użyć następującego kontenera Docker:

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

Punkty końcowe:

[GET] /ipv6/[domain]: Wykonaj rozpoznawanie nazw DNS dla danej domeny i zwróć powiązane adresy IPv6.

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

[GET] /ipv4/[domain]: Wykonaj rozpoznawanie nazw DNS dla danej domeny i zwróć powiązane adresy IPv4.

 {
     "addresses": [
         "139.180.232.162"
     ]
 }

Moim zaleceniem jest skonfigurowanie serwera WWW tak, aby odwracał proxy do kontenera na określonym punkcie końcowym serwera obsługującego JavaScript i wywoływał go przy użyciu standardowych funkcji JavaScript Ajax.

Havok
źródło
1

Istnieje biblioteka javascript DNS-JS.com , która właśnie to robi.

DNS.Query("dns-js.com",
    DNS.QueryType.A,
    function(data) {
        console.log(data);
});
Fiach Reid
źródło
1
Wciąż nie z perspektywy klienta. Ta biblioteka wysyła żądanie do dns-js.com/api.aspx w celu uzyskania adresu IP, który następnie rozpoznaje serwer DNS.
wp-overwatch.com
0

Wymagałoby to zerwania piaskownicy przeglądarki. Spróbuj pozwolić swojemu serwerowi na wyszukanie i zażądanie tego po stronie klienta za pośrednictwem XmlHttp.

Tomalak
źródło
-1

Firefox ma wbudowany interfejs API od wersji 60 dla WebExtensions:

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

Saturnus
źródło
Z jakiegoś powodu browsernie istnieje w Firefox 64 beta, więc zastanawiam się, czy został usunięty.
Kevin Ghadyani
3
@Sawtaytoes: Jest ujawniany tylko dla WebExtensions . Zauważ również, że wymaga dnspozwolenia, a skrypt nie będzie działał jako skrypt zawartości (jak ponownie, browser.dnsnie zostanie tam ujawniony)
Saturnus
@Saturnus Działa to dobrze w przypadku rozszerzeń przeglądarki Firefox. Czy jest jakaś szansa, aby zrobić to samo z rozszerzeniami Chrome?
drk
-1

na pewno możesz to zrobić bez żadnego dodatku, po prostu czystego javascript, używając tej metody dns, browser.dns.resolve("example.com"); ale jest ona kompatybilna tylko z FIREFOX 60 więcej informacji na MDN https://developer.mozilla.org/en-US/docs / Mozilla / Add-ons / WebExtensions / API / dns / solution

Yassine Farroud
źródło
4
Ta metoda jest dostępna tylko w kontekście WebExtension. Nie może być używany przez stronę internetową.
duskwuff
-2

Nie sądzę, aby było to dozwolone przez większość przeglądarek ze względów bezpieczeństwa, w czystym kontekście JavaScript, jak zadaje pytanie.

Nick Craver
źródło
5
To nie jest odpowiedź. To powinien być komentarz!
trejder
-3

Może przegapiłem punkt, ale w odpowiedzi dla faceta z NAVY, oto jak przeglądarka może powiedzieć ci adres IP „żądającego” (choć może tylko ich usługodawca).

Umieść tag skryptu na stronie, która ma być renderowana przez klienta, który wywołuje (ma src wskazujący na) inny serwer, który nie jest załadowany w sposób zrównoważony (zdaję sobie sprawę, że oznacza to, że potrzebujesz dostępu do drugiego serwera, ale hosting jest obecnie tani i możesz skonfigurować to łatwo i tanio).

Oto rodzaj kodu, który należy dodać do strony klienta:

Na drugim serwerze „someServerIown” musisz mieć stronę ASP, ASPX lub PHP;

----- zawiera taki kod serwera:

"<% Response.Write (" var clientipaddress = '"& Request.ServerVariables (" REMOTE_ADDR ") &"'; ")%>" (bez zewnętrznych cudzysłowów :-))

---- i zapisuje ten kod z powrotem do tagu script:

   var clientipaddress = '178.32.21.45';

To skutecznie tworzy zmienną Javascript, do której można uzyskać dostęp za pomocą Javascript na stronie.

Miejmy nadzieję, że uzyskasz dostęp do tej zmiennej i zapiszesz wartość w kontrolce formularza gotowej do odesłania.

Kiedy użytkownik wysyła lub odbiera następne żądanie, Twój JavaScript i / lub formularz wysyła wartość zmiennej, którą wypełnił dla Ciebie „otherServerIown”, z powrotem na serwer, na którym chcesz to zrobić.

W ten sposób omijam głupi system równoważenia obciążenia, który maskuje adres IP klienta i sprawia, że ​​wygląda on jak adres modułu równoważenia obciążenia… głupi… głupi głupi!

Nie podałem dokładnego rozwiązania, ponieważ sytuacja u każdego jest trochę inna. Jednak koncepcja jest rozsądna. Pamiętaj również, że jeśli robisz to na stronie HTTPS, Twój „otherServerIOwn” musi również dostarczać w tej bezpiecznej formie, w przeciwnym razie Klient zostanie ostrzeżony o mieszanej zawartości. A jeśli masz https, upewnij się, że WSZYSTKIE twoje certyfikaty są ważne, w przeciwnym razie klient również otrzyma ostrzeżenie.

Mam nadzieję, że to komuś pomoże! Przepraszamy, udzielenie odpowiedzi / przesłanie odpowiedzi zajęło rok. :-)

Rachunki
źródło
3
Przepraszam, ale musiałem zagłosować przeciw, ponieważ nie sądzę, aby to faktycznie odpowiadało na pierwotne pytanie. Chcą tylko standardowego wyszukiwania DNS, a nie publicznego adresu IP użytkownika.
Simon East
-4

Moja wersja wygląda tak:

php na moim serwerze:

<?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 stronie:

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

}).done( function( json ) {

    self.ip = json;

});

Działa w wielu domenach. Przydałoby się sprawdzenie statusu. Pracuję nad tym.

Joeri
źródło
2
Przepraszam, ale musiałem zagłosować przeciw, ponieważ nie sądzę, aby to faktycznie odpowiadało na pierwotne pytanie. Chcą tylko standardowego wyszukiwania DNS, a nie publicznego adresu IP użytkownika. Twój kod nie czyści również $ _GET, co jest dużym problemem bezpieczeństwa.
Simon East
@Simon East Myślę, że jest jeszcze gorzej. Wygląda na to, że chcą wyszukać dowolny adres IP przez DNS.
Joeri
@SimonEast Nie możesz udowodnić, że jest to problem z bezpieczeństwem, ponieważ nie masz pojęcia, jak skompilowałem mój php. Twoja surowość jest po prostu głupia.
Joeri
-10

Jeśli klient ma zainstalowaną Javę, możesz zrobić coś takiego:

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

Poza tym prawdopodobnie będziesz musiał użyć skryptu po stronie serwera.

Alex Fort
źródło
8
Dlaczego ktoś to popiera? java! = javascript, to NIE jest odpowiedź.
Sven Mawby
2
Puk puk. Kto tam? (... długa pauza) Aplet Java
mike nelson