ゲーム攻略からプログラミングまで、その時に思いついたことをだらだらと書き連ねていきます。

【jQuery】RDAPで遊んでみた

2019.09.04 12:00 | コメント(0) | 技術

program.jpg
なかなか楽しい

どうも、さつきさんです。
このまま行くとモンハンやらなさそう...。
誰か誘ってクレメンス。

さて、今日はRDAPのお話。

RDAP(Registration Data Access Protocol)
RDAPとは、IPアドレス等のレジストリに登録したデータにアクセスするためのプロトコル。
RFC7480 ~ 7485において、WHOISプロトコルの後継として標準化された。

はい。
この辺のお話と、実装コードをちょっと紹介していきます。

RDAPざっくり

堅苦しい定義ではなく、実際の話をすると、
whoisを叩いたときの結果をJSON形式で返してくれるAPIができたよ、というお話。
詳しい話を知りたい人はすまん、別サイトでも検索してくれ。

便利になった点

これまでのwhoisの結果はフォーマットが曖昧で、返ってくる内容も文字列ベースでした。
今回の場合はJSON形式で返ってくる、つまり項目が簡単に判別できるようになりました。


実際に作ってみた

JSONで返すってことは、WEB上から簡単にデータを引けるんじゃない?
というわけで、AjaxでデータをひっぱてくるjQueryを作ってみました。

ソース

<script type="text/javascript">
$(document).ready(function(){

  /* 取得結果を表示する小窓を閉じるための処理 */
  $(document).on('click', function(e){
    if ( e.which === 1 ) {
      if ( $('.rdap_results_box').is(':visible') ) {
        if (
           !$(e.target).hasClass('rdap_results_box')
        && !$(e.target).hasClass('rdap_results')
        && !$(e.target).hasClass('rdap_results_parts')
        &&  $(e.target).parents().index($('.rdap_results_box')) < 0
        ) {
          $('.rdap_results').hide();
        }
      }
    }
  });

  /* クリックしたIPアドレスを検索する */
  $('.search_rdap').click(function(e){
    e.preventDefault();
    var addr = $(this).text();
    var elem_id = $(this).attr('id');
    get_rdap_info(addr, elem_id);
  });

});

/* AjaxでRDAPにて情報を取得する */
function get_rdap_info(addr, elem_id){
  var target_id = '#' + elem_id + '_results';
  var base_url = 'https://rdap.apnic.net/ip/';
  var target = $(target_id);
  try {
    $.get(base_url + addr, function(data, status) {
      if ( data && target.length > 0 ) {
        target.html = '<p>情報を検索中です...</p>';
        target.show();
        set_rdap_values(data, target_id);
      }
    });
  }
  catch(error) {
    console.log(error);
  }
}

/* 取得した情報を整形して表示する */
function set_rdap_values(data, target_id){
  var target = $(target_id);
  if ( target.length > 0 ) {
    var table   = $('<table>').addClass('rdap_results rdap_results_parts');
    var head    = $('<tr>').append(
      $('<th>').addClass('rdap_results_parts').append('項目')
    ).append(
      $('<th>').addClass('rdap_results_parts').append('値')
    );
    table.append(head);
    
    var attributes = ['country', 'type', 'name'];
    $.each(attributes, function(idx, attr) {
      table.append(
        $('<tr>').append(
          $('<td>').addClass('attr_title rdap_results_parts').append(attr)
        ).append(
          $('<td>').addClass('attr_value rdap_results_parts').append(data[attr])
        )
      );
    });

    if ( data['startAddress'] != '' || data['endAddress'] != '') {
      var range = (data['startAddress'] == '' ? 'unknown' : data['startAddress']) + ' - ' + (data['endAddress'] == '' ? 'unknown' : data['endAddress']);
    }
    else {
      var range = 'unknown';
    }
    table.append(
      $('<tr>').append(
        $('<td>').addClass('attr_title rdap_results_parts').append('range')
      ).append(
        $('<td>').addClass('attr_value rdap_results_parts').append(range)
      )
    );
    target.append(table);
  }
}
</script>
他に必要なソースはこんな感じかな。 簡単なHTMLくらい。
<div>
<p><a id="in_article" href="" class="search_rdap">xxx.xxx.xxx.xxx</a></p>
<div id="in_article_results" class="rdap_results_box" style="display:none;"></div>
</div>

実際の画面はこんな感じ。

※ 動きません。

xxx.xxx.xxx.xxx

<!-- 問い合わせ結果の表示イメージ -->

項目
countryJP
typeALLOCATED PORTABLE
nameREGISTERED DOMAIN NAME
rangexxx.xxx.0.0 - xxx.xxx.255.255

簡単な説明

対象のクラスを持っている要素をクリックしたタイミングで関数が作動し、
対象の要素内の文字列をIPアドレスとしてRDAP APIに渡します。
XHR(GET)で問い合わせた結果を受け、
通信が成功した場合に結果を画面上に表示します。

すでに気付いている問題点

XHR時にでたらめな文字列を渡した場合、
HTTPステータスコード上はエラーを吐くのですが、
そのステータスを返り値として受け取ることができません
そもそも第2引数にstatusを取っていますが、
値として入ってくるのがおそらくsuccessのみ
苦し紛れに例外をキャッチするようにしてますが、そもそも例外を吐かない。
対策候補はいくつかあります。
どれももう自分が使うだけだし実装してませんが。
$.ajaxを使う
$.getではなく、$.ajaxを使う。
たぶんこれだとエラーハンドリングもできるんじゃないかな。
試してないけど、onCompleteとかonSuccessとかがあったはず。
APIリクエスト時のパラメータを精査する
リクエストする前に正規表現かなんかでチェックすりゃいいのでは。
/^\d+\.\d+\.\d+\.\d+$/
こんな感じでやればたぶんチェックできる。
ただ、この場合ipv6も弾いてしまうので注意。
(※ RDAP APIはipv6にも対応してます。)

あと、現状はAPNICにのみ問い合わせを行っているので、
海外かつAPNICに登録されていない情報の場合は引くことができません。
まあさつきさんのサイトにはいたずら以外で海外からのアクセスが来ることはまずないのでよき。


実益

さつきさんはまあまあ重宝してます。
Google AnalyticsやSearch Consoleも活用していますが、
それよりも自分で収集しているアクセス履歴の方が確認しやすい。
このアクセス履歴からいたずらに来ているIPアドレスを割り出したりできます。

(異常にアクセス数の多いIPアドレスの検知や、
存在しないファイルを探りに来ているリクエスト など)

こうした悪意のあるリクエストに対して、単発なら放っておくのですが、
しつこかったり、非常に悪質なものであった場合はiptablesに登録します。
その際に、これまで毎回IPアドレスからアクセス元の確認を手動で行っていたのですが、
この確認が画面上1クリックでできるようになるのは非常に楽。

今の所はテストも兼ねた実装なので4つの項目しか拾ってませんが、
APIから返される項目はもっと多岐にわたります。
これまで保有しているIPアドレスの範囲が分かりづらかったのですが、
RDAPでは始点と終点をそれぞれ返してくれるため、非常に使い勝手がいいです。
CIDRでiptablesに登録するため)
今は始点と終点をつなげて「range」として表示していますが、
CIDR換算してから表示してもいいかも知れませんね。
xxx.xxx.0.0/12 みたいな感じで。


まとめ

はい、というわけで今回はIPアドレスとリクエストにまつわるお話でした。
何が辛かったって、ソース載せたやんか...?

あれの色付け手動やからね

絶対なんか上手いことしてくれるプラグインあるはず。
なければ作ってもいいけどクソめんどくさい。
ちなみにソースのカラーリングはEclipseライクです。
あと驚いたのはwhoisの結果に対して、フォーマットが統一されていないということ。
そんなフリーダムな状態で今まで返してたのか。

あと、RDAPはWEB APIという形で実装されてますので、
たぶん連打すると一時的に応答してくれなくなると思います。
まあそんな必死でいろんなIPアドレスの情報引きまくることもないと思いますが、
ご利用は計画的にw
※ 実装のテストでポチポチする程度なら何ら問題ありません。

なんかこんなふうに使えばいいのでは!?
というナイスなアイデアあれば是非教えて下さい。
ではではー(*´ω`*)
技術の記事

コメント

まだコメントがありません...(´・ω・`)