β

大神教你DIY高性能运维堡垒体系

运维军团 109 阅读

概述

不怕出问题,就怕出问题找不到原因
运维团队一般会有个需求就是记录运维或者开发同事在服务器上的操作记录,比如进行一些常规审核或者是服务器被黑了、服务器日志被删的情况需要知道发生过什么事情,今天和大家分享下我们现在的服务器的shell和mysql操作日志记录的DIY方案。
团队内部之前有测试过一些堡垒机硬件,但终端操作方面不够人性化,不够灵活,而且价格昂贵,硬件容易形成单点故障。当然也接触过一些开源的方案,比如可以直接用ttyrec对终端进行录制,并且支持文本匹配,但是在实际使用中发现过严重bug,还有另外一些openssh的修改方案也不尽人意。
鉴于上述问题,我们针对bash和mysql的代码进行简单的修改来实现一个低成本、实用性能高的日志审计方案。
蹦跶~ 先上两张效果图
服务器日志:
远程日志中心web后台:
上面截图前面一部分是mysql的操作日志,后面部分是shell操作日志。具体解决方案请往下走

解决方案

整体架构如下图:

下面来“开源”这个解决方案,希望对大家有小小帮助。


1.linux bash审计

大家应该有听说过网络说的bash修改方案,我们从2011年开始使用,中间经历过很多bug,修复和优化过多次版本,下面会详细地给出我们现在的线上方案。现在的功能支持大致如下:
  • 同一系统用户精确到具体人员的shell操作记录
  • 支持远程通过ssh IP “command”执行和scp时候的日志记录
  • 支持不同系统用户进行切换时候能继续记录日志
  • 新支持mysql的操作日志
上述每一个功能列表都是经过多次实践出来的需求,虽然不是非常完美,但是如果不是刻意来逃避日志记录的话,基本可以满足大家的需求,上述的记录对应的人员是指多个人同时使用同一个系统帐号的情况,比如root帐号。

1.1 基本功能实现

基本功能就是需要记录到每个人的操作记录,网络上有个方案雏形,修改bashhist.c文件,701行左右修改bash_syslog_history函数,修改完之后内容:
然后重新编译安装即可。
上面取的是NAME_OF_KEY这个系统变量,我们称之为指纹,用这个变量来对应到具体的人员,然后将对应的操作记录到syslog。如果没有取到这个变量的话,/var/log/messages那里这个变量就显示为空了,只知道是某个系统帐号在执行,但无法精确到个人。

1.2. 指纹变量处理

接下来重点就是处理NAME_OF_KEY这个指纹变量,原理也比较简单,每个人登录系统的时候,我们让他自动执行一个脚本,然后设置这个变量为具体人就可以了。
——–
别说有人还在利用密码登录Linux服务器,太不专业了-_-
——–
在这个文件里面~/.ssh/authorized_keys加key的时候,第三列设置为具体的人员,我们是用工号@姓名拼音的模式,然后通过脚本进行处理即可。
脚本路径 /etc/bash_ywjt,内容:
上面的逻辑比较简单,首先我们还需要开启sshd的debug模式,在/etc/ssh/sshd_config文件加入:
还可以针对复杂的情况进一步的进行逻辑处理,比如su进行用户切换的时候,核心思想是跟踪PID变量,跟踪的变量主要是/var/log/secure里面的sshd[ID_NUM]里面的关键词和ps –ef|grep ID_NUM显示的第一二列的ID号,进行不断的匹配跟踪即可找到最原始的是哪个ID号。
然后在/etc/profile里面进行加载:
不过这样还不够,我们需要支持远程执行时候也记录的话就需要在~/.bashrc文件里面再加入一行,注意不能放在~/.bash_profile,两个文件虽然都是加载用户脚本,但是有差异的。在里面加入的内容:
这个逻辑是BASH_EXECUTION_STRING这个变量在本地执行和远程执行时候是不一样的,我们先进行变量判断,然后再做对应的处理即可,加完了就会发现远程执行时候也有日志记录了(马赛克处是来源IP):
这样就基本完成了shell操作记录的核心功能。

2. Mysql操作日志

很早以前找过相关的mysql插件,也尝试过audit之类的方案,但结果不是我们需要的效果,我们需要的是运维方面在服务器上的mysql操作,和mysql的binlog等日志不是同一个事情,而且和.mysql_history记录的也不一样,我们需要精确到同一系统用户的不同人员。
以下mysql版本是指Percona-Server-5.5。

2.1 初步解决

mysql自带了syslog日志功能,但是需要手动配置开启,配置比较简单:
在/etc/my.cnf里面的client字段加上syslog即可。
效果看起来也还满意,在/var/log/messages会有相关日志:
但是这样会存在三个问题

1)在mysqldump时候会报错:

2)可以轻易地绕过这个日志,在敲mysql命令行的时候加个参数–no-defaults即可。
3)日志里面只有是root帐号操作的,没有体现出具体是某个人操作的。
解决这几个问题还得靠开源的优势进行代码修改。

2.2 源码开启

我们可以在源码里面就把syslog这个开关开启,比较容易,找到client/mysql.cc这个文件,开关逻辑比较简单,找到以下代码:
看意思这里opt_syslog值就是个开关,wirte_syslog就是功能函数,找到static my_bool定义那里,把opt_syslog的bool值改为1,然后重新编译即可。
这样把上面的前面两个问题解决了。

2.3 交互式记录

单纯那样改会发现还有个小问题,就是在shell终端下面直接mysql可以用-e进行命令操作,比如:
但是按照之前那样开启syslog也无法记录日志。我们是有记录shell操作记录的,这个问题可以忽略,不过一定要显示的话也是有办法的,继续修改代码。
稍微看下逻辑分析可以看到是需要满足connect_flag == CLIENT_INTERACTIVE才写日志,找到CLIENT_INTERACTIVE的定义:
原来这个就是交互模式的定义,所以我们把这个“与”条件去掉即可,改为这样:
然后再重新编译,发现顺利解决msyql –e执行命令的历史记录了。

2.4 海量日志问题

在实际环境中会有新的问题,比如导入sql语句时候,会生成同样大小的日志,比如导入2G的sql,会生成2G的日志,这样明显不符合我们的需求。
想到我们已经有bash审核了,-e执行时候可以忽略记录,但是如果在mysql里面通过source命令引用sql语句时候同样有这个问题,所以还得继续改代码。
找到write_syslog函数,正式写日志时候是用的syslog函数,里面有个for循环的逻辑,意思是当sql语句很大时候,需要“切割”一下再写入,所以从这里入手,把syslog改为定义的MAX_SYSLOG_MESSAGE长度之内就写,超过的话就直接忽略。
另外之前说需要精确到不同人员,所以我们引入了我们的bash审核里面的指纹,变量NAME_OF_KEY,然后在mysql.cc里面引入即可。关键修改如下:
搞定,这样导入一个2G的sql语句,生成不到2m的日志,一些sql数据的话就忽略截断了。

2.5 自定义参数

这样虽然是在源码里面写死了一定有日志,但是还是可以提供一个备用的参数来取消这个功能。
在参数定义那里改动,把之前的syslog改为这样:
这样就是一个no-syslog的取消开关了,用法就是在my.cnf里面添加字段:
这段修改是可选的,可以忽略。

3. 远程日志中心

上述日志全部是通过syslog服务记录到/var/log/messages文件,更合理的是再传输到远程的日志中心来统一备案管理。
这个方法比较简单,在/etc/rsyslog.conf里面加入配置:
重启rsyslog服务之后,所有的日志就会同时发送一份到LOGSERVER_IP这个服务器,这里之前另外有个bash版本是内嵌了日志发送的功能,用的udp协议,不会对命令操作有卡顿,不过没用在线上。
最后我们在日志服务器可以搭建个splunk或者开源的logstash日志分析平台即可。关于日志系统,后续我们再详细介绍下我们现在的CDN日志系统。

4. 内网日志拦截

这个段落是额外的参考,我们的定制系统是写死了配置全部发送到公网的某一台日志中心服务器,但是我们内网机房也有很多服务器,这样会导致在日志中心那里无法查看原始的内网IP,只有办公网的出口IP,而且不方便每个机器都去更改日志中心的IP,那样会很容易漏掉,解决办法是进行“日志劫持”。
在我们的juniper防火墙那里进行日志拦截,然后转发到内网的一个日志中心即可,参考配置:
这样是在办公网搭建了另外一个日志中心服务器,拦截转发之后也就可以识别到具体的来源的内网IP了。

总结

这个远程日志中心平台是挺有必要搭建一个,像有时候服务器上不去了,我们可以上这个日志中心进行日志查询,看发生什么事情了,另外就是假如机器被别人拿到权限了,我们可以在这里看到原始日志。当然我们机器是都安装了ossec和lynis会进行安全系统层的安全扫描,不过保留一份原始的日志是必不可少的。
END
作者:运维军团
运维技术与开源架构交流
原文地址:大神教你DIY高性能运维堡垒体系, 感谢原作者分享。