execを使いアクセスログからJavaScriptでwhois解析

Node の exec や spawn を使うと、PHP や Perl の system コマンドのように、bash などのシェルコマンドを使えます。

つまり、普段、シェルコマンドで作業してたことを JavaScript からも利用できるわけです。

で、やってみます。

Apacheのアクセスログのなかから、IPアドレスを取り出して それぞれの whois情報を確認します。

アクセス解析だけでなく、怪しいアクセスがあった時にもサクッと調査ができるスクリプトを、なんということでしょう、JavaScript で書けてしまうのです。

```javascript:mywhois.js
var os = require('os');
var exec = require('child_process').exec;

// IPをキーとして最新行だけを記録するための配列（ハッシュ）
var addrs = [];

// 自分のIP(xxx.xxx.xxx.xxx)を除く、/test/hoge.htmへの最新アクセスログを100件取得する
var cmd = 'tail -100 /var/log/apache2/ccchart.org_access.log | grep -v xxx.xxx.xxx.xxx | grep "GET /test/hoge.htm HTTP"'

exec(cmd, function (err, res) {
  if (err) console.error(err);

  // アクセスログを改行で分離し、配列化する
  var lines = res.toString().split(os.EOL);
  // 1行づつ加工処理する
  lines.forEach(function (line, i) {
    // 123.123.123.x - - [21/Jan/2013:11:17:33 +0900] "GET /... という
    // フォーマットの場合に ip 123.123.123.x を取り出す
    var addr = line.split(' - - ')[0];
    // IPアドレスをキーとするaddrs配列へ上書き記録(つまり最新行だけを記録)
    addrs[addr] = line;
  });

  // addrsハッシュのキー配列を取り出す
  var kyes = Object.keys(addrs);
  var i = 0;
  // 0.5秒ごとにIPを順に取り出してdoWhoisを実行する
  var tid = setInterval(function(){
    doWhois(kyes[i], i);
    i++;
    //データが無くなれば終了
    if(!addrs[kyes[i]]){
      clearInterval(tid);
    }
  }, 500);

  // whois を実行して、最新アクセスログとともに結果を返す
  function doWhois(x, i) {

    exec('whois ' + x, function (err, data, stderr) {
      // アドレス区切り行
      console.log(x + '----------------------------------------------\r\n');
      // 最新アクセスログ
      console.log(addrs[x] + ' \r\n');
      // whoisの結果
      console.log(data);
    });
  };
});
``` 

これをたとえば、こんな感じ ```$ sudo node mywhois.js```で実行すると、次のようなレスポンスがずらずらと出てきます。

```
202.215.xxx.xxx----------------------------------------------

202.215.xxx.xxx - - [23/Jan/2013:02:53:29 +0900] "GET /test/hoge.htm HTTP/1.1" 200 3529 "http://socketapi.com/user/wschat/1/wschat/chat.htm" "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0_2 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A551 Safari/8536.25" 

[ JPNIC database provides information regarding IP address and ASN. Its use   ]
[ is restricted to network administration purposes. For further information,  ]
[ use 'whois -h whois.nic.ad.jp help'. To only display English output,        ]
[ add '/e' at the end of command, e.g. 'whois -h whois.nic.ad.jp xxx/e'.      ]

Network Information: [ネットワーク情報]
a. [IPネットワークアドレス]     202.215.118.0/23
b. [ネットワーク名]             V-FLETS-ADSL
f. [組織名]                     丸紅アクセスソリューションズ株式会社
g. [Organization]               Marubeni Access Solutions Inc.
m. [管理者連絡窓口]             IH010JP
n. [技術連絡担当者]             HS6422JP
p. [ネームサーバ]               ns1.vectant.ne.jp
p. [ネームサーバ]               ns2.vectant.ne.jp
[割当年月日]                    2002/01/21
[返却年月日]                    
[最終更新]                      2003/06/11 17:57:02(JST)
                                
上位情報
----------
丸紅アクセスソリューションズ株式会社 (Marubeni Access Solutions Inc.)
                     [割り振り]                                 202.215.0.0/16

下位情報
```

で、もちろん、そのサーバーのログ形式によってパースの仕方は異なります。

tail を -f にしてリアルタイムチェックとか、whoisの結果も、正規表現で欲しいものだけ簡潔に取り出すとかすればすっきり使えるかも。

ただし、whoisのレスポンスは、取ればわかりますが、上記のようなJPNICだけではないので、英語と日本語が混在します。というわけで、解析時はそれを考慮する必要があります。

また、上記のように、もし、Apacheのログが root 権限なら sudo node この.js で起動する必要があったりもします。

P.S. whois様の負荷を考慮して、あまり大量過ぎる問い合わせを一気に投げないように、setIntervalで問い合わせ間隔を調整するように変更しました。