近几年,云服务器迅速普及起来,但是安全问题频发
虽然安全措施基本都做了, 但是很多时候问题来的触不及防
所以监控服务器的登录情况,尽早发现异常登录
想到登录监控,要监控登录状态就想到从ssh入手,或者系统的last 或者 w
从ssh入手
但如果从阿里云服务器网页版控制台登录服务器的话,是不走ssh的,
所以ssh不够完美处理登录监控问题
用w命令
系统自带的w命令是很容易获得在线用户
但是只能获取到当前在线终端, 要通过对比获取到新增的登录就比较麻烦了
用last命令
用last可以获取到登录历史,
如果要通过对比获取到新增的登录的话,
得保存每次提取的最新记录
然后就是通知方式了, 想到了一下几种方式:
通过邮件发到邮箱,手机接收邮件
通过邮件发送到手机号绑定的139邮箱,以短信的形式接收
通过微信企业号,微信客户端接收
第一种方式效率很低,而且有点古老
第二种方式通过短信看邮件不大人性化,而且效率也不咋地
第三种方式,效率相对高,而且接收也方便
思路:
- 通过上一次上报的记录,获取新增的记录,并更新上报的最新记录
- 通过登录IP获取地理位置
- 通过企业号发到微信客户端
不多解析了, 直接上php脚本
<?php
//@version wzs 服务器登录警报
//记录最后登录信息
$lastFile = "/data/shell/lastlogin.time";
//企业号配置
$corpID = 'wx253036fe**********';
$corpSecret = 'Fft9orOhBVaIzn2aM3C1OG3bH25*******************************************';
$host = 'https://qyapi.weixin.qq.com';
$getAccessUri = "/cgi-bin/gettoken";
$sendMessageUri = "/cgi-bin/message/send";
if(file_exists($lastFile)){
$lastReport = @file_get_contents($lastFile);
}
$lastReport = rtrim($lastReport);
//最后一次上报
if ($lastReport){
$cmd = "last | grep -B 10 '{$lastReport}' | grep -v '{$lastReport}'";
}else{
$cmd = "last | head -n 10";
}
exec($cmd, $ret);
if (!empty($ret)){
//更新最新的登录
preg_match('/(.*?)(\d{2}:\d{2})/', $ret[0], $matches);
if (isset($matches[0])){
@file_put_contents($lastFile, $matches[0]);
}
//获取物理地址
foreach ($ret as &$t){
preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/', $t, $matches);
if (isset($matches[0])){
$cmd = "curl -s 'http://www.ip.cn/index.php?ip={$matches[0]}'";
unset($address);
exec($cmd, $address);
if (isset($address[0])){
preg_match('/来自:(\S*)/', $address[0], $matches);
$address[0] = isset($matches[0]) ? $matches[0] : "";
$t = $address[0] . "\n\t" . $t;
}
}
}
//发到微信企业号
$getAccessUrl = $host . $getAccessUri . "?corpid={$corpID}&corpsecret={$corpSecret}";
$accessToken = httpGet($getAccessUrl);
$token = json_decode($accessToken, true);
if (!isset($token['access_token'])){
exit("accessToken got failed");
}
$sendMessageUrl = $host . $sendMessageUri . "?access_token={$token['access_token']}";
$data = [
'touser' => 'wzs',
'toparty' => '1',
'totag' => '1',
'msgtype' => 'text',
'agentid' => 1,
'text' => [
"content" => implode("\n\n", $ret)
],
'safe' => 0
];
echo httpPost($sendMessageUrl, json_encode($data, JSON_UNESCAPED_UNICODE));
//print_r($accessToken);
}
function httpGet($url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60); //秒
$result = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
return $error ? $error : $result;
}
function httpPost($url, $params) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60); //秒
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //不验证证书,下同
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //
$result = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
return $error ? $error : $result;
}
然后在登录的时候执行即可:
在/etc/bashrc 最后加上 php /data/shell/safe.php > /dev/null
或者配置crontab即可:
* * * * * php /data/shell/safe.php > /dev/null &
* * * * * sleep 15; php /data/shell/safe.php > /dev/null &
* * * * * sleep 30; php /data/shell/safe.php > /dev/null &
* * * * * sleep 45; php /data/shell/safe.php > /dev/null &
安全,安全,安全,重要的事情说三遍
虽然阿里云盾也有异常登录警报,如果出现异地登录,会有短信警报的
但是呢, 亲力亲为,丰衣足食