Bash脚本实现实时监测登录

 更新时间:2024年11月28日 15:25:32   作者:小书童·阿杰  
在服务器的运维管理中,及时监控系统的登录日志对保障系统的安全至关重要,下面我们来看看如何使用Bash脚本实现实时监测登录日志吧

引言

背景介绍:在服务器的运维管理中,及时监控系统的登录日志对保障系统的安全至关重要。通过实时监控登录日志,运维人员可以发现潜在的异常登录行为,防止系统被非法访问。

问题引入:如何实现实时监控登录日志,并及时响应潜在的安全风险?

实时监控登录日志的意义

安全性:通过监控登录日志,可以迅速发现恶意登录、暴力 破解等异常行为。

合规性:确保满足各种合规要求,记录所有用户的登录行为。

解决方案概述

监控目标:关注登录日志中的关键信息,例如登录时间、IP 地址、用户名、登录方式等。

技术选型:通过编写 Bash 脚本,结合inotify、awk、grep 等工具,来实现对日志文件的实时监控与分析。

脚本实现原理

实时监控:利用 inotify 命令动态监控日志文件的变动,并结合 sed 命令实时提取和输出新增的登录日志。

日志筛选:通过 grep 等工具过滤出登录失败、异常登录等相关信息。

报警机制:脚本可以配置成在监控到异常行为时,自动发送通知邮件

脚本示例

#!/bin/bash
# 作者: 阿杰
# 用途: 实时检测登录日志,统计异常登录
# 脚本名称: watch_secure.sh
# 用法: bash watch_seacure.sh

# 日志记录
log_err() {
  printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: \033[31mERROR: \033[0m$@\n"
}

log_info() {
  printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: \033[32mINFO: \033[0m$@\n"
}

log_warning() {
  printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: \033[33mWARNING: \033[0m$@\n"
}

# 初始化Map
declare -A secureMap

init() {
    # 行数记录文件
    line_file_name="conf/line_file.txt"
    # inode存储文件
    inode_file="conf/inode.txt"
    # 认证失败文件记录
    ssh_auth_failed_file="conf/ssh_auth_failed.csv"

    # 文件列表
    file_array=("$line_file_name" "$inode_file" "$ssh_auth_failed_file")
    # inode 文件状态
    inode_file_status=0
    # 控制是否进行写入 0为可写,1为不可写
    write_status=1

    oneSecureKey=""

    {
        if [ ! -d "conf" ];then
            mkdir conf
        fi
        # 检查文件是否存在
        for file in ${file_array[@]};do
            check_file_exists $file
        done
        line=$(cat $line_file_name)
        if [ -z "$line" ];then
            line=0
        fi
        # 认证失败文件第一次创建
        if [ $(wc -l < $ssh_auth_failed_file) -eq 0 ];then
            # 时间以月天为单位(None为空账号或不存在账号)
            echo "登录认证失败时间,源IP地址,登录账号,连接认证失败次数" > $ssh_auth_failed_file
        fi

    }

    file_name="/var/log/secure"
    if [ -z "$(rpm -qa | grep 'inotify-tools')" ];then
        yum install -y inotify-tools > /dev/null 2>&1
        if [ $? -ne 0 ];then
            log_err "[init] inotify-tools 安装失败!"
        fi
    fi


}
# 检查文件是否存在,不存在则创建
check_file_exists() {
    local file_name=$1
    if [ ! -f "$file_name" ];then
        touch $file_name
        if [ $? -ne 0 ];then
            log_err "[check_file_exists] file: $file_name 文件创建失败!"
        fi
    fi
}



# 监听文件事件
watch_file() {
    inotifywait -mrq --format '%e' --event create,delete,modify $file_name | while read event ;do
        case "$event" in
        MODIFY)
            start_read_file
        ;;
        # 文件被删除或重新创建
        CREATE|DELETE)
            # 重置文件行数
            line=0
            > $line_file_name
            check
        ;;
        *)
            log_warning "[watch_file] watch file event: $event"
        ;;
        esac
    done
}

# 只读一行
read_line_file() {
    ((line++))
    echo $line > $line_file_name
    # 不是指定数据退出
    if [ $(sed -n "$line p" $file_name  | grep 'pam_unix(sshd:auth): authentication failure;' | wc -l ) -ne 1 ];then
        return
    fi
    # 控制是否进行写入
    write_status=0
    oneSecureKey=$(sed -n "$line p" $file_name  |awk -v dateNow=$(date +"%Y") '{
        split($0,rhost,"rhost=")
        split(rhost[2],rhost," ")
        split($0,user," user=")
        if (length(user[2])==0) {
            user[2]="None"
        }
        print dateNow":"$1":"$2","rhost[1]","user[2]
    }')
    log_info "[read_line_file] line: $line data:[$oneSecureKey]"

    send_map $oneSecureKey
}

# 往MAP中塞入数据
send_map() {
    local key=$1
    if [ -n ${secureMap[$key]} ];then
        secureMap[$key]=`expr ${secureMap[$key]} + 1`
    else
        secureMap[$key]=1
    fi
}

wirte_all_secure() {
    for key in ${!secureMap[@]};do
        write_one_secure $key
    done
}

write_one_secure() {
    local key="$@"
    local data=$(grep -w -n "$key" $ssh_auth_failed_file)
    if [ -n "$data" ];then
        local i=$(echo $data | awk -F: '{print $1}')
        local a=$(echo $data | awk -F, '{print $NF}')
        sed -i "${i} s#$a#${secureMap[$key]}#" $ssh_auth_failed_file
        if [ $? -ne 0 ];then
            log_err "[write_secure] 写 $ssh_auth_failed_file 文件失败! data:[$key,${secureMap[$key]}]"
        fi
    else
        # 新数据
        echo "$key,${secureMap[$key]}" >> $ssh_auth_failed_file
        if [ $? -ne 0 ];then
            log_err "[write_secure] 写 $ssh_auth_failed_file 文件失败! data:[$key,${secureMap[$key]}]"
        fi
    fi
    log_info "[write_secure] line: $line status: $write_status data:[$key,${secureMap[$key]}]"
}



# 启动前应先检查是否读取过
check() {
    # 检查预存Inode是否一致
    check_secure_file_inode
}

# 检查登录日志Inode是否一致
check_secure_file_inode() {
    inode=$(ls -i $file_name | awk '{print $1}')
    inode_file_data="$(cat $inode_file)"
    if [ -n "$inode_file_data" ]; then
        if [ $inode -ne $inode_file_data ];then
            log_warning "[check_secure_file_inode] secure file inode is inconsistency"
            # inode不一致,重置
            echo "$inode" > $inode_file
            inode_file_status=1
        else
           inode_file_status=0
        fi
    else
        # 第一次读取
        echo "$inode" > $inode_file
        inode_file_status=1
    fi
}

# 开始读取文件
start_read_file() {
    # 第一次读取
    if [ $inode_file_status -eq 1 ] ;then
        # 使用循环将历史内容读取
        while true;do
            if [ $line -eq $(wc -l < $file_name) ];then
                break
            fi
            read_line_file
        done
        wirte_all_secure
    elif [  $line -ne $(wc -l < $file_name) ];then
        # 使用循环将行数对齐
        while true;do
            if [ $line -eq $(wc -l < $file_name) ];then
                break
            fi
            read_line_file
            if [ $write_status -eq 0 ];then
                write_one_secure $oneSecureKey
            fi
            # 状态设置为1
            write_status=1
        done
    # else
    #     read_line_file
    #     if [ $write_status -eq 0 ];then
    #         write_one_secure $oneSecureKey
    #     fi
    #     # 状态设置为1
    #     write_status=1
    fi
}

test_main() {
    init
    check_secure_file_inode

}

main() {
    # 初始化
    init
    # 内容检查
    check
    start_read_file
    log_info "[main] watch secure startd"
    watch_file
}

main

到此这篇关于Bash脚本实现实时监测登录的文章就介绍到这了,更多相关Bash脚本监测登录内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Linux 字段连接 join 命令使用小结

    Linux 字段连接 join 命令使用小结

    join命令是Linux系统中的一个文本处理工具,它用于将两个文件的行按照共同的字段连接起来,这篇文章主要介绍了Linux字段连接join命令使用指南,需要的朋友可以参考下
    2023-06-06
  • Hadoop单机版和全分布式(集群)安装

    Hadoop单机版和全分布式(集群)安装

    Hadoop,分布式的大数据存储和计算, 免费开源,本文介绍Hadoop单机版、集群安装步骤。
    2013-10-10
  • linux上搭建solr的实现方法(用jetty部署)

    linux上搭建solr的实现方法(用jetty部署)

    下面小编就为大家分享一篇linux上搭建solr的实现方法(用jetty部署),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • shell 编写一个带有进度条的程序安装脚本

    shell 编写一个带有进度条的程序安装脚本

    这篇文章主要介绍了shell 编写一个带有进度条的程序安装脚本,通过使用Shell脚本,我们可以轻松地实现命令行中的进度条功能,从而提高工作效率,感兴趣的可以了解一下
    2023-08-08
  • 一些你必须要熟练掌握的git命令

    一些你必须要熟练掌握的git命令

    git 现在的火爆程度非同一般,它被广泛地用在大型开源项目,团队开发,以及独立开发者,甚至学生之中。下面这篇文章主要给大家分享了一些你必须要熟练掌握的git命令,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧。
    2018-02-02
  • shell中的curl网络请求的实现

    shell中的curl网络请求的实现

    本文主要介绍了shell中的curl网络请求的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • shell脚本批量将文件复制到指定的文件夹下

    shell脚本批量将文件复制到指定的文件夹下

    本文主要介绍了shell脚本批量将文件复制到指定的文件夹下,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • 深入浅出Shell编程 Shell变量介绍

    深入浅出Shell编程 Shell变量介绍

    先不要管Shell的版本,来看看Shell 变量,在Shell中有三种变量:系统变量,环境变量,用户变量。其中用户变量在编程过程中使用最多,系统变量在对参数判断和命令返回值判断会使用,环境变量主要是在程序运行的时候需要设置。
    2013-01-01
  • linux Shell获取某目录下所有文件夹的名称

    linux Shell获取某目录下所有文件夹的名称

    这篇文章主要介绍了linux Shell获取某目录下所有文件夹的名称,需要的朋友可以参考下
    2017-05-05
  • linux shell实现折线图代码实例

    linux shell实现折线图代码实例

    这篇文章主要给大家介绍了关于linux shell实现折线图的相关资料,文中通过代码介绍的非常详细,对大家学习或者使用shell具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-12-12

最新评论