클라이언트 측 Javascript를 사용하여 DNS 조회 (호스트 이름에서 IP 주소로)를 수행 할 수 있습니까?


92

클라이언트 측 자바 스크립트를 사용하여 클라이언트 컴퓨터에서 볼 수있는 DNS 조회 (호스트 이름에서 IP 주소로)를 수행하고 싶습니다. 가능합니까?


5
이 질문에 대한 많은 답변은 해결 서버 측을 권장하는 것 같습니다. 사용 사례에 따라 충분하지 않을 수 있습니다. 예를 들어, 찾고있는 서비스가 GSLB를 사용하는 경우 사용자의 위치에 따라 다른 IP를 반환 할 수 있습니다. 결과적으로 서버 측 코드가 수신하는 응답은 브라우저가 수신했을 것과 다른 응답 일 가능성이 높습니다. 즉,이 차이에 관심이있는 사람들을위한 대체 솔루션이 아직 없습니다.
Ilan Rabinovitch 2012-07-12

답변:


35

자바 스크립트 표준 라이브러리에는 호스트 나 IP 주소에 대한 개념이 없습니다. 따라서 호스트 이름을 찾으려면 일부 외부 서비스에 액세스해야합니다.

호스트 이름의 IP 주소를 조회하고 javascript를 통해 액세스하는 cgi-bin을 호스팅하는 것이 좋습니다.


26
cgi-bin? 구식이에요. 나는 그것을 좋아한다!
Andrew Hedges

10
이것은 글을 쓰는 시점 (2008)에 해당했습니다. 이것은 6 년 후 사실이 아닙니다. 동일한 페이지에서 WebRTC에 대한 저의 의견을 참조하십시오. (불확실하게 Google은 여전히 ​​IP 주소 문제에 대한 해결책을 찾을 때이 스레드를 가리키며 사람들을 잘못된 방향으로 이끌 수 있습니다.)
earizon 2014 년

1
@earizon-귀하의 답변은 다른 질문에 대한 것입니다-자신의 개인 IP 주소를 찾는 방법.
Gene Vayngrib

클라우드에서 CGI를 통한 문제는 외부에서는 불가능한 인트라넷 호스트 IP를 발견하는 것입니다. 컴퓨터 나 인트라넷에서 로컬 서비스를 사용해야합니다.
Tzahi Fadida

HTTPS를 통해 DNS 쿼리를 보낼 수있는 새로 제안 된 인터넷 표준이 있습니다 (이 답변 stackoverflow.com/a/58299823/9638991 참조 ). 실제로는 기본적으로 cgi-bin 스크립트와 동일하게 작동합니다. :) (IETF에 의해 표준화되었으며 많은 대기업에서 지원하는 것을 제외하고)
kimbo

83

편집 :이 질문은 나에게 가려움을 주었으므로 클라이언트 IP 주소를 반환하는 Google App Engine에 JSONP 웹 서비스를 올렸습니다. 용법:

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

예, 서버 프록시가 필요하지 않습니다.


Pure JS는 할 수 없습니다. 인쇄하는 동일한 도메인에 서버 스크립트가있는 경우 XMLHttpRequest를 보내서 읽을 수 있습니다.


4
웹 서비스에 소스를 게시 할 수 있습니까? 인스턴스를 실행하면 좋을 것입니다.

18
죄송합니다. 원래 질문에 실제로 답하지 않는다고 생각하기 때문에 반대 투표를해야했습니다. 사용자의 공용 IP가 아닌 표준 DNS 조회를 원합니다.
Simon East

30

아주 늦었지만 여전히 많은 사람들이 "Google Airlines"를 통해 여기에 착륙 할 것 같습니다. Moderm 접근 방식은 서버 지원이 필요하지 않은 WebRTC를 사용하는 것입니다.

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

다음 코드는 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.";
}   

19
이것은 실제로 WebRTC 이전에는 존재하지 않았던 새로운 기능입니다-자신의 IP 주소를 발견 할 수 있습니다. 그러나 @noahjacobson은 javascript의 호스트 이름으로 IP의 DNS 조회라는 다른 질문을했습니다.
Gene Vayngrib

2
매우, 매우 흥미로운, 그것은 버그 또는 디자인 결함 어쨌든 어떤 점에서이 수정됩니다, 그래서 장기 프로젝트에 대한 좋은하지 않습니다
전자 info128

15

나는이 질문이 아주 오래전에 요청되었다는 것을 알고 있지만 더 최근의 답변을 제공 할 것이라고 생각했습니다.

HTTPS를 통한 DNS (DoH)

HTTPS를 통해 DNS 쿼리를 지원하는 DNS 해석기로 보낼 수 있습니다. DOH 표준은 RFC 8484에 설명되어 있습니다.

이것은 다른 모든 답변이 제안하는 것과 비슷하지만 DoH가 실제로 HTTPS를 통한 DNS 프로토콜이라는 것입니다. 또한 "제안 된"인터넷 표준이며 상당히 인기를 얻고 있습니다. 예를 들어 일부 주요 브라우저에서이를 지원하거나 지원할 계획 (Chrome, Edge, Firefox)이 있으며 Microsoft는이를 운영 체제에 구축하는 중입니다.

DoH의 목적 중 하나는 다음과 같습니다.

웹 애플리케이션이 CORS (Cross Origin Resource Sharing)와 일치하는 안전한 방식으로 기존 브라우저 API를 통해 DNS 정보에 액세스하도록 허용

dohjs 라는 웹 애플리케이션에서 DNS 조회를 수행하기 위해 특별히 만들어진 오픈 소스 도구가 있습니다. 그것은 않습니다 DNS를 통해 HTTPS 에 설명 된대로 (DOH) wireformat 쿼리를 RFC 8484 . GET 및 POST 메서드를 모두 지원합니다.

전체 공개 : 나는 dohjs의 기여자입니다.

HTTPS JSON API를 통한 DNS

DNS wireformat에 신경 쓰지 않으려면 Google과 Cloudflare 모두 HTTPS를 통한 DNS 용 JSON API를 제공합니다.

Google의 JSON DOH API로 example.com을 조회하는 자바 스크립트 코드의 예 :

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

wireformat을 사용하는 DOH GET 및 POST에 대한 RFC의 예

다음은 RFC가 GET 및 POST에 대해 제공하는 예입니다 ( https://tools.ietf.org/html/rfc8484#section-4.1.1 참조 ).

GET 예 :

첫 번째 예제 요청은 GET을 사용하여 "www.example.com"을 요청합니다.

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

POST 예 :

POST 메서드를 사용하는 "www.example.com"에 대한 동일한 DNS 쿼리는 다음과 같습니다.

: method = POST
: scheme = https
: authority = dnsserver.example.net
: path = / dns-query
accept = application / dns-message
콘텐츠 유형 = application / dns-message
콘텐츠 길이 = 33

<다음 16 진 인코딩으로 표현되는 33 바이트> 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

DOH 쿼리를 보낼 수있는 다른 장소

HTTPS를 통한 DNS를 지원하는 일부 공용 DNS 해석기 목록은 다음과 같은 위치에서 찾을 수 있습니다.

위의 리소스 중에서 Curl의 위키와 DNSCrypt 목록이 아마도 가장 완전하고 가장 자주 업데이트 될 것이라고 말하고 싶습니다. Curl의 페이지에는 DoH 용 오픈 소스 도구 목록 (서버, 프록시, 클라이언트 라이브러리 등)도 포함되어 있습니다.


14

호스팅 된 JSONP 버전은 매력적으로 작동하지만 대부분의 날 (동부 표준시) 밤 시간에 리소스를 넘기는 것 같아서 나만의 버전을 만들어야했습니다.

이것이 내가 PHP로 그것을 달성 한 방법입니다.

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

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

그러면 Javascript는 배열이 아니라 이전과 똑같습니다.

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

그렇게 간단합니다!

참고 : 공공 환경에서 사용하는 경우 $ _GET을 반드시 청소하십시오!


감사합니다 tcole! 그냥 내가 찾던 것 :)
jClark

잠깐만 요, 왜 $ _GET을 사용하나요? 이것이 취약점이라고 말한 것처럼. 그냥 사용할 수는 없습니다 : echo 'getip ('. $ data. ');';
deweydb 2013 년

7
죄송합니다. 원래 질문에 실제로 답하지 않는다고 생각하기 때문에 반대 투표를해야했습니다. 사용자의 공용 IP가 아닌 표준 DNS 조회를 원합니다.
Simon East

2
@SimonEast 허. 7 년 된 질문의 질문을 수정했습니다. 당신이 ;-) 자신을 만족시키기 위해 무엇을해야합니까
tcole

2
나는 최근에 같은 질문을 조사하고 있었기 때문에 원래 질문을 더 명확하게 편집했을 뿐이지 만, 어떤 이유로 여기에있는 대부분의 답변은 실제로 원래 포스터가 요청한 내용이 아니며 다른 질문으로 게시되어야합니다.
Simon East

3

나는 이것이 오래된 질문이라는 것을 알고 있지만 내 솔루션이 다른 사람들에게 도움이 될 수 있습니다.

나는 이것을 쉽게 만드는 JSON (P) 서비스가 영원히 지속되지는 않지만 다음 JavaScript는 글을 쓰는 시점에서 잘 작동한다는 것을 알았습니다.

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

위의 내용은 내 서버의 IP를 해당 페이지에 기록하지만 'zero.eu.org'를 다른 도메인 이름으로 변경하여 모든 IP를 찾도록 스크립트를 수정할 수 있습니다. 이것은 내 페이지 http://meon.zero.eu.org/ 에서 실제로 볼 수 있습니다 .


웹 사이트에 따라 <!-# echo var = "REMOTE_ADDR"->를 사용하여 내 IP 주소를 찾는 방법을 이해할 수 없습니다.
George Carlin

이것은 대부분의 웹 서버에서 사용할 수있는 표준 '에코'기능입니다. 참조 : google.co.uk/…
Neville Hillyer

1
이것은 아마도 원래의 질문을 실제로 올바르게 다루는 유일한 대답 일 것입니다. 안타깝게도 클라이언트의 컴퓨터 부분 에서 볼 수 있는 준수하지 않으며 이는 중요한 요구 사항 일 수도 있고 그렇지 않을 수도 있습니다.
Simon East

@Simon- "고객의 컴퓨터에서 볼 때"라고 표시되는 위치와 내 대답이 이에 부합하지 않는 이유는 무엇입니까?
Neville Hillyer 2015

1
@Simon-좋은 지적이지만 일반적으로 클라이언트 측 JS는 서버에서 제공되기 때문에 작성자 / 서버 소유자가이 DNS 제한 사항을 알고있을 가능성이 높습니다. 타사 서버를 사용하는 작성자에게는 문제가 될 수 있습니다. 여기 게시물에서 알 수 있듯이 기존 기술은 이것에 대한 모든 제약을 충족시키기 위해 고군분투하고 있습니다. 내 입력은 내 서버에서 가장 실용적인 솔루션을 전달하기위한 것입니다.
Neville Hillyer 2015


1

많은 사람들이 외부 서비스를 사용하고 전화해야한다고 말했습니다. 그리고 서버 관점에서만 DNS 확인을 얻을 수 있습니다.

충분하고 DNS 확인 만 필요한 경우 다음 Docker 컨테이너를 사용할 수 있습니다.

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

끝점 :

[GET] /ipv6/[domain]: 주어진 도메인에 대해 DNS 확인을 수행하고 연관된 IPv6 주소를 반환합니다.

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

[GET] /ipv4/[domain]: 주어진 도메인에 대해 DNS 확인을 수행하고 연관된 IPv4 주소를 반환합니다.

 {
     "addresses": [
         "139.180.232.162"
     ]
 }

내 권장 사항은 Javascript를 제공하는 서버의 특정 끝점에있는 컨테이너에 대한 역방향 프록시로 웹 서버를 설정하고 표준 Javascript Ajax 함수를 사용하여 호출하는 것입니다.


1

이를 수행하는 JavaScript 라이브러리 DNS-JS.com 이 있습니다.

DNS.Query("dns-js.com",
    DNS.QueryType.A,
    function(data) {
        console.log(data);
});

1
여전히 클라이언트의 관점에서는 아닙니다. 해당 라이브러리는 dns-js.com/api.aspx 에 요청 하여 IP 주소를 얻은 다음 DNS 서버 측을 확인합니다.
wp-overwatch.com

0

이렇게하려면 브라우저 샌드 박스를 중단해야합니다. 서버가 조회를 수행하도록하고 XmlHttp를 통해 클라이언트 측에서 요청하십시오.


-1

Firefox에는 WebExtensions에 대해 v60부터이를위한 내장 API가 있습니다.

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


어떤 이유로 든 browserFirefox 64 베타에는 존재하지 않으므로 제거되었는지 궁금합니다.
Sawtaytoes

3
@Sawtaytoes : WebExtensions 에만 노출 됩니다. 또한 dns권한 이 필요 하며 스크립트는 콘텐츠 스크립트로 실행되지 않아야합니다 (다시 말하지만 browser.dns여기에 노출되지 않음)
Saturnus

@Saturnus 이것은 Firefox 확장 프로그램에서 잘 작동합니다. 어떻게 든 Chrome 확장 프로그램으로 동일한 작업을 수행 할 수 있습니까?
drk

-1

이 dns 방법을 사용하여 추가하지 않고 순수한 자바 스크립트를 사용할 수 browser.dns.resolve("example.com"); 있지만 FIREFOX 60과 호환됩니다 .MDN https://developer.mozilla.org/en-US/docs 에서 자세한 정보를 볼 수 있습니다. / Mozilla / 추가 기능 / WebExtensions / API / dns / resolve


4
이 방법은 WebExtension의 컨텍스트에서만 사용할 수 있습니다. 웹 페이지에서는 사용할 수 없습니다.
duskwuff -inactive-

-2

질문에서 묻는 것처럼 순수한 JavaScript 컨텍스트에서 보안상의 이유로 대부분의 브라우저에서 이것이 허용되지 않는다고 생각합니다.


5
대답이 아닙니다. 이것은 주석이어야합니다!
trejder

-3

요점을 놓쳤을 수도 있지만 NAVY 녀석에 대한 답장으로 브라우저가 '요청자'의 IP 주소를 알려줄 수 있습니다 (아마도 서비스 제공 업체 일 수도 있음).

로드 균형이 잡히지 않은 다른 서버를 호출하는 (src가 가리키는) 클라이언트가 렌더링 할 페이지에 스크립트 태그를 배치합니다 (이는 두 번째 서버에 대한 액세스가 필요하지만 호스팅 비용이 저렴하다는 것을 알고 있습니다. 쉽고 저렴하게 설정).

다음은 클라이언트 페이지에 추가해야하는 코드 유형입니다.

다른 서버 "someServerIown"에는 ASP, ASPX 또는 PHP 페이지가 있어야합니다.

-----에는 다음과 같은 서버 코드가 포함됩니다.

"<% Response.Write ("var clientipaddress = ' "& Request.ServerVariables ("REMOTE_ADDR ") &"'; ") %>"(외부 dbl 따옴표 제외 :-))

---- 그리고이 코드를 스크립트 태그에 다시 씁니다.

   var clientipaddress = '178.32.21.45';

이렇게하면 페이지에서 자바 스크립트로 액세스 할 수있는 자바 스크립트 변수가 효과적으로 생성됩니다.

바라건대,이 변수에 액세스하고 값을 다시 보낼 준비가 된 양식 컨트롤에 기록하십시오.

사용자가 다음 요청을 게시하거나 받으면 Javascript 및 / 또는 양식이 "otherServerIown"이 입력 한 변수 값을 원하는 서버로 다시 보냅니다.

이것이 내가 클라이언트 IP 주소를 마스킹하고로드 밸런서처럼 보이게하는 멍청한로드 밸런서를 우회하는 방법입니다. .... dumb ... dumb dumb dumb!

모든 사람의 상황이 조금 다르기 때문에 정확한 해결책을 제시하지 못했습니다. 그러나 개념은 건전합니다. 또한 HTTPS 페이지에서이 작업을 수행하는 경우 "otherServerIOwn"도 해당 보안 형식으로 전달해야합니다. 그렇지 않으면 클라이언트에게 혼합 콘텐츠에 대한 경고가 표시됩니다. https가 있으면 모든 인증서가 유효한지 확인하십시오. 그렇지 않으면 클라이언트도 경고를받습니다.

누군가에게 도움이되기를 바랍니다! 죄송합니다. 답변 / 기여하는 데 1 년이 걸렸습니다. :-)


3
죄송합니다. 원래 질문에 실제로 답하지 않는다고 생각하기 때문에 반대 투표를해야했습니다. 사용자의 공용 IP가 아닌 표준 DNS 조회를 원합니다.
Simon East

-4

내 버전은 다음과 같습니다.

내 서버의 PHP :

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

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

}).done( function( json ) {

    self.ip = json;

});

도메인 간 작동합니다. 상태 확인을 사용할 수 있습니다. 작업 중입니다.


2
죄송합니다. 원래 질문에 실제로 답하지 않는다고 생각하기 때문에 반대 투표를해야했습니다. 사용자의 공용 IP가 아닌 표준 DNS 조회를 원합니다. 귀하의 코드는 또한 큰 보안 문제인 $ _GET을 삭제하지 않습니다.
Simon East

@Simon East 나는 그것이 더 나쁘다고 생각합니다. DNS로 IP를 조회하려는 것 같습니다.
Joeri

@SimonEast 내 PHP를 어떻게 컴파일했는지 모르기 때문에 보안 문제임을 증명할 수 없습니다. 당신의 엄격함은 단지 어리석은 것입니다.
Joeri

-10

클라이언트에 Java가 설치되어 있으면 다음과 같이 할 수 있습니다.

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

그 외에는 서버 측 스크립트를 사용해야 할 것입니다.


8
누군가 찬성하는 이유는 무엇입니까? java! = javascript, 이것은 대답이 아닙니다.
Sven Mawby 2015-06-06

2
똑 똑. 거기 누구야? (... 긴 일시 정지) 자바 애플릿
마이크 넬슨
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.