Tôi có thể thực hiện tra cứu DNS (tên máy chủ đến địa chỉ IP) bằng Javascript phía máy khách không?


92

Tôi muốn sử dụng Javascript phía máy khách để thực hiện tra cứu DNS (tên máy chủ thành địa chỉ IP) như được thấy từ máy tính của khách hàng. Điều đó có thể không?


5
Nhiều câu trả lời cho câu hỏi này dường như khuyên bạn nên làm ở phía máy chủ giải quyết. Tùy trường hợp sử dụng mà có thể không đủ. Ví dụ: nếu dịch vụ bạn đang tìm kiếm đang sử dụng GSLB, nó có thể trả về một IP khác dựa trên vị trí của người dùng; kết quả là phản hồi mà mã phía máy chủ nhận được rất có thể là phản hồi khác với những gì trình duyệt sẽ nhận được. Tuy nhiên, tôi vẫn chưa có giải pháp thay thế cho những người quan tâm đến sự khác biệt này.
Ilan Rabinovitch

Câu trả lời:


34

Không có khái niệm về máy chủ hoặc địa chỉ ip trong thư viện chuẩn javascript. Vì vậy, bạn sẽ phải truy cập một số dịch vụ bên ngoài để tra cứu tên máy chủ cho bạn.

Tôi khuyên bạn nên lưu trữ cgi-bin để tra cứu địa chỉ ip của tên máy chủ và truy cập thông qua javascript.


26
cgi-bin? Đó là trường cũ. Tôi thích nó!
Andrew Hedges

10
Điều này đúng vào thời điểm viết bài (2008). Điều này không đúng 6 năm sau: Hãy xem nhận xét của tôi về WebRTC trong cùng trang này. (Thật không may, Google vẫn trỏ đến chủ đề này khi tìm kiếm giải pháp cho vấn đề địa chỉ IP và điều đó có thể khiến mọi người đi sai hướng).
earizon

1
@earizon - câu trả lời của bạn dành cho một câu hỏi khác - cách khám phá địa chỉ IP riêng của bạn.
Gene Vayngrib,

Vấn đề thông qua CGI từ đám mây sẽ là phát hiện ra các ips máy chủ mạng nội bộ không thể thực hiện từ bên ngoài. Bạn sẽ phải sử dụng một dịch vụ cục bộ trên máy hoặc mạng nội bộ.
Tzahi Fadida

Có một tiêu chuẩn Internet mới được đề xuất cho phép bạn gửi các truy vấn DNS qua HTTPS (xem câu trả lời này stackoverflow.com/a/58299823/9638991 ). Trong thực tế, về cơ bản nó hoạt động giống như một tập lệnh cgi-bin :) (ngoại trừ nó đã được chuẩn hóa bởi IETF và rất nhiều công ty lớn hỗ trợ nó)
kimbo

83

Chỉnh sửa : Câu hỏi này khiến tôi ngứa ngáy, vì vậy tôi đã thiết lập một dịch vụ web JSONP trên Google App Engine để trả về địa chỉ ip của khách hàng. Sử dụng:

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

Yay, không cần proxy máy chủ.


JS thuần túy không thể. Nếu bạn có một tập lệnh máy chủ trong cùng một miền in nó ra, bạn có thể gửi một XMLHttpRequest để đọc nó.


4
Bạn có thể đăng nguồn lên dịch vụ web của mình không? Sẽ rất tốt nếu bạn chạy một phiên bản.
Sẽ

18
Xin lỗi, nhưng đã phải từ chối vì tôi không nghĩ nó thực sự trả lời câu hỏi ban đầu. Họ chỉ muốn tra cứu DNS tiêu chuẩn, không phải IP công khai của người dùng.
Simon East

29

Rất muộn, nhưng tôi đoán nhiều người vẫn sẽ hạ cánh xuống đây thông qua "Google Airlines". Một cách tiếp cận hiện đại là sử dụng WebRTC không yêu cầu máy chủ hỗ trợ.

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

Mã tiếp theo là một bản sao và dán từ 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
đây thực sự là một khả năng mới không tồn tại trước WebRTC - để khám phá địa chỉ IP của chính bạn. Nhưng @noahjacobson đã hỏi một câu hỏi khác - tra cứu DNS của IP theo tên máy chủ từ javascript.
Gene Vayngrib,

2
Rất, rất thú vị, đó là một lỗi hoặc thiết kế lỗ hổng, dù sao tại một số điểm nó sẽ được sửa chữa vì vậy không tốt cho các dự án dài hạn
e-info128

14

Phiên bản JSONP được lưu trữ hoạt động giống như một sự quyến rũ, nhưng có vẻ như nó sử dụng tài nguyên của nó vào ban đêm hầu hết các ngày (Giờ miền Đông), vì vậy tôi đã phải tạo phiên bản của riêng mình.

Đây là cách tôi đã hoàn thành nó với PHP:

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

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

Sau đó, Javascript giống hệt như trước đây, chỉ không phải là một mảng:

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

Đơn giản như vậy!

Lưu ý phụ: Hãy chắc chắn xóa $ _GET của bạn nếu bạn đang sử dụng nó trong bất kỳ môi trường công khai nào!


Cảm ơn tcole! Đúng những gì tôi đang tìm kiếm :)
jClark

Chờ một chút, tại sao thậm chí sử dụng $ _GET? như bạn nói đây là một lỗ hổng. Không thể chỉ sử dụng: echo 'getip ('. $ Data. ');';
deweydb

7
Xin lỗi, nhưng đã phải từ chối vì tôi không nghĩ nó thực sự trả lời câu hỏi ban đầu. Họ chỉ muốn tra cứu DNS tiêu chuẩn, không phải IP công khai của người dùng.
Simon East

2
@SimonEast Heh. Bạn đã sửa đổi câu hỏi của một câu hỏi 7 năm tuổi. Hãy làm những gì bạn cần để thỏa mãn chính mình ;-)
tcole

2
Tôi chỉ chỉnh sửa câu hỏi ban đầu để làm cho nó rõ ràng hơn, vì gần đây tôi đang nghiên cứu câu hỏi tương tự, nhưng vì một số lý do mà hầu hết các câu trả lời ở đây không thực sự là những gì người đăng ban đầu yêu cầu và nên được đăng dưới một câu hỏi khác.
Simon East

13

Tôi biết câu hỏi này đã được hỏi cách đây rất lâu, nhưng tôi nghĩ mình sẽ đưa ra một câu trả lời mới hơn.

DNS qua HTTPS (DoH)

Bạn có thể gửi các truy vấn DNS qua HTTPS tới các trình phân giải DNS hỗ trợ nó. Tiêu chuẩn cho DOH được mô tả trong RFC 8484 .

Đây là một điều tương tự với những gì mà tất cả các câu trả lời khác gợi ý, chỉ khác rằng DoH thực sự là giao thức DNS qua HTTPS. Nó cũng là một tiêu chuẩn Internet "được đề xuất" và nó đang trở nên khá phổ biến. Ví dụ: một số trình duyệt chính hỗ trợ hoặc có kế hoạch hỗ trợ (Chrome, Edge, Firefox) và Microsoft đang trong quá trình xây dựng nó vào hệ điều hành của họ.

Một trong những mục đích của DoH là:

cho phép các ứng dụng web truy cập thông tin DNS thông qua các API trình duyệt hiện có theo cách an toàn nhất quán với Chia sẻ tài nguyên nguồn gốc chéo (CORS)

Có một công cụ mã nguồn mở được tạo đặc biệt để thực hiện tra cứu DNS từ các ứng dụng web được gọi là dohjs . Nó thực hiện các truy vấn định dạng dây DNS qua HTTPS (DoH) như được mô tả trong RFC 8484 . Nó hỗ trợ cả hai phương thức GET và POST.

Tiết lộ đầy đủ: Tôi là người đóng góp cho dohjs.

DNS qua các API HTTPS JSON

Nếu bạn không muốn bận tâm đến định dạng dây DNS, cả Google và Cloudflare đều cung cấp API JSON cho DNS qua HTTPS.

Mã Javascript mẫu để tra cứu example.com bằng API JSON DOH của Google:

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

Ví dụ từ RFC cho DOH GET và POST với wireformat

Dưới đây là các ví dụ mà RFC cung cấp cho cả GET và POST (xem https://tools.ietf.org/html/rfc8484#section-4.1.1 ):

Lấy ví dụ:

Yêu cầu mẫu đầu tiên sử dụng GET để yêu cầu "www.example.com".

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

POST ví dụ:

Cùng một truy vấn DNS cho "www.example.com", sử dụng phương thức POST sẽ là:

: method = POST
: Scheme = https
: Authority = dnsserver.example.net
: path = / dns-query
accept = application / dns-message
content-type = application / dns-message
content-length = 33

<33 byte được biểu thị bằng mã hóa hex sau> 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

Những nơi khác để gửi truy vấn DOH

Bạn có thể tìm thấy danh sách một số trình phân giải DNS công cộng hỗ trợ DNS qua HTTPS ở một số nơi:

Trong số các nguồn trên, tôi muốn nói rằng danh sách trên wiki của Curl và danh sách DNSCrypt có lẽ là đầy đủ nhất và được cập nhật thường xuyên nhất. Trang của Curl cũng bao gồm danh sách các công cụ mã nguồn mở cho DoH (máy chủ, proxy, client libs, v.v.).


3

Tôi biết đây là một câu hỏi cũ nhưng giải pháp của tôi có thể hỗ trợ những người khác.

Tôi thấy rằng các dịch vụ JSON (P) giúp việc này trở nên dễ dàng không tồn tại mãi mãi nhưng JavaScript sau hoạt động tốt đối với tôi tại thời điểm viết bài.

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

Ở trên ghi IP của máy chủ của tôi trên trang được đặt nhưng tập lệnh có thể được sửa đổi để tìm bất kỳ IP nào bằng cách thay đổi 'zero.eu.org' thành một tên miền khác. Bạn có thể thấy điều này đang hoạt động trên trang của tôi tại: http://meon.zero.eu.org/


Tôi không thể hiểu cách tìm địa chỉ ip của chính mình bằng cách sử dụng: <! - # echo var = "REMOTE_ADDR" -> theo trang web của bạn.
George Carlin

Đây là cơ sở 'tiếng vọng' tiêu chuẩn có sẵn trên hầu hết các máy chủ web. Xem: google.co.uk/…
Neville Hillyer

1
Đây có thể là câu trả lời duy nhất thực sự giải quyết chính xác câu hỏi ban đầu, được thực hiện tốt. Thật không may, nó không tuân theo những gì được nhìn thấy từ phần máy tính của khách hàng , điều này có thể (hoặc không) là một yêu cầu quan trọng.
Simon East

@Simon - Ở đâu nó nói "như được nhìn thấy từ máy tính của khách hàng" và tại sao câu trả lời của tôi không tuân thủ điều này?
Neville Hillyer

1
@Simon - Điểm tốt nhưng vì thông thường JS phía máy khách là máy chủ được cung cấp nên rất có thể tác giả / chủ sở hữu máy chủ sẽ biết về giới hạn DNS này - có thể là vấn đề đối với tác giả sử dụng máy chủ của bên thứ ba. Như đã chỉ ra trong các bài viết ở đây, công nghệ hiện tại đang đấu tranh để đáp ứng tất cả các hạn chế đối với điều này. Đầu vào của tôi nhằm mục đích truyền đạt giải pháp mà tôi thấy thiết thực nhất trên máy chủ của mình.
Neville Hillyer


1

Như nhiều người đã nói bạn cần sử dụng dịch vụ bên ngoài và gọi nó. Và điều đó sẽ chỉ giúp bạn có được độ phân giải DNS từ góc độ máy chủ.

Nếu điều đó đủ tốt và nếu bạn chỉ cần phân giải DNS, bạn có thể sử dụng vùng chứa Docker sau:

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

Điểm cuối:

[GET] /ipv6/[domain]: Thực hiện phân giải DNS cho miền nhất định và trả về các địa chỉ IPv6 được liên kết.

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

[GET] /ipv4/[domain]: Thực hiện phân giải DNS cho miền nhất định và trả về các địa chỉ IPv4 được liên kết.

 {
     "addresses": [
         "139.180.232.162"
     ]
 }

Khuyến nghị của tôi là bạn nên thiết lập máy chủ web của mình để đảo ngược proxy tới vùng chứa trên một điểm cuối cụ thể trong máy chủ phục vụ Javascript của bạn và gọi nó bằng các hàm Ajax Javascript tiêu chuẩn của bạn.


0

Làm điều này sẽ yêu cầu phá vỡ hộp cát của trình duyệt. Cố gắng để máy chủ của bạn thực hiện tra cứu và yêu cầu điều đó từ phía máy khách thông qua XmlHttp.


0

Có một thư viện javascript DNS-JS.com thực hiện điều này.

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

1
Vẫn không phải từ quan điểm của khách hàng. Thư viện đó thực hiện một yêu cầu tới dns-js.com/api.aspx để lấy địa chỉ IP, sau đó sẽ phân giải phía máy chủ DNS.
wp-overwatch.com

-1

Firefox có một API tích hợp cho việc này kể từ v60, dành cho WebExtensions:

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


Vì lý do gì đó, browserkhông tồn tại trong Firefox 64 beta nên tôi tự hỏi liệu điều đó có bị xóa hay không.
Sawtaytoes

3
@Sawtaytoes: Nó chỉ được hiển thị cho WebExtensions . Cũng lưu ý rằng nó yêu cầu sự dnscho phép và tập lệnh sẽ không chạy dưới dạng kịch bản nội dung (một lần nữa, browser.dnssẽ không được hiển thị ở đó)
Saturnus

@Saturnus này hoạt động tốt cho các phần mở rộng của Firefox. Có cơ hội nào để làm điều tương tự với các tiện ích mở rộng của Chrome không?
drk

-1

chắc chắn bạn có thể làm điều đó mà không cần sử dụng bất kỳ bổ sung nào, chỉ cần javascript thuần túy, bằng cách sử dụng phương pháp dns này browser.dns.resolve("example.com"); nhưng nó chỉ tương thích với FIREFOX 60, bạn có thể xem thêm thông tin trên MDN https://developer.mozilla.org/en-US/docs / Mozilla / Tiện ích bổ sung / WebExtensions / API / dns / giải quyết


4
Phương pháp này chỉ khả dụng trong ngữ cảnh của WebExtension. Nó không thể được sử dụng bởi một trang web.
duskwuff -inactive-

-2

Tôi không nghĩ rằng điều này được cho phép bởi hầu hết các trình duyệt vì lý do bảo mật, trong bối cảnh JavaScript thuần túy như câu hỏi đặt ra.


5
Nó không phải là một câu trả lời. Đây nên là một bình luận!
trejder

-3

Có thể tôi đã bỏ sót điểm nhưng để trả lời cho anh chàng NAVY đây là cách trình duyệt có thể cho bạn biết địa chỉ IP của 'người yêu cầu' (mặc dù có thể chỉ là nhà cung cấp dịch vụ của họ).

Đặt một thẻ script trong trang sẽ được hiển thị bởi ứng dụng khách gọi (có src trỏ đến) một máy chủ khác không được tải cân bằng (Tôi nhận thấy rằng điều này có nghĩa là bạn cần truy cập vào máy chủ thứ hai nhưng ngày nay máy chủ lưu trữ rất rẻ và bạn có thể thiết lập điều này dễ dàng và rẻ).

Đây là loại mã cần được thêm vào trang khách hàng:

Trên máy chủ khác "someServerIown", bạn cần có trang ASP, ASPX hoặc PHP;

----- chứa mã máy chủ như thế này:

"<% Response.Write (" var clientipaddress = '"& Request.ServerVariables (" REMOTE_ADDR ") &"'; ")%>" (không có dấu ngoặc kép dbl bên ngoài :-))

---- và viết mã này trở lại thẻ script:

   var clientipaddress = '178.32.21.45';

Điều này có hiệu quả tạo ra một biến Javascript mà bạn có thể truy cập bằng Javascript trên trang.

Hy vọng rằng bạn truy cập vào var này và ghi giá trị vào một điều khiển biểu mẫu sẵn sàng để gửi lại.

Khi người dùng đăng hoặc nhận được yêu cầu tiếp theo Javascript và / hoặc biểu mẫu của bạn sẽ gửi giá trị của biến mà "otherServerIown" đã điền cho bạn, quay lại máy chủ mà bạn muốn.

Đây là cách tôi đi vòng quanh bộ cân bằng tải ngu ngốc mà chúng tôi có để che đi địa chỉ IP của máy khách và làm cho nó xuất hiện dưới dạng của bộ cân bằng tải .... ngu ngốc ... chết lặng!

Tôi chưa đưa ra giải pháp chính xác vì tình hình của mọi người hơi khác nhau. Tuy nhiên, khái niệm là âm thanh. Ngoài ra, hãy lưu ý nếu bạn đang thực hiện việc này trên trang HTTPS "OtherServerIOwn" của bạn cũng phải gửi ở dạng bảo mật đó nếu không Khách hàng sẽ được cảnh báo về nội dung hỗn hợp. Và nếu bạn có https thì hãy đảm bảo TẤT CẢ các chứng chỉ của bạn đều hợp lệ, nếu không khách hàng cũng nhận được cảnh báo.

Hy vọng nó sẽ giúp một ai đó! Xin lỗi, đã mất một năm để trả lời / đóng góp. :-)


3
Xin lỗi, nhưng đã phải từ chối vì tôi không nghĩ nó thực sự trả lời câu hỏi ban đầu. Họ chỉ muốn tra cứu DNS tiêu chuẩn, không phải IP công khai của người dùng.
Simon East

-4

Phiên bản của tôi như thế này:

php trên máy chủ của tôi:

<?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 trên trang:

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

}).done( function( json ) {

    self.ip = json;

});

Nó hoạt động trên nhiều miền. Nó có thể sử dụng một kiểm tra trạng thái. Làm việc về điều đó.


2
Xin lỗi, nhưng đã phải từ chối vì tôi không nghĩ nó thực sự trả lời câu hỏi ban đầu. Họ chỉ muốn tra cứu DNS tiêu chuẩn, không phải IP công khai của người dùng. Mã của bạn cũng không khử trùng $ _GET, đây là một vấn đề bảo mật lớn.
Simon East

@Simon East Tôi nghĩ nó thậm chí còn tệ hơn. Có vẻ như họ muốn tra cứu bất kỳ IP nào bằng DNS.
Joeri

@SimonEast Bạn không thể chứng minh đó là vấn đề bảo mật vì bạn không biết cách tôi biên dịch php của mình. Sự nghiêm khắc của bạn chỉ là ngớ ngẩn.
Joeri

-10

Nếu máy khách đã cài đặt Java, bạn có thể làm như sau:

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

Ngoài ra, bạn có thể sẽ phải sử dụng tập lệnh phía máy chủ.


8
Tại sao ai đó ủng hộ điều này? java! = javascript, đây KHÔNG phải là câu trả lời.
Sven Mawby

2
Cốc cốc. Ai đó? (... tạm dừng dài) Java Applet
mike nelson
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.