翼度科技»论坛 编程开发 .net 查看内容

运维脚本: 实时监测登录

5

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15
引言

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

  • 安全性:通过监控登录日志,可以迅速发现恶意登录、暴力破解等异常行为。
  • 合规性:确保满足各种合规要求,记录所有用户的登录行为。
解决方案概述

  • 监控目标:关注登录日志中的关键信息,例如登录时间、IP 地址、用户名、登录方式等。
  • 技术选型:通过编写 Bash 脚本,结合inotify、awk、grep 等工具,来实现对日志文件的实时监控与分析。
脚本实现原理

  • 实时监控:利用 inotify 命令动态监控日志文件的变动,并结合 sed 命令实时提取和输出新增的登录日志。
  • 日志筛选:通过 grep 等工具过滤出登录失败、异常登录等相关信息。
  • 报警机制:脚本可以配置成在监控到异常行为时,自动发送通知邮件
脚本示例
  1.   1 #!/bin/bash
  2.   2 # 作者: 阿杰
  3.   3 # 用途: 实时检测登录日志,统计异常登录
  4.   4 # 脚本名称: watch_secure.sh
  5.   5 # 用法: bash watch_seacure.sh
  6.   6
  7.   7 # 日志记录
  8.   8 log_err() {
  9.   9   printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: \033[31mERROR: \033[0m$@\n"
  10. 10 }
  11. 11
  12. 12 log_info() {
  13. 13   printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: \033[32mINFO: \033[0m$@\n"
  14. 14 }
  15. 15
  16. 16 log_warning() {
  17. 17   printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: \033[33mWARNING: \033[0m$@\n"
  18. 18 }
  19. 19
  20. 20 # 初始化Map
  21. 21 declare -A secureMap
  22. 22
  23. 23 init() {
  24. 24     # 行数记录文件
  25. 25     line_file_name="conf/line_file.txt"   
  26. 26     # inode存储文件
  27. 27     inode_file="conf/inode.txt"
  28. 28     # 认证失败文件记录
  29. 29     ssh_auth_failed_file="conf/ssh_auth_failed.csv"
  30. 30
  31. 31     # 文件列表
  32. 32     file_array=("$line_file_name" "$inode_file" "$ssh_auth_failed_file")
  33. 33     # inode 文件状态
  34. 34     inode_file_status=0
  35. 35     # 控制是否进行写入 0为可写,1为不可写
  36. 36     write_status=1
  37. 37
  38. 38     oneSecureKey=""
  39. 39
  40. 40     {   
  41. 41         if [ ! -d "conf" ];then
  42. 42             mkdir conf
  43. 43         fi
  44. 44         # 检查文件是否存在
  45. 45         for file in ${file_array[@]};do
  46. 46             check_file_exists $file
  47. 47         done
  48. 48         line=$(cat $line_file_name)
  49. 49         if [ -z "$line" ];then
  50. 50             line=0
  51. 51         fi
  52. 52         # 认证失败文件第一次创建
  53. 53         if [ $(wc -l < $ssh_auth_failed_file) -eq 0 ];then
  54. 54             # 时间以月天为单位(None为空账号或不存在账号)
  55. 55             echo "登录认证失败时间,源IP地址,登录账号,连接认证失败次数" > $ssh_auth_failed_file
  56. 56         fi
  57. 57
  58. 58     }
  59. 59
  60. 60     file_name="/var/log/secure"
  61. 61     if [ -z "$(rpm -qa | grep 'inotify-tools')" ];then
  62. 62         yum install -y inotify-tools > /dev/null 2>&1
  63. 63         if [ $? -ne 0 ];then
  64. 64             log_err "[init] inotify-tools 安装失败!"
  65. 65         fi
  66. 66     fi
  67. 67
  68. 68
  69. 69 }
  70. 70 # 检查文件是否存在,不存在则创建
  71. 71 check_file_exists() {
  72. 72     local file_name=$1
  73. 73     if [ ! -f "$file_name" ];then
  74. 74         touch $file_name
  75. 75         if [ $? -ne 0 ];then
  76. 76             log_err "[check_file_exists] file: $file_name 文件创建失败!"
  77. 77         fi
  78. 78     fi
  79. 79 }
  80. 80
  81. 81
  82. 82
  83. 83 # 监听文件事件
  84. 84 watch_file() {
  85. 85     inotifywait -mrq --format '%e' --event create,delete,modify $file_name | while read event ;do
  86. 86         case "$event" in
  87. 87         MODIFY)
  88. 88             start_read_file
  89. 89         ;;
  90. 90         # 文件被删除或重新创建
  91. 91         CREATE|DELETE)
  92. 92             # 重置文件行数
  93. 93             line=0
  94. 94             > $line_file_name
  95. 95             check
  96. 96         ;;
  97. 97         *)
  98. 98             log_warning "[watch_file] watch file event: $event"
  99. 99         ;;
  100. 100         esac
  101. 101     done
  102. 102 }
  103. 103
  104. 104 # 只读一行
  105. 105 read_line_file() {
  106. 106     ((line++))
  107. 107     echo $line > $line_file_name
  108. 108     # 不是指定数据退出
  109. 109     if [ $(sed -n "$line p" $file_name  | grep 'pam_unix(sshd:auth): authentication failure;' | wc -l ) -ne 1 ];then
  110. 110         return
  111. 111     fi
  112. 112     # 控制是否进行写入
  113. 113     write_status=0
  114. 114     oneSecureKey=$(sed -n "$line p" $file_name  |awk -v dateNow=$(date +"%Y") '{
  115. 115         split($0,rhost,"rhost=")
  116. 116         split(rhost[2],rhost," ")
  117. 117         split($0,user," user=")
  118. 118         if (length(user[2])==0) {
  119. 119             user[2]="None"
  120. 120         }
  121. 121         print dateNow":"$1":"$2","rhost[1]","user[2]
  122. 122     }')
  123. 123     log_info "[read_line_file] line: $line data:[$oneSecureKey]"
  124. 124     
  125. 125     send_map $oneSecureKey
  126. 126 }
  127. 127
  128. 128 # 往MAP中塞入数据
  129. 129 send_map() {
  130. 130     local key=$1
  131. 131     if [ -n ${secureMap[$key]} ];then
  132. 132         secureMap[$key]=`expr ${secureMap[$key]} + 1`
  133. 133     else
  134. 134         secureMap[$key]=1
  135. 135     fi
  136. 136 }
  137. 137
  138. 138 wirte_all_secure() {
  139. 139     for key in ${!secureMap[@]};do
  140. 140         write_one_secure $key
  141. 141     done
  142. 142 }
  143. 143
  144. 144 write_one_secure() {
  145. 145     local key="$@"
  146. 146     local data=$(grep -w -n "$key" $ssh_auth_failed_file)
  147. 147     if [ -n "$data" ];then
  148. 148         local i=$(echo $data | awk -F: '{print $1}')
  149. 149         local a=$(echo $data | awk -F, '{print $NF}')
  150. 150         sed -i "${i} s#$a#${secureMap[$key]}#" $ssh_auth_failed_file
  151. 151         if [ $? -ne 0 ];then
  152. 152             log_err "[write_secure] 写 $ssh_auth_failed_file 文件失败! data:[$key,${secureMap[$key]}]"
  153. 153         fi
  154. 154     else
  155. 155         # 新数据
  156. 156         echo "$key,${secureMap[$key]}" >> $ssh_auth_failed_file
  157. 157         if [ $? -ne 0 ];then
  158. 158             log_err "[write_secure] 写 $ssh_auth_failed_file 文件失败! data:[$key,${secureMap[$key]}]"
  159. 159         fi
  160. 160     fi
  161. 161     log_info "[write_secure] line: $line status: $write_status data:[$key,${secureMap[$key]}]"
  162. 162 }
  163. 163
  164. 164
  165. 165
  166. 166 # 启动前应先检查是否读取过
  167. 167 check() {
  168. 168     # 检查预存Inode是否一致
  169. 169     check_secure_file_inode
  170. 170 }
  171. 171
  172. 172 # 检查登录日志Inode是否一致
  173. 173 check_secure_file_inode() {
  174. 174     inode=$(ls -i $file_name | awk '{print $1}')
  175. 175     inode_file_data="$(cat $inode_file)"
  176. 176     if [ -n "$inode_file_data" ]; then
  177. 177         if [ $inode -ne $inode_file_data ];then
  178. 178             log_warning "[check_secure_file_inode] secure file inode is inconsistency"
  179. 179             # inode不一致,重置
  180. 180             echo "$inode" > $inode_file
  181. 181             inode_file_status=1
  182. 182         else
  183. 183            inode_file_status=0
  184. 184         fi
  185. 185     else
  186. 186         # 第一次读取
  187. 187         echo "$inode" > $inode_file
  188. 188         inode_file_status=1
  189. 189     fi
  190. 190 }
  191. 191
  192. 192 # 开始读取文件
  193. 193 start_read_file() {
  194. 194     # 第一次读取
  195. 195     if [ $inode_file_status -eq 1 ] ;then
  196. 196         # 使用循环将历史内容读取
  197. 197         while true;do
  198. 198             if [ $line -eq $(wc -l < $file_name) ];then
  199. 199                 break
  200. 200             fi
  201. 201             read_line_file
  202. 202         done
  203. 203         wirte_all_secure
  204. 204     elif [  $line -ne $(wc -l < $file_name) ];then
  205. 205         # 使用循环将行数对齐
  206. 206         while true;do
  207. 207             if [ $line -eq $(wc -l < $file_name) ];then
  208. 208                 break
  209. 209             fi
  210. 210             read_line_file
  211. 211             if [ $write_status -eq 0 ];then
  212. 212                 write_one_secure $oneSecureKey
  213. 213             fi
  214. 214             # 状态设置为1
  215. 215             write_status=1
  216. 216         done        
  217. 217     # else
  218. 218     #     read_line_file
  219. 219     #     if [ $write_status -eq 0 ];then
  220. 220     #         write_one_secure $oneSecureKey
  221. 221     #     fi
  222. 222     #     # 状态设置为1
  223. 223     #     write_status=1
  224. 224     fi
  225. 225 }
  226. 226
  227. 227 test_main() {
  228. 228     init
  229. 229     check_secure_file_inode
  230. 230
  231. 231 }
  232. 232
  233. 233 main() {
  234. 234     # 初始化
  235. 235     init
  236. 236     # 内容检查
  237. 237     check
  238. 238     start_read_file
  239. 239     log_info "[main] watch secure startd"
  240. 240     watch_file
  241. 241 }
  242. 242
  243. 243 main
复制代码
 

来源:https://www.cnblogs.com/chang157122/p/18574033
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具