いますぐ実践! Linux システム管理 / Vol.271 / 読者数:2841名こんばんは、うすだです。 Ubuntu 16.04 LTS と日本語Remix が4月にリリースされました。 今まで 14.04 LTS を使っていましたが、HDD が手狭になってきたこともあり、 HDD を新調して、えいやーで乗り換えてみました。 移行期はたいてい戸惑いますが、お察しの通り、今回も困っています。 いま、一番不都合に感じているのが、インプットメソッドです。 15.10 から Fcitx が標準となりましたが、 日本語入力の際にキーマップを上書きしてくださるため、 自分でよきように xmodmap で設定した内容がその都度消される、 という悲しい状況に陥っています。
仕方がないので、cron で xmodmap を毎分実行してしのいでいます。 とはいえ、悪いことばかりではありません。
新しいものに触れることで、
今まで使っていたものを捨てて乗り換えるという機会も得られます。 …と、なるべく前向きに考えるようにすることで、今回の移行を、 技術的にも精神的にも乗り切りたいと考えております。 まだまだストレスの種は尽きませんが、今回もはりきってまいりますよ。 今回のお題 - Swatch でログを監視する (レベル:初級)前回、Apache のアクセスログをクラスタリングしようとして、 特に成果をあげられないまま、終わってしまいました。 Vol.270 - Jubatus でログをクラスタリングしてみる http://www.usupi.org/sysad/270.html やはり、物事を学ぶのに近道はありません。基礎から地道に勉強すべきと思います。 「守・破・離」の「守」を端折るなということですね。 というわけで今回は、「Swatch」を使って、正攻法でログを監視し、 即座に警告を通知するものを作ってみたいと思います。 Swatch の概要とインストールSwatch とは、指定したパターンがログに記録されたとき、 メールで通知したり任意のコマンドを実行したりする、シンプルなツールです。 SWATCH: The Simple WATCHer of Logfiles http://swatch.sourceforge.net ※ ものすごくシンプルなページです。 CentOS にも Ubuntu にも同名のパッケージがあり、 下記の手順でさくっとインストールできます。 $ sudo yum install swatch (RedHat系の場合) $ sudo apt-get install swatch (Debian系の場合) パッケージのファイル一覧を見ると、 中身は「swatch」コマンドとPerlのモジュールくらいで、 サービスの起動スクリプトなどはありません。 $ rpm -ql swatch (Debian系の場合は dpkg -L swatch) /usr/bin/swatch /usr/share/doc/swatch-3.2.3 /usr/share/doc/swatch-3.2.3/CHANGES ...中略... /usr/share/perl5/vendor_perl/Swatch/Actions.pm /usr/share/perl5/vendor_perl/Swatch/Threshold.pm /usr/share/perl5/vendor_perl/Swatch/Throttle.pm ...後略...
swatchコマンド自体がPerlスクリプトであり、
Swatchのモジュールを使用して自分でPerlで書いて動かすことも可能です。 $ file $(which swatch) /usr/bin/swatch: a /usr/bin/perl script text executable $ perldoc Swatch::Actions まずは簡単な使い方から
swatchコマンドの大まかな書式は以下の通りです。 swatch -c 設定ファイル -t 監視するログファイル 「-c」オプション(または「--config-file」オプション)で設定ファイルを指定し、 「-t」オプション(または「--tail-args」オプション)で監視対象のログファイルを指定します。 設定ファイルには、以下を記述します。複数記述することも可能です。 watchfor /正規表現によるパターン/ アクション ... 「watchfor」の後に指定した正規表現にマッチすると、アクションを実行します。 複数指定可能です。主なアクションを以下に示します。
たとえば、以下の設定ファイルを作成します。 watchfor /Invalid user/ mail addresses=usu\@example.org,subject="[secure] alert from swatch"
RedHat系なら「/var/log/secure」、Debian系なら「/var/log/auth.log」
を指定して以下のように実行します。 $ sudo swatch -c swatch_invalid_user.conf -t /var/log/secure すると、SSHでログインに失敗したとき、 「Invalid user」という文字がログに含まれていれば、 ログの内容を「addresses」に指定したアドレス(無指定の場合は root) 宛にメールしてくれます。 Subject: [secure] alert from swatch From: root@example.com (root) To: usu@example.org 日時 サーバ sshd[PID]: Invalid user ユーザ名 from IPアドレス メールの設定なんてしていないよという貴兄は、アクションを「echo」に置き換えると、 swatchを実行している端末にログが出力されます。
また、「exec」でコマンドを実行できます。 watchfor /authentication failure|incorrect password/ exec notify-send "swatch: $_" なお、「$_」はマッチした1行のログ全体、 「$数」は指定した「数」番目の単語に置き換わります。 ignore で無視します
「ignore」でログを無視することもできます。 ignore /正規表現によるパターン/ 指定したパターンにマッチした場合、以降の設定を評価しなくなります。 たとえば、以下のような設定ファイルの場合、sshd のログで、 「Fail」か「fail」とあれば赤色、そうでない場合は通常の色で表示します。 watchfor /sshd.*[Ff]ail/ echo red watchfor /sshd/ echo normal
1行目の正規表現(「sshd」と「Fail」または「fail」という文字がある)
にマッチすれば、2行目のアクションを実行(赤色で表示)します。 ここに、ignore の設定を追加します。 ignore /listening|restarting/ watchfor /sshd.*[Ff]ail/ echo red watchfor /sshd/ echo normal この場合、「listening」か「restarting」という文字を含む場合、 sshdのログであったとしても表示されなくなります。 $ sudo swatch -c swatch_ignore.conf -t /var/log/secure と実行しておいて、sshd (Debian系なら ssh) サービスを再起動すると、 (先の設定ファイルが「swatch_ignore.conf」という前提です。) $ sudo service sshd restart ログには以下が出力されますが、(sudo のログは割愛) 日時 サーバ sshd[PID]: Received signal 15; terminating. 日時 サーバ sshd[PID]: Server listening on 0.0.0.0 port 222. 日時 サーバ sshd[PID]: Server listening on :: port 222. swatch が出力するログは以下だけになります。 日時 サーバ sshd[PID]: Received signal 15; terminating. threshold で端折りますwatchfor と ignore、アクションを設定ファイルに書けば、 特定のログが書き込まれたとき、即座に何か行わせることができるようになります。 ただ、指定したログが大量に発生すると、 たとえばわんさかメールが来てたいへんなことになってしまいます。 そんなときは、アクションに「threshold」を指定することで、 一定数を越える同様のログを無視できます。threshold の書式は以下の通りです。 threshold track_by=/キー/,type=タイプ,count=カウント,seconds=秒
「track_by」には、thresholdの対象を区別するためのキーとなる文字列を指定します。
固定の文字列を指定すれば対象は全体になります。「$5」などを指定すれば、
プロセスごとに分けてカウントできます。
たとえば、設定ファイルが以下の場合、 watchfor /sshd.*[Ff]ail/ echo red threshold track_by=/sshd/,type=limit,count=1,seconds=60
sshdのログで [Ff]ail が含まれていれば赤色で表示されます。 おわりに以上、Swatch を使ってログを監視し、 条件にマッチしたログがあったら即座にアクションを起こす方法を、 さらっとご説明しました。 シンプルなようですが、Perlの記述が使えることを利用するなどすれば、 もっといろいろなことができそうに思います。ぜひお試しください。 宿題の答え前回の宿題は、 他のログでもクラスタリングをしてみましょう。 でした。 自分でクラスタリングと書いてしまい、可能性を狭めてしまったことや、 16.04 にしたら Jubatus が動かなくなってしまったことで、 軽く途方に暮れております。
…が、嘆いていても仕方がありません。
あくまでもクラスタリングをすることが目的であって、
何か成果を出すとは言っていないことに希望の光を見出すことにして、
淡々と進めていきたいと思います。 以下では、セキュリティに関するログ(CentOSだと「/var/log/secure」、 Ubuntuだと「/var/log/auth.log」)をクラスタリングしてみました。 今回は、sshd のログに限定し、 単純に単語の出現数だけを見てどうなるかをやってみました。 #!/usr/bin/env python # -*- coding: utf-8 -*- import sys import re import socket import jubatus from jubatus.common import Datum def line2datum(l): datum = Datum() cnts = {} for n in l.split(' '): if len(n) < 4: continue if re.match('^\d+\.\d+\.\d+\.\d+$', n): n = '0.0.0.0' else: n = n.lower() if n in cnts: cnts[n] += 1 else: cnts[n] = 1 for n in cnts: datum.add_number(n, cnts[n]) return datum def get_result(centers, r): i = 0 for center in centers: if center.num_values == r.num_values: return i i += 1 return -1 if __name__ == '__main__': if len(sys.argv) != 3: print >> sys.stderr, "Usage: %s learnlogfile testlogfile" % (sys.argv[0]) sys.exit(1) jclient = jubatus.Clustering('localhost', 9199, 'auth_log') #jclient.clear() pat = re.compile('^\S+\s+\d+\s+\d+:\d+:\d+\s+\S+\s+sshd\[\d+\]: (.*)$') # learn with open(sys.argv[1], 'r') as f: l = f.readline().rstrip() cnt = 0 while len(l) > 0: sd = pat.split(l) if len(sd) > 1: datum = line2datum(sd[1]) if datum is not None: jclient.push([datum]) l = f.readline().rstrip() cnt += 1 # get centers centers = jclient.get_k_center() print '# centers' for center in centers: print center.num_values # test print '\n# test' with open(sys.argv[2], 'r') as f: l = f.readline().rstrip() cnt = 0 while len(l) > 0: sd = pat.split(l) if len(sd) > 1: datum = line2datum(sd[1]) if datum is not None: r = jclient.get_nearest_center(datum) print "%d = \"%s\"" % (get_result(centers, r), sd[1]) l = f.readline().rstrip() cnt += 1
やけに長いですが、大まかな流れは前回のスクリプトと同じです。
詳細の説明は割愛しますが、ざっくり言うと、正規表現にマッチしたsshdのログを対象に、
出現した単語の個数をDatumに放り込んで処理しています。
まず、前回同様、jubaclusteringを実行します。 $ . /opt/jubatus/profile $ sed -e 's/"k" : 3,/"k" : 5,/' \ /opt/jubatus/share/jubatus/example/config/clustering/kmeans.json \ > kmeans5.json $ jubaclustering --configpath kmeans5.json
上記のスクリプトを実行すると、以下のような結果が得られました。 $ chmod +x clustering_authlog.py $ ./clustering_authlog.py /var/log/auth.log /var/log/auth.log # centers ...中略... # test 1 = "Received SIGHUP; restarting." 0 = "Server listening on 0.0.0.0 port 22." 0 = "Server listening on :: port 22." ...中略... 3 = "Accepted password for usuda from IPアドレス port ポート ssh2" 4 = "pam_unix(sshd:session): session opened for user usu by (uid=0)" 2 = "Received disconnect from IPアドレス port ポート ...略..." 2 = "Disconnected from IPアドレス port ポート" ...中略... 今回は、「クラスタリングされた番号 = "ログ"」という形式で出力しています。 それっぽい結果が得られた…ように思います。思ってください。 …だから何? という問いが聞こえてくるような気がしますが、 まずは手を動かして実感することが大切なのではないかと思います。(言い訳!) というわけで、いろいろ試してみてくださいませ。(投げやり!!) 今回の宿題今回の宿題は、 Swatchをサービスとして起動してみましょう。 です。 swatchコマンドを刹那的に動かすことが目的ではなく、 365日24時間休みなく我々の代わりに働いていただくことが目的なのではないでしょうか。 ということですので、systemd でも Upstart でも、 レガシーな SysV のinit でも何でも構いませんので、swatch を常時動かしてみましょう。 あとがき諸般の事情により、Raspberry Pi 3を購入しました。 電源供給が USB なのですが、最低 2A の電流が必要という記載があったため、 iPad 用のアダプタを別途購入しました。 以前購入した初代 Raspberry Pi は、家にある適当なアダプタで動作したのですが、 進化の過程で、よりたくさんの電気が必要になったようです。
で、さあ動かしてみようと思ったら、SDカードを挿す口がありません。
初代はマイクロじゃない大きいSDカードが挿せましたので、先日、
実家で発掘してきた大量のSDカードが使えると思っていたのですが…。 急遽、近くの電気屋さんで、割高なマイクロSDカードを買ってきました。 という感じで、今、ようやく、 Raspbianが動くところまでたどり着くことができたところです。 冒頭で、新しいものに触れることで、古いものを捨てて乗り換えられると書きましたが、 今回、新しい Raspi だけでなく、アダプタとマイクロSDカードが新たに加わり、 単調にものが増加していっております。
物理的にも古いものを捨てればよい、ということは理解しているのです。 家の収納スペースも、HDD と同様、年々容量が増えればいいのになあ、 と思っている今日このごろです。
今回も、ここまで読んでいただき、誠にありがとうございました。
「いますぐ実践! Linux システム管理」はこちらです。
その他、作者に関するページは、概ね以下にございます。 |
▼ トップ ▼ プロフィール ▼ リンク
▼ 作ってみました
▼ せんでん
▼ 最近読んだ本
▼ 気に入ってる本 |