SSH のアクセスログを洗ってみる
SSH ポート空けてると、不正にログインしようとするやつはいるもの。
また、アカウントが盗まれて変な所から ssh されることもあり得る。
そんなこんなで、/var/log/auth* なログファイルをパースしてディレクトリに振り分ける処理をざっくり書く。
わざとシーケンシャルに書いてみた ubuntu のログで多分パースできるはず。
import java.io.{PrintWriter, File} import org.slf4j.LoggerFactory import scala.io.Source object AuthLogUtil { val sshLogPattern = """^([A-Z][a-z]{2}\s+\d\s\d{2}:\d{2}:\d{2}) ([a-z]+) sshd\[\d+\]: (.+)$""".r val acceptPattern = """^Accepted .+? for ([_a-zA-Z0-9\- ]+?) from ([0-9.]+).*""".r val invalidPattern = """^Failed .+? for ([_a-zA-Z0-9\- ]+?) from ([0-9.]+).*""".r val distDir = "./replaces" val sourceDir = "./sources" val valid = "valid" val invalid = "invalid" def makePath(path:String*):String = { path.mkString(File.separator) } def using[T <: {def close()}, R](src:T)(func:T => R):R = { try { func(src) } finally { src.close() } } } class AuthLogUtil { import AuthLogUtil._ val log = LoggerFactory.getLogger(getClass) def isSSHLog(str:String):Boolean = { sshLogPattern.findFirstIn(str) match { case Some(_) => true case _ => false } } def acceptLog(user:String, ip:String, dateTime:String, host:String) { val path = makePath(distDir, valid, user.replaceAll(" ", "_"), ip) val dir = new File(path) // ディレクトリなければ作る if(!dir.exists()) dir.mkdirs() // ファイルに書き込む val filePath = path + File.separator + "auth.log" using(new PrintWriter(filePath)) { fileWriter => fileWriter.println("%s %s %s(%s)".format(dateTime, host, user, ip)) } } def invalidLog(user:String, ip:String, dateTime:String, host:String) { val path = makePath(distDir, invalid, user.replaceAll(" ", "_"), ip) val dir = new File(path) // ディレクトリなければ作る if(!dir.exists()) dir.mkdirs() // ファイルに書き込む val filePath = path + File.separator + "auth.log" using(new PrintWriter(filePath)) { fileWriter => fileWriter.println("%s %s %s(%s)".format(dateTime, host, user, ip)) } } def parse(logLine:String) { logLine match { // sshd っぽいログだけ処理 case sshLogPattern(dateTime, host, message) => { message match { // accept 系ログだけ処理 case acceptPattern(user, ip) => acceptLog(user, ip, dateTime, host) // invalid 系ログだけ処理 case invalidPattern(user, ip) => invalidLog(user, ip, dateTime, host) // それ以外のログ case other => log.warn("Not a Accept or Invalid : " + logLine) } } // 一致しないものは処理しない case _ => } } } object LogRelocator extends App { import AuthLogUtil.{sourceDir, using} val log = LoggerFactory.getLogger(getClass) // 先ずは対象ファイルを列挙 val sources = new File(sourceDir) // logLine 処理クラス val executer = new AuthLogUtil // ファイルを1個づつ処理 sources.list().foreach(fileName => { log.info("Execute file : %s".format(fileName)) // ファイルをオープン using(Source.fromFile(sourceDir + File.separator + fileName)) { source => // 1行づつ処理 source.getLines().foreach(executer.parse) } }) }
時間がかかってくれることを期待したのだけれど、自宅サーバ(しかもポート変えてると)不正ログインないなーというか、ファイルサイズが小さくて数百ミリ秒で終わってしまう。
どうすべ。。。。