修改 | 2020 年 3 月 1 日 13:09

修改 | 2020 年 3 月 1 日 13:09

我在 Linux 中创建了一个服务 sshield,用于防止通过 ssh 进行的暴力攻击。我的服务已完成,一切运行良好。

但是...我看到了一个细节。这个服务消耗了太多的 CPU!

图片:服务器中的 sshield CPU

图片:桌面上的 sshield 的 CPU

它消耗了20.6%,太多了

我的服务在一秒钟内运行了一个无限循环。这会导致 CPU 占用如此之高吗?否则会是什么原因?

Github:https://github.com/cleanet/sshield
评论 sshield:https://www.youtube.com/watch?v=0rj4j7VqXXI

修改 | 2020 年 3 月 1 日 13:09

我编辑了脚本,删除了以下内容:

lineas_antiguas=$(wc -l /var/log/auth.log);
IFS=" " read -ra lineas_antiguas <<< $lineas_antiguas;

添加常量:

declare -r SSHIELD_LOG_FILE="/var/log/sshield.log"
declare -r AUTH_LOG_FILE="/var/log/auth.log"

并用它替换路径。另外,我将 while 循环替换为:

tail -F -n 0 "$AUTH_LOG_FILE" | while read line
do
   ...
done

并删除:

lineas=$(wc -l /var/log/auth.log);
IFS=" " read -ra lineas <<< $lineas;
linea_contenido=$(tail -n 1 /var/log/auth.log);

我的脚本已在我的 GITHUB 中更新

结果是,它不会消耗太多的 CPU 和内存 0.3% CPU 和 0.2% RAM

但是。为什么服务是重复的

答案1

如果我没看错的话,你是不断地/var/log/auth.log从头开始计算文件中的行数,并执行以下操作:

while [ TRUE ]
do

    lineas=$(wc -l /var/log/auth.log);
   ...
    ip_logueada=$(wc -l /var/log/auth.log | grep -E -o "[0-9]{1,9}")
   ....
done

因此,承受压力的不仅仅是 CPU,还有硬盘。

如果您确实必须从头开始处理日志文件来计算行数或收集统计数据,那么在脚本启动时只执行一次,不要循环重复此操作,这是浪费和不必要的。

你想要的是某种尾巴在你监视的文件上。因此,你可以使用类似下面的命令:

tail -n0 -F /var/log/auth.log | while read line
do
  echo "$line"
  # do something
done

此代码片段将在新行写入文件时回显它们。因此,您只需“监听”新行流、解析它们并跟踪有问题的 IP 地址。这种方法应该可以解决您的性能问题。

一点建议:对源文件和目标文件使用变量名。例如,/var/log/auth.log在代码中多次重复出现,也是如此/var/log/sshield.log

您可以在脚本开头添加一些变量,甚至将它们声明为常量(只读变量)像这样:

declare -r SOURCE_LOG_FILE="/var/log/auth.log"

然后你就可以简单地写:tail -n0 -F "$SOURCE_LOG_FILE"。这样就避免了重复。

我也会划分代码在一些功能块中。例如,您可以拥有:

  • 一个用于发送邮件的函数
  • 另一个函数是跟踪计数器:您传递一个 IP 地址,它会检查当前会话中记录了多少次违规,如果达到阈值,它会阻止该 IP 地址。

这将使代码更清晰,更易于维护。目前流程不太容易理解,代码到处都是。

你还应该有一个函数日志记录提醒到您的文件/var/log/sshield.log。您有很多重复如下代码:

echo "logged ip: $ip_logueada - $(date)" >> /var/log/sshield.log

创建一个函数,然后只需将要记录的文本作为参数传递,让函数添加时间戳并将文本写入文件,格式如您所愿。您可以通过摆脱以下代码来简化代码冗余

现在我不得不同意你正在重新发明轮子,有免费工具可以做更多、更高效。不过,这种练习对于教育目的来说很有好处。

相关内容