カスタマー・ポータルのインテグレーション

Traffic Sentinelの、スクリプト・クエリ機能は、ネットワーク・ユーザに提示されるトラフィック情報の抽出において、柔軟なメカニズムを提供します。多くの場合、ネットワーク停止や定期保守やトラブル・チケットを発行するシステムを提供する”カスタマー・ポータル”がすでに存在しているかもしれません。このチュートリアルでは、セキュアでスケーラブルな方法で、トラフィック情報をカスタマーにアクセス可能にするテクニックを説明しています。このチュートリアルは、Script APIを熟知している方を対象に書かれています(クエリのスクリプト化 チュートリアルを参照)。このチュートリアル内の例は、Traffic Sentinel バージョン 2.0.33 以降を必要とします。

注意: Traffic SentinelのWEBインターフェースは、ネットワーク・マネージャーやオペレーターを対象として設計されています。Traffic Sentinelの詳細でネットワーク先般に渡るトラフィック・ビューの能力は、ネットワーク・オペレーションに対してとても有効ですが、この重要な情報へのアクセスに関しては機密上の問題により制限される必要もあります。カスタマーに情報を提供するためには、カスタマー間での秘密情報の漏れやセキュリティ上の問題となる内部ネットワーク構成に関する情報の漏れが無いことを保証する必要があります。

カスタマーへデータを提供するための2つのアプローチがあります。:

  • 標準レポート(Standard Reports) それぞれのカスタマーのトラフィックを記述したチャートやテーブルの標準のセットを作成します。
  • アドホック・クエリ(Ad-Hoc Queries) カスタマーへ、選択したデータベースのパートへのクエリを実行する方法を提供します。
これらの2つのテクニックの詳細については、以下を参照ください。

標準レポート(Standard Reports)

最初のタスクは、それぞれのカスタマーの関連するネットワークやトラフィックの対象を識別する方法を見つけることです。この関連性は、ネットワークに依存する傾向にあります。:

  • スイッチ・ポート 多くのネットワークカスタマー内のスイッチ・ポートは、サーバーをネットワークに接続するときに使用するエッジ・スイッチ上のインターフェースに関連しています。これは、ファシリティの配置の事例になります。
  • MACアドレス カスタマーのルーターに結びついているMACアドレスで、カスタマーを識別出来るかもしれません。これは、レイヤー2変換の事例になります。
  • CIDR カスタマーは、個々のIPアドレスやアドレス群で関連させられるかもしれません。
ネットワークの対象にマッピングされたカスタマーは、スクリプトを利用可能にする必要があります。オプションには、以下のものがあります。:
  • file Traffic Sentinelサーバーからアクセス可能なロケーションにファイルとして情報をダンプします。
  • url WEBサーバー経由で利用可能な情報を作成します。この情報は、phpやCGIスクリプト経由で動的に作成することが出来ます。また、それは、ファイルにエクスポートするひとつの方法でもあります。
  • script Perlスクリプト内からクエリを呼び出すことが可能で、そのクエリ情報を渡すことが出来ます。

この例では、カスタマー情報は、XMLドキュメントとして利用可能とします。:

<customers>
  <customer name="InMon Corp." id="1001">
    <port agent="10.0.0.1" ifName="ethernet5" />
    <port agent="10.0.0.1" ifName="ethernet6" />
  </customer>
  <customer name="NewCo Inc." id="1002">
    <port agent="10.0.0.4" ifName="A4" />
  </customer>
</customers>
このドキュメントでは、それぞれのカスタマーは、名前とユニークなカスタマー識別子を持ちます。それぞれのカスタマーは、ひとつ、あるいは、ひとつ以上のスイッチ・ポートが割り当てられます。それぞれのスイッチ・ポートは、スイッチのIPアドレスとインターフェースの ifName によって表現されます。

それぞれのカスタマーに対して、それぞれのインターフェースのトラフィックの傾向を示すチャートを作成したい場合、以下のスクリプト(trends.txt) が、チャートを作成します。:

var url = "//www.inmon.com/tutorials2/customers.xml";
var rootdir = "/var/www/html/customers/";
var height = 200;
var width = 400;

// get customer data
var customersString = readurl(url);
var customers = new XML(customersString);

var network = Network.current();

// create list of customer interfaces
var ifs = new Array();
for each (var customer in customers..customer) {  
  for each (var port in customer..port) {
    network.path = port.@agent + ">" + port.@ifName;
    var ifId = network.interfaceId();
    if(ifId) ifs.push(ifId);
  }
}

// query for trends on each customer interface
var query = Query.trend(
  "historycounters",
  "time,interface,rate(ifinoctets),rate(ifoutoctets)",
  "interface=" + ifs,
  "yesterday",
  5);
var table = query.run();

// split results by customer
var trends = new Array();
var pvt = table.pivotTime(0,1,2);
for(var j = 1; j < pvt.ncols; j++) {
  var t = new Table();
  t.start = table.start;
  t.end = table.end;
  t.addColumn("Time","time",pvt.column(0));
  t.addColumn("In","double",pvt.column(j));
  t.scaleColumn(1,8);
  trends[pvt.cnames[j]] = t;
}
pvt = table.pivotTime(0,1,3);
for(var j = 1; j < pvt.ncols; j++) {
  var t = trends[pvt.cnames[j]];
  t.addColumn("Out","double",pvt.column(j));
}

// create charts for each customer
for each (var customer in customers..customer) {  
  var n = 1;
  for each (var port in customer..port) {
    network.path = port.@agent + ">" + port.@ifName;
    var ifId = network.interfaceId();
    if(ifId) {
      var t = trends[ifId];
      var chart = Chart.multiSeries(
           "trend", "Interface:" + n++,
           t, "Time", 0, "Bits per Second", [1,2]); 
      chart.height = height;
      chart.width = width;
      write(
        rootdir + customer.@id + "/" 
        + port.@agent + "-" + port.@ifName + ".png",
        chart);      
    }
    else println(
       "cannot find interface, agent=" + port.@agent 
       + " ifName=" + port.@ifName);
  }
} 

ほとんどのレポート・スクリプトは、同様の構文を持ちます。以下が、基本的なステップになります。:

  1. カスタマーデータの確認
  2. カスタマーに関連するデータのみを選択するためのフィルターを作成
  3. データを抽出するためのクエリを実行
  4. 生成されたデータを個々のカスタマー・テーブルに分割
  5. ここのカスタマーに対するチャートを作成しディスクに保存
このスクリプトは、JavaスクリプトのE4Xエクステンションを利用しています。このスクリプトは、XMLドキュメント上で反復させるのとドキュメント内でエレメントにアクセスするためにE4Xメカニズムを使用しています。

以下のステップは、カスタマー・チャートをアップデートするために、このスクリプトを毎日午前2時に自動実行するために、crontab コマンドを使用します。以下を、タイプしてください。:

crontab -e
以下のラインをタスクのリストに追加:
0 2 * * * /usr/local/inmsf/bin/query /home/pp/scripts/trends.txt
それぞれに異なるタイプのチャートをアップデートするために複数のスクリプトを構成する必要があるかもしれません。10分ごとに実行されるあるスクリプトは、前一時間のデータを表示するトレンド・チャートをアップデートするかもしれません。毎月実行されるあるスクリプトは、上位利用者に使用料を提示するチャートを提供するかもしれません。

この時点で、自動的に生成された一連のチャートを持つことが出来ます。それぞれのカスタマーのチャートは、カスタマーIDに対応するディレクトリに保存されます。次のステップは、どのようにしてこのデータをカスタマー・ポータル上で利用可能にするかを決定することにあります。

データをエクスポートするためのいくつかのオプションがあります。:

  • NFS カスタマーのポータルサーバー上に直接データを保存する、あるいは、カスタマーのポータルサーバーにカスタマーデータへアクセスさせるためにNFSマウントを利用することが出来ます。もし、Traffic Sentinel サーバーとカスタマーのポータルサーバーがセキュアなネットワーク上で近い場合、このテクニックは非常に便利です。
  • rsync アップデートされた情報をカスタマーポータルにコピーするために、rsync ユティリティを使用することができます。rsync は、サーバー間でのデータの転送をセキュアに行なうために ssh を使用します。
  • HTTP HTTP(セキュリティに配慮するのであればHTTPS)経由でデータをエクスポートするために、Traffic Sentinelサーバー上のApacheを編集することが出来ます。カスタマーポータルが存在しないシンプルなケースでは、単純にWEBインターフェースで、Traffic Sentinelサーバー上で公開しているページを通してユーザにトラフィックデータを提示する運用が出来ます。

次のセクションでは、許可されたカスタマーに提供される、トラフィックデータにアクセスするクエリを作成するテクニックを確認ください。

アドホック・クエリ(Ad-Hoc Queries)

アドホック・クエリは、即座に必要とされる情報やごく稀にアクセスされる情報の提供に便利です。

この例は、カスタマーに、指定された期間で特定のIPアドレスに接続した全てのホストをリストするクエリを作成することが確認できるはずです。このタイプのクエリは、感染しているかもしれない疑いのあるホストを特定するなどの場合に、カスタマーに有益な監査証跡(Audit Trail)を提供します。

このケースでは、スイッチ・ポートに関連させるのではなく、それぞれのカスタマーをひとつ、あるいは、ひとつ以上のIPアドレス群で関連させます。:

<customers>
  <customer name="InMon Corp." id="1001">
    <cidr address="10.1.1.0" bits="24" />
    <cidr address="10.1.2.0" bits="24" />
  </customer>
  <customer name="NewCo Inc." id="1002">
    <cidr address="10.1.4.0" bits="25" />
  </customer>
</customers>

以下のスクリプト (connections.txt) は、カスタマーにデータ・クエリを可能にします。

var url = "//www.inmon.com/tutorials2/customers_cidr.xml";

// get customer data
var customersString = readurl(url);
var customers = new XML(customersString);

// get cidrs for customerid
var cidrs = new Array();
for each(var cidr in customers.customer.(@id == customerid)..cidr) {
   cidrs.push(cidr.@address + "/" + cidr.@bits);
}
if(cidrs.length > 0) {
  var where = "(ipsource=" + cidrs + "|" + "ipdestination=" + cidrs + ")";
  where += "&(ipsource=" + target + "|" + "ipdestination=" + target + ")";
  println(where);
  var query = Query.topN(
    "historytrmx",
    "sourceaddress,sourceport,destinationaddress,destinationport,bytes",
     where, "today", "bytes", 100);
  var t = query.run();
  t.printHTML(true);
}

最後に、このスクリプトは、カスタマー・ポータルと一体にする必要があります。ポータルが、phpで構築されていると仮定して、以下のサンプルスクリプトは記述されています。:

<?php
$customerid = '1001';
$target = $_GET['target']; 
if($target) {
 exec('/usr/local/inmsf/bin/query\
 -input customerid='.$customerid.'\
 -input target='.escapeshellarg($target).'\
 /home/pp/scripts/connections.txt',$result);
 foreach($result as $line) echo($line);  
}
else {
 echo '<form method="GET" action="'.$PHP_SELF.'">';
 echo '<input type="text" size="12" name="target">';
 echo '<button type="submit">OK</button>';
 echo '</form>';
}
?> 

カスタマーは、そのクエリ・フォームにアクセスする前に、認証される必要があります。変数 $customerid には、認証されたカスタマーIDをセットする必要があります。

この例は、クエリを扱うカスタマーにとっての基本的な方法を示しています。:

  1. カスタマーの認証
  2. クエリ・パラメーターの抽出
  3. カスタマーにアクセスデータを制限させるためにフィルターの構成
  4. フィルターを適用するカスタマーの追加
  5. クエリの実行
  6. 結果のフォーマット