運用環境 シェル(その14)

【連載】

にわか管理者のためのLinux運用入門

【第194回】運用環境 シェル(その14)

[2019/09/03 09:15]後藤大地 ブックマーク ブックマーク

サーバ/ストレージ

ツールとして仕上げていく

前回はsshdのログファイルを解析して不正ログインを試みてきたユーザー名とIPアドレスを閲覧表示するシェルスクリプトを作成した。今回はこのスクリプトにさらに手を加えて、日付ごとに不正アクセス元IPアドレスとその記録回数をグラフにして出力するスクリプトに変更する。

先に成果物を掲載しておく。次のようなスクリプトを「ssh-check」という名前でつくった。

#!/bin/sh

logfile=/var/log/auth.log

# ログデータを取得
cat $logfile                        |
#
# sshdに関するログのみを選択
grep    -E 'sshd\[[0-9]*\]'                 |
#
# 必要なデータのみを抽出
#   1列目:    月
#   2列目:    日
#   3列目:    時:分:秒
#   12列目:   ユーザー名
#   14列目:   アクセス元IPアドレス
awk '{print $1,$2,$3,$12,$14}'              |
#
# 必要なログのみを選択
grep -E '[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}'     |
#
# 日付データを正規化(年月日時分秒)
while read mon day time user ip
do
    date=$(date --date="$mon $day $time" +%Y%m%d%H%M%S)
    echo "$date $user   $ip"
done                                |
# 1:年月日時分秒 2:ユーザー名 3:アクセス元IPアドレス
#
# 年月日時分秒を年月日に変更
awk '{print substr($1, 1, 8),$3}'               |
# 1:年月日 2:アクセス元IPアドレス
#
# 日付とアクセス元IPアドレスごとに数を集計
sort    -k1,2                           |
count   1 2                         |
# 1:年月日 2:アクセス元IPアドレス 3:集計数
#
# 集計数を横棒グラフに変更
awk '{
    bar=""
    for (i=0; i<$3; i++)
        bar=bar "*"
    print $1,$2,bar
}'                              |
# 1:年月日 2:アクセス元IPアドレス 3:棒グラフ
#
# 出力を若干調整
sed -e 's/ \([0-9]\)[.]/   \1./'                \
    -e 's/ \([0-9][0-9]\)[.]/  \1./'            |
sed -e 's/[.]\([0-9]\)\([. ]\)/.  \1\2/g'           \
    -e 's/[.]\([0-9][0-9]\)\([. ]\)/. \1\2/g'       |
sed -e 's/[.]\([0-9]\)\([. ]\)/.  \1\2/g'           \
    -e 's/[.]\([0-9][0-9]\)\([. ]\)/. \1\2/g'

このスクリプトを実行すると次のような結果を得ることができる。

% ./ssh-check 
20190731 170. 80.226. 29 **
20190731  27. 41.190. 25 *
20190802 113.109.110. 51 *
20190802 223.199.221.178 *
20190802  59.125. 69. 40 ***
20190803 113. 17. 31. 61 *
20190803  14.118.206.120 *
20190803 183.128.224.219 *
20190804 115.213.143.250 *
20190804 170. 80.227. 99 *
20190804 217. 92.127.208 *
20190804  27.222.223.201 *
20190804  58. 35. 16.  9 *
20190804  71.202.241.115 *
20190805 113.215.220. 89 *
20190805  31.181.215. 22 *
20190806 101.235.114.131 *
20190806 113.215.193.142 *
20190806 121. 25. 24. 86 *
20190806 177.184.189.209 **
20190806 183.159.195. 55 *
20190806  76. 20. 69.183 *
20190806  91.250. 22.133 *
20190807 115.213.128.113 *
20190807 115. 59.120. 27 *
20190807 125. 42.179.246 *
20190807 188. 92. 75.248 *********************
20190807  49.130. 34. 61 *
20190807  49. 69. 83. 42 *
(略)
20190831 112. 93.138. 80 *
20190831 115.200.120. 56 *
20190831 123.145. 79. 20 *
20190831 123.157.113.170 *
20190831 218. 57. 96.113 *
20190831  39. 65.132. 59 *
20190831  39. 87.180. 98 *
20190831  69.115.101.133 *
%

このくらいであれば、書き換えにかかる時間は10分から1時間もあれば十分だと思う。

追加したコマンドについて

個々のコマンドの使い方がわかっていれば特に説明はいらないと思うが、追加したコマンドをざっくり説明しておこうと思う。

「YYYYmmddHHMMSS」というデータを「YYYYmmdd」に変換する処理は次のように実装した。

# 年月日時分秒を年月日に変更
awk '{print substr($1, 1, 8),$3}'               |

これはawkコマンドに用意されているsubstr()関数の機能で、1列目の1文字目から8文字分を切り出して出力するという内容になっている。この手のシェルスクリプトとawkは相性がよく、結構便利に使用できる。

次の処理は日付とIPアドレスをごとにデータを集計して、日付ごとにアクセス元IPアドレスからのログ記録回数を集計するものだ。

# 日付とアクセス元IPアドレスごとに数を集計
sort    -k1,2                           |
count   1 2                         |
# 1:年月日 2:アクセス元IPアドレス 3:集計数

ここでは「count」というコマンドを使って処理を行っている。countはあまり広く使われているコマンドではないので、処理系によっては存在しないこともある。その場合は、awkコマンドで同じような働きをする処理を記述すればよいだろう。

次の処理は集計した数を棒グラフにする処理だ。

# 集計数を横棒グラフに変更
awk '{
    bar=""
    for (i=0; i<$3; i++)
        bar=bar "*"
    print $1,$2,bar
}'                              |
# 1:年月日 2:アクセス元IPアドレス 3:棒グラフ

awkで数値を文字列に変換している。数の分だけ棒グラフを表現する文字を増やしているだけだ。

最後に棒グラフが見やすくなるように、IPアドレスを長さを揃えたドット区切りで表示されるように調整している。

# 出力を若干調整
sed -e 's/ \([0-9]\)[.]/   \1./'                \
    -e 's/ \([0-9][0-9]\)[.]/  \1./'            |
sed -e 's/[.]\([0-9]\)\([. ]\)/.  \1\2/g'           \
    -e 's/[.]\([0-9][0-9]\)\([. ]\)/. \1\2/g'       |
sed -e 's/[.]\([0-9]\)\([. ]\)/.  \1\2/g'           \
    -e 's/[.]\([0-9][0-9]\)\([. ]\)/. \1\2/g'

シェルスクリプトはコマンドのスキルでもある。コマンドの使い方をよく知っているほど、こうした処理を簡単に記述することができる。

1つの考え方として

ここで紹介しているようなシェルスクリプトは、Pythonで全部書くこともできるし、awkで書くこともできる。どちらかというかawkで書くほうがいいかもしれない。

なぜここで紹介したような感じでシェルスクリプトに書いているかというと、後からよく使う処理を別のコマンドとして実装しやすくなるからだ。例えば、今回書いたシェルスクリプトだが、個々の機能を個別のコマンドとして実装すれば、次のような感じでシェルスクリプトをシンプルに書くことができるようになる。

#!/bin/sh

logfile=/var/log/auth.log

# ログデータを取得
cat $logfile                        |
#
# sshdに関するログのみを選択
grep_sshd                           |
#
# 必要なデータのみを抽出
#   1列目:    月
#   2列目:    日
#   3列目:    時:分:秒
#   12列目:   ユーザー名
#   14列目:   アクセス元IPアドレス
retusel 1 2 3 12 14                     |
#
# 必要なログのみを選択
grep_ipaddr                         |
#
# 日付データを正規化(年月日時分秒)
datefmt 1=1+2+3                         |
retusel 1 5                         |
# 1:年月日時分秒 2:アクセス元IPアドレス
#
# 年月日時分秒を年月日に変更
datefmt 1.%Y%m%d%H%M%S.%Y%m%d
# 1:年月日 2:アクセス元IPアドレス
#
# 日付とアクセス元IPアドレスごとに数を集計
aggregate 1 2                           |
# 1:年月日 2:アクセス元IPアドレス 3:集計数
#
# 集計数を横棒グラフに変更
num2bar 3                           |
# 1:年月日 2:アクセス元IPアドレス 3:棒グラフ
#
# 出力を若干調整
ipfmt   2.%3d%3d%3d%3d

業務で必要になる処理は、似たような処理であることが多い。このため「こういうコマンドがあればな」という部分が経験を重ねるにつれてはっきりしてくる。そうなってきたら、その部分をコマンドとして実装すればよい。Pythonで書いてもよいし、awkで書いてもいいだろう。処理速度が必要になったらC言語で書き換えればよい。

こんな感じでシェルスクリプトで処理を組んでいくときは、将来的には自分でコマンドを開発することも視野に入れておくとよい。うまくいけば業務に必要なスクリプトをすごく簡単に書けるようになる。

※ 本記事は掲載時点の情報であり、最新のものとは異なる場合がございます。予めご了承ください。

一覧はこちら

連載目次

もっと知りたい!こちらもオススメ

なぜ今、統合システムなのか? 押さえておくべき「3つのインパクト」

なぜ今、統合システムなのか? 押さえておくべき「3つのインパクト」

ガートナー ジャパンは10月31日~11月2日、都内で「Gartner Symposium/ITxpo 2017」を開催。11月1日には同社 主席アナリストの青山浩子氏が登壇し「CIOが理解すべき統合システムの3大インパクト」と題する講演を行った。本稿では、講演の内容をダイジェストでお届けする。

関連リンク

この記事に興味を持ったら"いいね!"を Click
Facebook で IT Search+ の人気記事をお届けします

会員登録(無料)

注目の特集/連載
[解説動画] Googleアナリティクス分析&活用講座 - Webサイト改善の正しい考え方
[解説動画] 個人の業務効率化術 - 短時間集中はこうして作る
ミッションステートメント
教えてカナコさん! これならわかるAI入門
知りたい! カナコさん 皆で話そうAIのコト
対話システムをつくろう! Python超入門
Kubernetes入門
AWSで作るクラウドネイティブアプリケーションの基本
PowerShell Core入門
徹底研究! ハイブリッドクラウド
マイナビニュース スペシャルセミナー 講演レポート/当日講演資料 まとめ
セキュリティアワード特設ページ

一覧はこちら

今注目のIT用語の意味を事典でチェック!

一覧はこちら

ページの先頭に戻る