クライアント側のJavascriptを使用してDNSルックアップ(ホスト名からIPアドレス)を実行できますか?


92

クライアント側のJavaScriptを使用して、クライアントのコンピューターから見たDNSルックアップ(ホスト名からIPアドレス)を実行したいと思います。それは可能ですか?


5
この質問に対する回答の多くは、サーバー側で解決を行うことを推奨しているようです。ユースケースによっては十分でない場合があります。たとえば、検索しているサービスがGSLBを使用している場合、ユーザーの場所に基づいて異なるIPを返すことがあります。その結果、サーバー側のコードが受け取る応答は、ブラウザーが受け取る応答とは異なる応答になる可能性が高くなります。そうは言っても、この違いを気にする人のための代替ソリューションはまだありません。
Ilan Rabinovitch

回答:


34

JavaScript標準ライブラリには、ホストやIPアドレスの概念はありません。したがって、ホスト名を検索するには、いくつかの外部サービスにアクセスする必要があります。

ホスト名のIPアドレスを検索し、JavaScriptを介してそれにアクセスするcgi-binをホストすることをお勧めします。


26
cgi-bin?それは古い学校です。私はそれが好きです!
Andrew Hedges

10
これは執筆時(2008)に当てはまりました。これは6年後では当てはまりません。この同じページでWebRTCに関する私のコメントを参照してください。(残念ながら、GoogleはまだIPアドレスの問題の解決策を探しているときにこのスレッドを参照しており、それが人々を誤った方向に導く可能性があります)。
領域14

1
@earizon-あなたの答えは別の質問です-あなた自身のプライベートIPアドレスを発見する方法。
Gene Vayngrib 2015年

クラウドからのCGI経由の問題は、外部からは不可能であるイントラネットホストのIPを検出することです。マシンまたはイントラネットのローカルサービスを使用する必要があります。
Tzahi Fadida 2017年

HTTPS経由でDNSクエリを送信できるようにする新しい提案されたインターネット標準があります(この回答を参照してくださいstackoverflow.com/a/58299823/9638991)。すべての現実において、それは基本的にcgi-binスクリプトと同じように機能します:)(IETFによって標準化されており、多くの大企業がそれをサポートしている場合を
除き

83

編集:この質問は私にかゆみを与えたので、クライアントのIPアドレスを返すJSONP WebサービスをGoogle App Engineに配置しました。使用法:

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

はい、サーバープロキシは必要ありません。


純粋なJSはできません。印刷する同じドメインの下にサーバースクリプトがある場合は、XMLHttpRequestを送信してそれを読み取ることができます。


4
ソースをWebサービスに投稿できますか?インスタンスを実行するとよいでしょう。
ウィル

18
申し訳ありませんが、元の質問には実際には答えないと思いますので、反対票を投じる必要がありました。ユーザーのパブリックIPではなく、標準のDNSルックアップが必要なだけです。
Simon East

29

非常に遅いですが、まだ多くの人が「Googleエアライン」を通じてここに着陸すると思います。近代的なアプローチは、サーバーサポートを必要としない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 2015年

2
非常に興味深いです。これはバグまたは設計上の欠陥であり、いずれにしても修正されるため、長期的なプロジェクトには適していません
e-info128

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 Heh。7年前の質問の質問を変更しました。満足するために必要なことは何でもしてください;-)
tcole

2
私は最近同じ質問を調査していたので、元の質問を明確にするために編集しただけでしたが、何らかの理由で、ここでのほとんどの回答は実際には元のポスターが求めていたものではなく、別の質問の下に投稿する必要があります。
Simon East

14

この質問がかなり前に行われたことは知っていますが、もっと最近の回答を提供すると思いました。

DNS over HTTPS(DoH)

DNSクエリをサポートするDNSリゾルバーにHTTPS経由で送信できます。DOHの標準はRFC 8484で説明されています

これは、他のすべての回答が示唆するものと似ていますが、実際にはDoHがHTTPSを介したDNSプロトコルであるだけです。これは「提案された」インターネット標準でもあり、非常に人気が高まっています。たとえば、一部の主要なブラウザはこれをサポートしているか、サポートする予定があります(Chrome、Edge、Firefox)。

DoHの目的の1つは次のとおりです。

Webアプリケーションが既存のブラウザーAPIを介して、クロスオリジンリソースシェアリング(CORS)と一貫性のある安全な方法でDNS情報にアクセスできるようにする

dohjsと呼ばれるWebアプリケーションからDNSルックアップを行うために特別に作成されたオープンソースツールがあります。それはありませんDNS経由HTTPSで説明したように(DOH)です。WireFormatクエリをRFC 8484。GETメソッドとPOSTメソッドの両方をサポートしています。

完全な開示:私はdohjsに貢献しています。

DNS over HTTPS JSON API

DNSワイヤフォーマットに煩わされたくない場合は、GoogleとCloudflareの両方がHTTPS経由のDNS用のJSON APIを提供しています。

GoogleのJSON DOH APIを使用してexample.comを検索するJavaScriptコードの例:

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
content-type = application / dns-message
content-length = 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クエリを送信する他の場所

DNS over HTTPSをサポートするいくつかのパブリックDNSリゾルバーのリストをいくつかの場所で見つけることができます。

上記のリソースのうち、CurlのwikiのリストとDNSCryptリストがおそらく最も完全であり、最も頻繁に更新されていると思います。Curlのページには、DoH用のオープンソースツール(サーバー、プロキシ、クライアントライブラリなど)のリストも含まれています。


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/


あなたのウェブサイトによると、これを使用して自分のIPアドレスを見つける方法がわかりません:<!-#echo var = "REMOTE_ADDR"->
ジョージカーリン

これは、ほとんどのWebサーバーで使用できる標準の「エコー」機能です。参照:google.co.uk/...
ネビル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関数を使用してそれを呼び出すようにWebサーバーを設定することです。


0

これを行うには、ブラウザーのサンドボックスを破壊する必要があります。サーバーにルックアップを実行させ、XmlHttpを介してクライアントサイドからのリクエストを要求します。



-1

Firefoxには、WebExtensions用のv60以降、このための組み込みAPIがあります。

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


なんらかの理由browserでFirefox 64ベータには存在しないので、削除されたのでしょうか。
Sawtaytoes

3
@Sawtaytoes:WebExtensionsでのみ公開されます。またdns、許可が必要であり、スクリプトはコンテンツスクリプトとして実行されません(ここbrowser.dnsでも公開されません)
Saturnus

@SaturnusこれはFirefox拡張機能で問題なく動作します。どういうわけかChrome拡張機能で同じことをするチャンスはありますか?
8分にdrk

-1

このdnsのメソッドを使用することで、純粋なJavaScriptを追加せずにそれを実行できることを確認してください。browser.dns.resolve("example.com"); ただし、これはFIREFOX 60とのみ互換性があるため、MDN https://developer.mozilla.org/en-US/docsで詳細を確認できます。 / Mozilla / Add-ons / WebExtensions / API / dns / resolve


4
このメソッドは、WebExtensionのコンテキストでのみ使用できます。Webページでは使用できません。
duskwuff -inactive-

-2

質問が尋ねるように、これはセキュリティ上の理由から、ほとんどのブラウザで純粋なJavaScriptコンテキストでは許可されていないと思います。


5
答えではありません。これはコメントです!
trejder 2015年

-3

ポイントを逃したかもしれませんが、NAVYの担当者への返信として、ブラウザが「リクエスタ」のIPアドレスを通知する方法を説明します(おそらくサービスプロバイダのみです)。

負荷分散されていない別のサーバーを呼び出す(srcがポイントしている)クライアントによってレンダリングされるページにスクリプトタグを配置します(これは、2番目のサーバーへのアクセスが必要ですが、最近のホスティングは安価であり、簡単かつ安価に設定できます)。

これは、クライアントページに追加する必要がある種類のコードです。

他のサーバー「someServerIown」では、ASP、ASPX、またはPHPページが必要です。

-----このようなサーバーコードが含まれています:

"<%Response.Write(" var clientipaddress = '"&Request.ServerVariables(" REMOTE_ADDR ")&"'; ")%>"(外側のdbl引用符なし:-))

----そして、このコードをスクリプトタグに書き戻します。

   var clientipaddress = '178.32.21.45';

これにより、JavascriptでページにアクセスできるJavaScript変数が効果的に作成されます。

うまくいけば、あなたはこの変数にアクセスして、送り返す準備ができているフォームコントロールに値を書き込みます。

ユーザーが次のリクエストを投稿または取得すると、Javascriptまたはフォーム、あるいはその両方が、「otherServerIown」が入力した変数の値を、希望するサーバーに送り返します。

これは、クライアントのIPアドレスをマスクし、それをロードバランサーのアドレスとして表示するダムロードバランサーを回避する方法です。

皆の状況は少し違うので、正確な解決策は示していません。しかし、コンセプトはしっかりしています。また、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

@サイモン・イーストもっと悪いと思います。DNSでIPを検索したいようです。
Joeri、2015

@SimonEast私がphpをコンパイルした方法がわからないので、それがセキュリティの問題であることを証明することはできません。あなたの厳格さはばかげています。
Joeri、

-10

クライアントにJavaがインストールされている場合は、次のようにすることができます。

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

それ以外は、おそらくサーバー側のスクリプトを使用する必要があります。


8
なぜ誰かがこれに賛成しているのですか?java!= javascript、これは答えではありません。
Sven Mawby

2
コンコン。誰がいるの?(...長い休止)Javaアプレット
マイクネルソン2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.