需求
运维工程师在工作中经常会遇到这样的问题:
这个时候,如果我们找不到始作俑者,那毫无疑问得运维自己背锅。如果有证据证明是别人干的,我们才能坦然地(甩锅)找到对应的人问清楚原因。这个时候,我们就需要做好服务器的命令审计。
下面,给大家介绍一种非常简单实用的服务器命令审计方式,设置一个命令审计日志系统,非常好用!
配置
我们只需要把这一段代码执行,就完成了配置:
# 创建目录和文件
sudo mkdir -p /var/log/cmd_audit
sudo touch /var/log/cmd_audit/audit.log
# 设置目录和文件权限
sudo chmod 755 /var/log/cmd_audit
sudo chmod 662 /var/log/cmd_audit/audit.log
# 设置文件仅允许追加属性
sudo chattr +a /var/log/cmd_audit/audit.log
# 写入内容到 /etc/profile.d/cmd_audit.sh
sudo tee /etc/profile.d/cmd_audit.sh > /dev/null << 'EOF'
################## Audit ##################
export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL
HISTTIMEFORMAT="%Y/%m/%d %T"; export HISTTIMEFORMAT
# 定义审计命令
audit_command='{ thisHistID=`history 1 | awk "{print \\$1}"`; lastCommand=`history 1 | awk "{\\$1=\"\"; print}"`; user=`id -un`; pwd=`pwd`; whoStr=(`who -u am i`); realUser=${whoStr[0]}; logMonth=${whoStr[2]}; logDay=${whoStr[3]}; logTime=${whoStr[4]}; pid=${whoStr[6]}; ip=${whoStr[7]}; if [ ${thisHistID}x != ${lastHistID}x ]; then echo -E `date "+%Y/%m/%d %H:%M:%S"` $user\($realUser\)@$ip[IP:$pid][PWD:$pwd][LOGIN:$logMonth $logDay $logTime] --- $lastCommand; lastHistID=$thisHistID; fi; } >> $HISTORY_FILE'
# 检查和设置 PROMPT_COMMAND
if [ -z "${PROMPT_COMMAND_READONLY}" ]; then
if [ -z "${PROMPT_COMMAND}" ]; then
export PROMPT_COMMAND="$audit_command"
else
export PROMPT_COMMAND="$PROMPT_COMMAND; $audit_command"
fi
export HISTORY_FILE=/var/log/cmd_audit/audit.log
export PROMPT_COMMAND_READONLY=1
readonly PROMPT_COMMAND_READONLY
fi
################## Audit_end ##############
EOF
# 使配置立即生效
source /etc/profile.d/cmd_audit.sh
复制代码
你可以直接复制后粘贴到服务器上,也可以执行下面这条命令帮你配置完成:
curl -s http://8.138.10.37/tools/setup_cmd_audit.sh | tee /tmp/setup_cmd_audit.sh && read -p "可以执行此文件吗? (y/n): " user_input && [ "$user_input" = "y" ] && bash /tmp/setup_cmd_audit.sh && rm /tmp/setup_cmd_audit.sh
复制代码
效果
执行后,登录到服务器上操作的命令行都会被记录到/var/log/audit/cmd_audit.log
,我们看看效果:
[root@devops ~]# tail -f /var/log/cmd_audit/audit.log
2024/07/21 19:11:32 root(root)@[IP:(172.30.0.254)][PWD:/root][LOGIN:2024-07-21 19:11 .] --- 2024/07/21 19:10:46 date
2024/07/21 19:11:38 root(root)@[IP:(172.30.0.254)][PWD:/root][LOGIN:2024-07-21 19:11 .] --- 2024/07/21 19:11:37 top
2024/07/21 19:11:40 root(root)@[IP:(172.30.0.254)][PWD:/root][LOGIN:2024-07-21 19:11 .] --- 2024/07/21 19:11:40 touch demo
2024/07/21 19:11:43 root(root)@[IP:(172.30.0.254)][PWD:/root][LOGIN:2024-07-21 19:11 .] --- 2024/07/21 19:11:43 rm -rf demo
# 这是root切换到jaywin用户
2024/07/21 19:11:59 jaywin(root)@[IP:(172.30.0.254)][PWD:/home/jaywin][LOGIN:2024-07-21 19:11 .] --- 2024/07/21 19:08:17 touch
2024/07/21 19:12:05 jaywin(root)@[IP:(172.30.0.254)][PWD:/home/jaywin][LOGIN:2024-07-21 19:11 .] --- 2024/07/21 19:12:05 touch somefile
复制代码
并且,这个审计文件只能追加,任何用户都无法修改,删除!只有超级管理员才能查看,其他普通用户都无法查看!
解释
这个设置的原理是通过配置特殊变量PROMPT_COMMAND
,在每次显示提示符之前执行指定的命令。简而言之,它允许你在每次命令提示符出现之前运行一段代码。这在审计、日志记录和其他自动化任务中非常有用。
接下来说明下具体原理,这里涉及到几个知识点,我们根据脚本的内容一一来讲:
# 下面的配置保证了审计文件只有管理员才有权限操作!
# 设置目录和文件权限
sudo chmod 755 /var/log/cmd_audit # 755表示目录权限是rwxr-xr-x,允许所有用户执行,以便在这个目录下的文件,能写入用户的命令
sudo chmod 662 /var/log/cmd_audit/audit.log # 622表示文件权限是-rw-rw--w-,不允许其他用户查看文件内容
# 设置文件仅允许追加属性
sudo chattr +a /var/log/cmd_audit/audit.log # chattr+a表示此文件仅允许追加操作,任何用户都无法修改文件内容或删除文件!
复制代码
以下是命令审计日志系统的重点解释:
export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL
复制代码
HISTTIMEFORMAT="%Y/%m/%d %T"; export HISTTIMEFORMAT
复制代码
audit_command='{ thisHistID=`history 1 | awk "{print \\$1}"`; lastCommand=`history 1 | awk "{\\$1=\"\"; print}"`; user=`id -un`; pwd=`pwd`; whoStr=(`who -u am i`); realUser=${whoStr[0]}; logMonth=${whoStr[2]}; logDay=${whoStr[3]}; logTime=${whoStr[4]}; pid=${whoStr[6]}; ip=${whoStr[7]}; if [ ${thisHistID}x != ${lastHistID}x ]; then echo -E `date "+%Y/%m/%d %H:%M:%S"` $user\($realUser\)@$ip[IP:$pid][PWD:$pwd][LOGIN:$logMonth $logDay $logTime] --- $lastCommand; lastHistID=$thisHistID; fi; } >> $HISTORY_FILE'
复制代码
thisHistID=`history 1 | awk "{print \\$1}"` # 获取当前历史ID
lastCommand=`history 1 | awk "{\\$1=\"\"; print}"` # 获取最后一条命令
user=`id -un`;pwd=`pwd` # 获取当前用户和当前路径
# 获取用户登录信息
whoStr=(`who -u am i`) # 用户登录信息
realUser=${whoStr[0]} # 用户名
logMonth=${whoStr[2]} # 登录时间
logDay=${whoStr[3]}
logTime=${whoStr[4]}
pid=${whoStr[6]} # 登录会话ID
ip=${whoStr[7]} # 登录的客户端IP
复制代码
if [ ${thisHistID}x != ${lastHistID}x ]; then
echo -E `date "+%Y/%m/%d %H:%M:%S"` $user\($realUser\)@$ip[IP:$pid][PWD:$pwd][LOGIN:$logMonth $logDay $logTime] --- $lastCommand
lastHistID=$thisHistID
fi
复制代码
if [ -z "${PROMPT_COMMAND_READONLY}" ]; then
if [ -z "${PROMPT_COMMAND}" ]; then
export PROMPT_COMMAND="$audit_command"
else
export PROMPT_COMMAND="$PROMPT_COMMAND; $audit_command"
fi
export HISTORY_FILE=/var/log/cmd_audit/audit.log
export PROMPT_COMMAND_READONLY=1
readonly PROMPT_COMMAND_READONLY
fi
复制代码
注意
你最好在服务器初始化时做好此项配置;
你最好结合用户权限管理系统来使用,才能真正发挥这个配置的功能;
下一期,我们会简单谈谈如何实现一个用户权限管理系统,敬请期待~
评论