いますぐ実践! Linuxシステム管理

[バックナンバーのトップへ] [Linux システム管理のトップへ]


いますぐ実践! Linux システム管理 / Vol.133 / 読者数:1311名

こんばんは、うすだです。

いきなり唐突ですが、スラッシュドット・ジャパンに、以下のような記事がありました。

Linuxを使う本当の理由?
http://slashdot.jp/linux/08/03/18/0835201.shtml

Linux ユーザが Linux を使う真の理由は、 セキュリティの強化や無料のためなどではなく、「楽しい」からなのではないか、 という新説が上記で提示されています。

わたしは、お仕事用マシンもプライベートマシンも、Linux がメインですが、 確かに、コマンドラインでいろいろやるのは楽しいですし、 システムをいじくり回すのも楽しいです。

Linux を使えるようになりたいけど慣れないなぁ、と思われている方は、 Linux をいじくり回す「楽しさ」に目覚めていない、 あるいは「楽しさ」を求めていない、からなのかもしれませんね。

そんなときは、当メルマガを読んで、わからないけどとりあえず実行してみよう、 と無理矢理思い込んで、実行してみてはいかがでしょうか。

結論も唐突になってしまいましたが、今回も、はりきってまいりますよ。

今回のお題 - 特定のログをメールで通知する

いまや、ネットワークのない環境はほとんど存在しないのではないか、 と思えるくらい、いろんなものが、ネットワークに接続されています。

そして、直接的にせよ間接的にせよ、インターネットに接続された環境では、 不正侵入される可能性が常につきまといます。

また、あまり身内を疑いたくはありませんが、社内からの不正侵入の可能性も、 ないとは言いきれません。

そんな世知辛い世の中ですから、システム管理者たるもの、 不穏な空気はなるべく早急に察知すべきだと思ってしかるべきでしょう。

さて、世の中には、IDS(不正侵入検知システム)というものが、 いくつも存在します。
IDS を使えば、侵入そのものや侵入の試みを検知して、 メールなどで通知することができます。

ですが、IDS のインストールや設定方法の調査、 バージョンアップの対応などを行うことは、それなりに手間がかかります。
また、そんな高機能である必要はなく、 決まったログを通知してくれさえすればいいんだ、 と思うことも多々あるのではないかと思います。

そのような貴兄のために、今回は、特定のログを検知して、 それをメールで通知する方法について、ご紹介したいと思います。


今回は、ログインに失敗したときのログを検知し、 メールで通知することを目指したいと思います。

ログインに関するログは、/etc/syslog.conf によりますと、 facility が authpriv か auth になるようです。

  authpriv         /var/log/secure      (※1)
  auth,authpriv    /var/log/auth.log    (※2)

※1: Fedora Core5 や Vine Linux4.2 などの場合
※2: Ubuntu7.10 などの場合

ちなみに、手元にある OpenSUSE10.1 には、 syslog ではなく syslog-ng が入っていますが、該当する設定は見当たりませんでした。

さて、これと同じログを、パイプを通して受け取るようにします。
ここでは、/var/log/authpriv というファイル名のパイプに渡そうと思いますので、 以下の設定を /etc/syslog.conf に追加します。

  auth,authpriv    |/var/log/authpriv

かたや、OpenSUSE の場合は、 以下を /etc/syslog-ng/syslog-ng.conf に追加してください。

  filter f_authpriv { facility(auth,authpriv); };
  destination authpriv { fifo("/var/log/authpriv"); };
  log { source(src); filter(f_authpriv); destination(authpriv); };

もちろん、上記のパイプが必要ですので、mkfifo コマンドを使って作成します。

  # mkfifo -m 600 /var/log/authpriv

そして、syslogd(あるいは syslog-ng) に設定変更を伝えるため、以下を実行します。

  # /etc/init.d/syslog reload    (※1)
  # /etc/init.d/sysklogd reload  (※2)

※1: Fedora Core5, Vine Linux4.2 や OpenSUSE10.1 などの場合
※2: Ubuntu7.10 などの場合

あとは、/var/log/authpriv から読み出して、その内容をメールで送ってやれば、 目的達成です。
まずは単純に、以下のようなスクリプトを作成してみました。

  #!/bin/sh
  while read message; do
      echo $message | /usr/bin/Mail -s 'syslog authpriv' root
  done < /var/log/authpriv

/var/log/authpriv から1行ずつ読み出して、 Mail コマンドで root 宛にメールを送信するだけのスクリプトです。
これを、auth2mail.sh というファイル名で保存したら、実際に実行してみましょう。

  # chmod +x auth2mail.sh
  # ./auth2mail.sh

すると、/var/log/secure や /var/log/auth.log に出力される内容が、 そのままメールで送信されるようになります。
(試しに、上記スクリプトを実行したまま、別のマシンなどから、 SSH でログインに失敗してみてください。)


以上、特定のログをメールで通知する方法を、お知らせしました。

…と言いたいところですが、たとえば、SSH でログインに失敗しますと、 Vine の場合、10行以上ログが出力されます。
(以下では、日付とホスト名を省略しています。)

  sshd[PID]: pam_unix(sshd:auth): authentication failure; ...
  sshd[PID]: error: PAM: Authentication failure for usu from ...
  ...
  sshd[PID]: Postponed keyboard-interactive for usu from ...
  ...
  sshd[PID]: Failed password for usu from ...
  ...
  sshd[PID]: Connection closed by ...

前述のスクリプトでは、1行につき1つのメールが送信されますので、 こうたくさん送りつけられますと、読むだけでも大変です。

そこで、たとえば、ログに 'Failed password' という文字列を含むときだけ、 メールを送信するようにしてみましょう。
一旦スクリプトを終了させて、スクリプトの内容を、以下に変更してみてください。

  #!/bin/sh
  while read message; do
      if [ "z`echo $message | grep 'Failed password'`" != z ]; then
          echo $message | /usr/bin/Mail -s 'syslog authpriv' root
      fi
  done < /var/log/authpriv

1行読み込んだ $message に、'Failed password' を含むときのみ、 Mail コマンドでメールを送信します。
(先ほどと同様にスクリプトを実行して、SSH などでログインに失敗してみましょう。)


以上、特定のログをメールで通知する方法を…と言いたいところですが、 たとえば Ubuntu の場合、それでも3通ほどメールが届いてしまいます。
また、Failed password 云々だけで、他の情報が抜けてしまうのも、 少々もの足りない気がします。

そこで、ちょっと発想を変えて、一定期間に出力されたログを、 まとめて 1通のメールで通知するようにしてみましょう。

  #!/bin/bash
  while [ 1 ]; do
      allmessages=""
      while read -t 60 message; do
          allmessages="${allmessages}${message}@RET@"
      done < /var/log/authpriv
      if [ "z$allmessages" != z ]; then
          echo $allmessages | sed 's/@RET@/\n/g' | \
              /usr/bin/Mail -s 'syslog authpriv' root
      fi
  done

前半の while 文で、60秒間ログが出力されなくなるまで、ひたすら読み込んで、 内容を $allmessages に追加していきます。
60秒間出力されないと、while 文を抜けます。そして、 $allmessages が空っぽでないときに、Mail コマンドでメールを送信します。

これを用いますと、先ほどの10行ちょいあるログが、 まとめて1通で送信されるようになります。1通だけなら、 多少冗長でも許せますよね。ね。


以上、特定のログを…と言いたいところですが、まだ問題があります。
ログインに成功したときなどの際にも、メールが届いてしまいます。

  sshd[PID]: Accepted keyboard-interactive/pam for usu from ...
  sshd[PID]: pam_unix(sshd:session): session opened for user usu...

SSH や FTP などで、いろんなひとに利用されるマシンですと、 その度にメールが飛んできますので、チェックが大変ですし、 セキュリティ的にもあまりよろしくないように思われます。

そこで、今度は、まとめたログに fail という文字列が含まれているときのみ、 メールを送信するようにしてみましょう。

  #!/bin/bash
  while [ 1 ]; do
      allmessages=""
      while read -t 60 message; do
          allmessages="${allmessages}${message}@RET@"
      done < /var/log/authpriv
      if [ "z`echo $allmessages | grep -i fail`" != z ]; then
          echo $allmessages | sed 's/@RET@/\n/g' | \
              /usr/bin/Mail -s 'syslog authpriv' root
      fi
  done

先ほどと異なるのは、if 文の条件だけです。
ここでは、 $allmessages に fail という文字列が含まれる(大文字小文字の区別なし)場合に、 メールを送信するようにしています。

これで、ログインに失敗したログを、 1つにまとめてメールで通知できるようになりました。


以上、特定のログをメールで通知する方法を、ご紹介しました。
(今度こそ、ホントウのおしまいです。)

ただ、上記では、60秒で区切っていますが、システムの設定やタイミングによっては、 1つの失敗が複数のメールで通知されたり、他のログが混入することも、 十分ありえます。

また、ログの情報をメールで別のマシンに送信するというリスクも、 実際に運用する際には、きちんと検討する必要があると思います。

ちなみに、syslog に関するネタは、以前にいくつかご紹介しています。
パイプを使った方法もご紹介していますので、興味のあるかたは、 以下をご覧くださいませ。

Vol.016 - syslog を管理する
http://www.usupi.org/sysad/016.html
Vol.017 - syslog を集中管理する (…の宿題の答え)
http://www.usupi.org/sysad/017.html

また、メールを送信するスクリプトを、今回は手動で動かしていますが、 これを自動的に実行する方法を、以下でご紹介しております。
こちらも、よろしければどうぞ。

Vol.094 - デーモンじゃないものをデーモンにする
http://www.usupi.org/sysad/094.html

これが実用的かどうかはともかく、実際に動かしてみることで、侵入検知のしくみが、 なんとなく理解できるのではないかと思います。
(もちろん、本物の IDS は、もっと複雑なことをされていますし、 パイプを使ってもいないと思います。あくまで雰囲気的にということで…。)

また、Mail コマンドに渡さなければ、単体で試せますので、是非、 試行してみてくださいませ。

宿題の答え

前回の宿題は、

  メールのログを集計して、日毎の送受信バイト数を求めましょう。

でした。

前回は、時間をキーにして集計しましたが、今度は日付です。
(そして、前回同様、詳細な説明はございません。すみません。)

  #!/usr/bin/perl
  use strict;

  my %tm;
  my %sz;
  my %tot;
  my %num;

  while(<>) {
      chop;
      # (1) ↓時間ではなく、月と日に括弧がついた
      if(/^(\S+)\s+(\d+)\s+\d+:\d+:\d+[^:]*\]:\s*([^:^\s]+):.*size=(\d+)/) {
          $tm{$3} = "$2-$1";  # 日-月 を記録  ($3 がキューID)
          $sz{$3} = $4;       # サイズを記録 ($4 がサイズ)
      # (2) ↓送ったかどうかの判定は変わらず
      } elsif(/^\S+\s+\d+\s+\d+:\d+:\d+[^:]*\]:\s*([^:^\s]+):.*stat[^=^\s]*=[Ss]ent/) {
          if($sz{$1} > 0) {
              $tot{$tm{$1}} += $sz{$1};
              $num{$tm{$1}}++;
              $tm{$1} = $sz{$1} = 0;
          }
      }
  }

  # (3) キーのソートを数字に変更
  foreach my $m (sort {$a <=> $b} keys %tot) {
      printf("%s,%d,%d\n", $m, $tot{$m}, $tot{$m}/$num{$m});
  }

前回のスクリプトと見比べればわかりますが、ほとんど変わりません。
時刻をキーにしていたところを、"日-月" に変更しただけです。

これを、mtasize2.pl というファイル名で保存して、 以下のように実行権をつけて実行すれば、前回同様、結果が CSV 形式で得られます。

  # chmod +x mtasize2.pl
  # ./mtasize2.pl /var/log/maillog

もし、ログファイルが複数にわかれているなら、以下のように、 まとめて実行してください。

  非圧縮形式の場合:
    # cat /var/log/maillog.? | ./mtasize2.pl
  非圧縮の場合:
    # zcat /var/log/maillog.4.gz > /tmp/maillog_all.log
    # zcat /var/log/maillog.3.gz >> /tmp/maillog_all.log
    # zcat /var/log/maillog.2.gz >> /tmp/maillog_all.log
    # zcat /var/log/maillog.1.gz >> /tmp/maillog_all.log
    # ./mtasize2.pl /tmp/maillog_all.log
    # rm /tmp/maillog_all.log

出力された CSV を、あれやこれやすると、以下のグラフができました。

上記によりますと、土日がどうこうという法則性が見られることもなく、 のぺーっとした結果が得られただけでした。
ちなみに、27日から下降線をたどっているのは、 管理下にあったドメインが期限切れになったためです。

このように、期待した結果が得られないこともありますが、めげないで、 今後もいろいろ試していただけますと幸いです。(言い訳…)

今回の宿題

今回の宿題は、

  プロミスキャス・モードになったときに、メールで通知しましょう。

です。

tcpdump コマンドなどを起動し、ネットワーク上のパケットをキャプチャするとき、 ネットワーク・インタフェースが、プロミスキャス・モードというモードになります。

具体的には、/var/log/messages などに、以下が記録されます。

  Mar 23 02:19:23 xxx kernel: device eth0 entered promiscuous mode
  Mar 23 02:21:10 xxx kernel: device eth0 left promiscuous mode

ネットワークをキャプチャしないといけない、いうシチュエーションは、 通常の業務では、あまりないことだと思います。
ということは、 誰かがこっそりネットワークを盗み見ようとしている可能性が考えられます。

疑わしきは検知せよ、ということで、 上記のログをメールで通知するようにしてみてください。

あとがき

冒頭に引き続き、またまた、ご紹介なお話です。
シェルから、さまざまな方法を用いて、Hello World を出力してみよう! という、楽しい記事です。

Hello World コレクション(2) シェルスクリプト編
http://journal.mycom.co.jp/column/helloworld/002/index.html

echo や printf コマンドくらいなら、だれでも思いつくと思いますが、 よくもまあこれだけ考えたなあ、というくらい、 変わった方法がたくさん紹介されています。

ここで、少しでもご紹介するのはもったいないですので、 みなさんで上記を参照してみてください。(難しくありませんので、楽しく読めます。)

ちなみに、上記は第2回ですが、第1回では C言語の、 第3回では C++言語の出力が取り上げられています。(こちらはややまっとうです。)

Hello World コレクション
http://journal.mycom.co.jp/column/helloworld/

こういった身近なところにも、いろいろ考える余地はあるのですね。
普段からこのように考えることで、どんなときでも、 なんらかのアイデアをひねり出せるようになる…のかもしれません。

というわけで、淡々と仕事をしていると、 だんだんマンネリ化(よく言うとルーチンワーク化)していきがちですので、 なにか改善の余地がある、あるいはもっと楽しく仕事できる、 という視点を常に持って、よいほうに変化し続けられるようにしたいと思います。

 

今回も、ここまで読んでいただき、ありがとうございました。
それでは、次回は 4月6日 頃に、お会いしましょう!

 

「いますぐ実践! Linux システム管理」の解除は、以下からできます。
http://www.usupi.org/sysad/ (まぐまぐ ID:149633)

バックナンバーは、こちらにほぼ全部そろっています。
http://www.usupi.org/sysad/backno.html

「栗日記」− ややスランプ気味ですが、がんばって栗画を描いてます。
http://www.usupi.org/kuri/ (まぐまぐ ID:126454)
http://usupi.seesaa.net/ (栗日記ブログ)


[バックナンバーのトップへ] [Linux システム管理のトップへ]

トップ

バックナンバー
    [日付順] [目的別]

プロフィール

▼ リンク

独学Linux
Linuxデスクトップ環境に関する情報が満載です。 メルマガもありますよ。
Server World
CentOS 6をサーバとしたときの設定例が、これでもかというくらいたくさん載っています。 CentOS以外のディストリビューション(Fedora, Ubuntu)も充実しています。
LINUXで自宅サーバーを構築・導入(Fedora9)
Fedora9のインストールの仕方から管理方法まで、詳しく載っています。 SearchManには情報がもりだくさんです。
マロンくん.NET
〜サーバ管理者への道〜
Linuxをサーバとして使用するための、いろいろな設定方法が載っています。 マロンくんもかわいいです。 なんといっても、マロンくんという名前がいいですね!!
日経Linux
今や数少なくなってしまったLinuxの雑誌。ニュースやガイドもあります。
Linux Square − @IT
@ITが提供する、Linux の情報が満載。 載っていない設定方法はないんじゃないでしょうか。
gihyo.jp…技術評論社
Linuxに限らず様々な技術情報が満載のサイト。 SoftwareDesign誌も、 ソフトウェア技術者は必見です。
SourceForge.JP Magazine
Linux に限らず、オープンソース関連の記事が網羅されています。
ITmediaエンタープライズ:Linux Tips 一覧
Tips というより FAQ 集でしょうか。わからないことがあれば覗きましょう。
IBM developerWorks : Linux
開発者向けですが、勉強になりますよ。
Yahoo!ニュース - Linux
Yahoo!のLinuxに関するニュース一覧です。
栗日記
システム管理とかと全然関係ありませんが、毎日栗の絵を描いています。
システム管理につかれちゃったとき、癒されたいときに、ご覧ください。:-)
WEB RANKING - PC関連
ランキングに参加してみました。押してやってください。

▼ 作ってみました

Add to Google

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本