232 lines
8.9 KiB
Python
232 lines
8.9 KiB
Python
import json
|
|
import os
|
|
import sys
|
|
import time
|
|
from datetime import datetime
|
|
|
|
if "/www/server/panel/class" not in sys.path:
|
|
sys.path.insert(0, "/www/server/panel/class")
|
|
|
|
os.chdir("/www/server/panel")
|
|
import public
|
|
# from mod.project.ssh.base import SSHbase
|
|
from mod.project.ssh.journalctlMod import JournalctlManage
|
|
from mod.project.ssh.secureMod import SecureManage
|
|
|
|
|
|
class main(JournalctlManage, SecureManage):
|
|
|
|
def __init__(self):
|
|
super(main,self).__init__()
|
|
|
|
def get_ssh_list(self, get):
|
|
"""
|
|
@name 获取日志列表
|
|
@param data:{"p":1,"limit":20,"search":"","select":"ALL"}
|
|
@return list
|
|
"""
|
|
page = int(get.p) if hasattr(get, 'p') else 1
|
|
limit = int(get.limit) if hasattr(get, 'limit') else 20
|
|
query = get.get("search", "").strip().lower()
|
|
history = get.get("historyType", "").strip().lower()
|
|
|
|
# 读取IP封禁规则
|
|
ip_rules_file = "data/ssh_deny_ip_rules.json"
|
|
try:
|
|
ip_rules = json.loads(public.readFile(ip_rules_file))
|
|
except Exception:
|
|
ip_rules = []
|
|
|
|
login_type = self.login_all_flag
|
|
get.select = get.get("select", "ALL")
|
|
if get.select == "Failed":
|
|
login_type = self.login_failed_flag
|
|
elif get.select == "Accepted":
|
|
login_type = self.login_access_flag
|
|
|
|
if history == "all":
|
|
self.ssh_log_path += "*"
|
|
total,login_list = self.get_secure_logs(login_type=login_type,pagesize=limit, page=page, query=query)
|
|
|
|
for log in login_list:
|
|
if log["address"] in ip_rules:
|
|
log["deny_status"] = 1
|
|
data = self.return_area(login_list, 'address')
|
|
return public.return_message(0, 0, {"data":data, "total":total})
|
|
|
|
def get_ssh_intrusion(self, get):
|
|
"""
|
|
@name 登陆详情统计 周期 昨天/今天 类型 成功/失败
|
|
@return {"error": 0, "success": 0, "today_error": 0, "today_success": 0}
|
|
"""
|
|
stats = {
|
|
'error': 0,
|
|
'success': 0,
|
|
'today_error': 0,
|
|
'today_success': 0,
|
|
'yesterday_error': 0,
|
|
'yesterday_success': 0,
|
|
'sevenday_error': 0,
|
|
'sevenday_success': 0
|
|
}
|
|
try:
|
|
from datetime import datetime, timedelta
|
|
|
|
# 获取并更新日志数据
|
|
today = datetime.now()
|
|
yesterday = today - timedelta(days=1)
|
|
|
|
osv = public.get_os_version().lower()
|
|
#个别系统使用标准时间格式
|
|
date_v1 = ["debian", "opencloudos"]
|
|
is_iso_date = any(d in osv for d in date_v1)
|
|
if is_iso_date:
|
|
# Debian/OpenCloudOS 日志为标准时间
|
|
today_str = today.strftime("%Y-%m-%d")
|
|
yesterday_str = yesterday.strftime("%Y-%m-%d")
|
|
else:
|
|
#centos ubuntu 等日志为月份日期
|
|
today_str = today.strftime("%b %d").replace(" 0", " ")
|
|
yesterday_str = yesterday.strftime("%b %d").replace(" 0", " ")
|
|
|
|
stats['today_error'] = self.get_secure_log_count(self.login_failed_flag, today_str)
|
|
stats['today_success'] = self.get_secure_log_count(self.login_access_flag, today_str)
|
|
stats['yesterday_success'] = self.get_secure_log_count(self.login_access_flag, yesterday_str)
|
|
stats['yesterday_error'] = self.get_secure_log_count(self.login_failed_flag, yesterday_str)
|
|
stats['sevenday_error'] = self.get_secure_log_count(self.login_failed_flag, "")
|
|
stats['sevenday_success'] = self.get_secure_log_count(self.login_access_flag, "")
|
|
|
|
self.ssh_log_path += "*"
|
|
stats['error'] = self.get_secure_log_count(self.login_failed_flag)
|
|
stats['success'] = self.get_secure_log_count(self.login_access_flag)
|
|
except Exception as e:
|
|
import traceback
|
|
public.print_log(f"Failed to get SSH login information: {traceback.format_exc()}")
|
|
return public.return_message(0, 0,stats)
|
|
|
|
def clean_ssh_list(self, get):
|
|
"""
|
|
@name 清空SSH登录记录 只保留最近一周的数据(从周日开始为一周)
|
|
@return: {"status": True, "msg": "清空成功"}
|
|
"""
|
|
|
|
public.ExecShell("rm -rf /var/log/secure-*;rm -rf /var/log/auth.log.*".format())
|
|
|
|
return public.return_message(0, 0, 'Clearance successful.')
|
|
|
|
def index_ssh_info(self, get):
|
|
"""
|
|
获取今天和昨天的SSH登录统计
|
|
@return: list [今天登录次数, 昨天登录次数]
|
|
"""
|
|
from datetime import datetime, timedelta
|
|
|
|
today_count = 0
|
|
yesterday_count = 0
|
|
|
|
try:
|
|
# 获取并更新日志数据
|
|
today = datetime.now()
|
|
yesterday = today - timedelta(days=1)
|
|
|
|
if "debian" in public.get_os_version().lower():
|
|
today_str = today.strftime("%Y-%m-%d")
|
|
yesterday_str = yesterday.strftime("%Y-%m-%d")
|
|
else:
|
|
today_str = today.strftime("%b %d").replace(" 0", " ")
|
|
yesterday_str = yesterday.strftime("%b %d").replace(" 0", " ")
|
|
|
|
today_count = self.get_secure_log_count(self.login_all_flag, today_str)
|
|
yesterday_count = self.get_secure_log_count(self.login_all_flag, yesterday_str)
|
|
except Exception as e:
|
|
import traceback
|
|
public.print_log(f"Failed to count SSH login information: {traceback.format_exc()}")
|
|
|
|
return [today_count, yesterday_count]
|
|
|
|
def add_cron_job(self,get):
|
|
"""
|
|
将 SSH爆破的脚本 添加到定时任务中
|
|
"""
|
|
cron_hour = get.get("cron_hour", 1)
|
|
fail_count = get.get("fail_count", 10)
|
|
ban_hour = get.get("ban_hour", 10)
|
|
public.print_log(f"{cron_hour},{fail_count},{ban_hour}")
|
|
cron_exist = public.M('crontab').where("name='aa-SSH Blast IP Blocking [Security - SSH Admin - Add to Login Logs]'", ()).get()
|
|
if len(cron_exist) > 0:
|
|
return public.return_message(-1, 0, 'Timed tasks already exist! Task details can be viewed in the panel scheduled tasks')
|
|
|
|
|
|
from time import localtime
|
|
run_minute = localtime().tm_min + 1
|
|
if run_minute == 60: run_minute = 0
|
|
|
|
get.name = "aa-SSH Blast IP Blocking [Security - SSH Admin - Add to Login Logs]"
|
|
get.type = "hour-n"
|
|
get.hour = cron_hour
|
|
get.minute = run_minute
|
|
get.where1 = cron_hour
|
|
get.where_hour = cron_hour
|
|
get.week = "1"
|
|
get.timeType = "sday"
|
|
get.timeSet = "1"
|
|
get.sType = "toShell"
|
|
get.sBody = "{path}/pyenv/bin/python3 -u {path}/script/ssh_ban_login_failed.py {cron_hour} {fail_count} {ban_second}".format(
|
|
path = public.get_panel_path(),
|
|
cron_hour = cron_hour,
|
|
fail_count = fail_count,
|
|
ban_second = ban_hour * 3600
|
|
)
|
|
get.sName = ""
|
|
get.backupTo = ""
|
|
get.save = ""
|
|
get.urladdress = ""
|
|
get.save_local = "0"
|
|
get.notice = "0"
|
|
get.notice_channel = ""
|
|
get.datab_name = ""
|
|
get.tables_name = ""
|
|
get.keyword = ""
|
|
get.flock = "1"
|
|
get.stop_site = "0"
|
|
get.version = ""
|
|
get.user = "root"
|
|
from crontab import crontab
|
|
|
|
res = crontab().AddCrontab(get)
|
|
if res["status"] == True:
|
|
return public.return_message(0, 0,"Added successfully, the task will run at {} minutes per {} hour.".format(cron_hour,run_minute))
|
|
public.set_module_logs('SSH', 'add_cron_job', 1)
|
|
return res
|
|
|
|
def remove_cron_job(self,get):
|
|
"""
|
|
将 SSH爆破的脚本 在定时任务中移除
|
|
"""
|
|
cron_exist = public.M('crontab').where("name='aa-SSH Blast IP Blocking [Security - SSH Admin - Add to Login Logs]'", ()).get()
|
|
if len(cron_exist) > 0:
|
|
for crontask in cron_exist:
|
|
get.id = crontask["id"]
|
|
from crontab import crontab
|
|
crontab().DelCrontab(get)
|
|
return public.return_message(0 ,0, 'Timed tasks have been removed!')
|
|
else:
|
|
return public.return_message(-1, 0, 'Removal failed, timed task does not exist!')
|
|
|
|
def run_ban_login_failed_ip(self,get):
|
|
hour = get.get("hour", 1)
|
|
fail_count = get.get("fail_count", 10)
|
|
ban_hour = get.get("ban_hour", 10)
|
|
|
|
exec_shell = "{path}/pyenv/bin/python3 -u {path}/script/ssh_ban_login_failed.py {hour} {fail_count} {ban_second}".format(
|
|
path=public.get_panel_path(),
|
|
hour=hour,
|
|
fail_count=fail_count,
|
|
ban_second=ban_hour * 3600
|
|
)
|
|
import panelTask
|
|
task_obj = panelTask.bt_task()
|
|
task_id = task_obj.create_task('SSH blocking and IP bursting programme', 0, exec_shell)
|
|
public.set_module_logs('SSH', 'run_ban_login_failed_ip', 1)
|
|
return {'status': True, 'msg': 'Task created.', 'task_id': task_id}
|