cleanup
This commit is contained in:
47
waf3.py
47
waf3.py
@@ -12,36 +12,45 @@ import yaml
|
|||||||
from peewee import fn
|
from peewee import fn
|
||||||
from rich import print
|
from rich import print
|
||||||
|
|
||||||
|
|
||||||
base_path = Path('/var/opt/waf')
|
base_path = Path('/var/opt/waf')
|
||||||
conf_file = base_path / 'config.yml'
|
conf_file = base_path / 'config.yml'
|
||||||
db_path = base_path / 'waf.db'
|
|
||||||
|
|
||||||
if conf_file.exists():
|
if conf_file.exists():
|
||||||
conf = yaml.safe_load(conf_file.text())
|
conf = yaml.safe_load(conf_file.text())
|
||||||
else:
|
else:
|
||||||
conf = {
|
conf = {
|
||||||
'vroots': "/srv",
|
'vroots': "/srv",
|
||||||
|
'whitelist_ips': [],
|
||||||
|
'date_range': 'last_hour',
|
||||||
|
'purge_older_than': 'three_days',
|
||||||
|
'db_filename': 'waf.db',
|
||||||
}
|
}
|
||||||
conf_file.touch()
|
conf_file.touch()
|
||||||
yaml.dump(conf, conf_file.open('w'))
|
yaml.dump(conf, conf_file.open('w'))
|
||||||
# with open('names.yaml', 'w') as file:
|
|
||||||
|
# db_path = base_path / 'waf.db'
|
||||||
|
|
||||||
|
|
||||||
now = arrow.utcnow()
|
now = arrow.utcnow()
|
||||||
older_than = now.shift(days=-3).floor('day')
|
older_than = now.shift(days=-3).floor('day')
|
||||||
last_hour = now.shift(hours=-1).floor('hour')
|
last_hour = now.shift(hours=-1).floor('hour')
|
||||||
last_thirty_min = now.shift(minutes=-30)
|
last_thirty_min = now.shift(minutes=-30)
|
||||||
# last_period = last_thirty_min
|
|
||||||
last_period = last_hour
|
# Configuring
|
||||||
|
db_path = base_path / globals()[conf['db_filename']]
|
||||||
|
date_range = globals()[conf['date_range']]
|
||||||
vroots = Path(conf['vroots'])
|
vroots = Path(conf['vroots'])
|
||||||
logs = vroots.glob('*/logs/*access*.log')
|
logs = vroots.glob('*/logs/*access*.log')
|
||||||
whitelist_ips = conf['whitelist_ips']
|
whitelist_ips = conf['whitelist_ips']
|
||||||
|
|
||||||
|
# Database
|
||||||
db = SqliteExtDatabase(db_path, pragmas={'journal_mode': 'wal'})
|
db = SqliteExtDatabase(db_path, pragmas={'journal_mode': 'wal'})
|
||||||
|
|
||||||
class Attack(peewee.Model):
|
class Attack(peewee.Model):
|
||||||
ip = peewee.CharField(unique=True)
|
ip = peewee.CharField(unique=True)
|
||||||
host = peewee.CharField(index = True)
|
host = peewee.CharField(index = True)
|
||||||
date = peewee.DateTimeField(default=now.datetime)
|
date = peewee.DateTimeField(default=now.datetime)
|
||||||
# date = peewee.DateTimeField(default=datetime.datetime.now)
|
|
||||||
count = peewee.BigIntegerField()
|
count = peewee.BigIntegerField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -49,17 +58,16 @@ class Attack(peewee.Model):
|
|||||||
|
|
||||||
Attack.create_table(True)
|
Attack.create_table(True)
|
||||||
|
|
||||||
|
# CLI App
|
||||||
@click.group()
|
@click.group()
|
||||||
def cli():
|
def cli():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
async def nginx_reload():
|
async def nginx_reload():
|
||||||
returned_value = subprocess.call('/usr/bin/systemctl reload nginx', shell=True)
|
returned_value = subprocess.call('/usr/bin/systemctl reload nginx', shell=True)
|
||||||
if returned_value == 0:
|
if returned_value == 0:
|
||||||
click.echo(click.style('Nginx reloaded', fg="blue"))
|
click.echo(click.style('Nginx reloaded', fg="blue"))
|
||||||
|
|
||||||
|
|
||||||
async def get_denied():
|
async def get_denied():
|
||||||
denied = []
|
denied = []
|
||||||
for rule in ufw.get_rules().values():
|
for rule in ufw.get_rules().values():
|
||||||
@@ -67,11 +75,9 @@ async def get_denied():
|
|||||||
denied.append(rule.split(' ')[-1])
|
denied.append(rule.split(' ')[-1])
|
||||||
return denied
|
return denied
|
||||||
|
|
||||||
|
|
||||||
async def deny(ip):
|
async def deny(ip):
|
||||||
ufw.add('deny from ' + ip + ' to any', number=1)
|
ufw.add('deny from ' + ip + ' to any', number=1)
|
||||||
|
|
||||||
|
|
||||||
def undeny(ip):
|
def undeny(ip):
|
||||||
# Not async to avoid deleting wrong ufw rule.
|
# Not async to avoid deleting wrong ufw rule.
|
||||||
for key, rule in ufw.get_rules().items():
|
for key, rule in ufw.get_rules().items():
|
||||||
@@ -82,10 +88,9 @@ def undeny(ip):
|
|||||||
# if attack:
|
# if attack:
|
||||||
# attack.delete_instance()
|
# attack.delete_instance()
|
||||||
|
|
||||||
|
|
||||||
async def check(ip, host, date_position):
|
async def check(ip, host, date_position):
|
||||||
date = arrow.get(date_position,'DD/MMM/YYYY:HH:mm:ss')
|
date = arrow.get(date_position,'DD/MMM/YYYY:HH:mm:ss')
|
||||||
if date > last_period:
|
if date > date_range:
|
||||||
find = Attack.get_or_none(Attack.ip == ip)
|
find = Attack.get_or_none(Attack.ip == ip)
|
||||||
if find:
|
if find:
|
||||||
find.count = find.count + 1
|
find.count = find.count + 1
|
||||||
@@ -94,7 +99,6 @@ async def check(ip, host, date_position):
|
|||||||
data = {'ip': ip, 'date':date.datetime, 'host': host, 'count':1}
|
data = {'ip': ip, 'date':date.datetime, 'host': host, 'count':1}
|
||||||
Attack.create(**data)
|
Attack.create(**data)
|
||||||
|
|
||||||
|
|
||||||
checklist = [
|
checklist = [
|
||||||
{
|
{
|
||||||
'where': 'url',
|
'where': 'url',
|
||||||
@@ -111,11 +115,6 @@ checklist = [
|
|||||||
'in': "\\x00",
|
'in': "\\x00",
|
||||||
'store': 'suspects',
|
'store': 'suspects',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
'where': 'url',
|
|
||||||
'in': 'xmlrpc',
|
|
||||||
'store': 'suspects',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
'method': 'post',
|
'method': 'post',
|
||||||
'where': 'url',
|
'where': 'url',
|
||||||
@@ -145,7 +144,6 @@ async def scan(log):
|
|||||||
host = log.parent.parent.basename()
|
host = log.parent.parent.basename()
|
||||||
if ip not in whitelist_ips:
|
if ip not in whitelist_ips:
|
||||||
for rule in checklist:
|
for rule in checklist:
|
||||||
# print(rule)
|
|
||||||
where = url
|
where = url
|
||||||
if rule['where'] == 'url':
|
if rule['where'] == 'url':
|
||||||
where = url
|
where = url
|
||||||
@@ -154,24 +152,15 @@ async def scan(log):
|
|||||||
store = suspects
|
store = suspects
|
||||||
if 'in' in rule and rule['in'] in where:
|
if 'in' in rule and rule['in'] in where:
|
||||||
store.append(check(ip, host, date_position))
|
store.append(check(ip, host, date_position))
|
||||||
#if 'xmlrpc' not in where:
|
|
||||||
# print(host)
|
|
||||||
break
|
break
|
||||||
elif 'startswith' in rule and url.startswith(rule['startswith']) and 'notin' in rule and rule['notin'] not in url:
|
elif 'startswith' in rule and url.startswith(rule['startswith']) and 'notin' in rule and rule['notin'] not in url:
|
||||||
store.append(check(ip, host, date_position))
|
store.append(check(ip, host, date_position))
|
||||||
# print(2)
|
|
||||||
break
|
break
|
||||||
elif 'startswith' in rule and url.startswith(rule['startswith']):
|
elif 'startswith' in rule and url.startswith(rule['startswith']):
|
||||||
store.append(check(ip, host, date_position))
|
store.append(check(ip, host, date_position))
|
||||||
# print(3)
|
|
||||||
break
|
break
|
||||||
# elif 'login.php' in url and method == 'POST':
|
|
||||||
# if ip in suspects_login:
|
|
||||||
# suspects_login[ip].append( (ip, host, date_position) )
|
|
||||||
# else:
|
|
||||||
# suspects_login[ip] = [(ip, host, date_position),]
|
|
||||||
# elif 'wp-admin' in url and status not in ['200','302','499']:
|
# elif 'wp-admin' in url and status not in ['200','302','499']:
|
||||||
# suspects.append(check(ip, host, date_position))
|
# store.append(check(ip, host, date_position))
|
||||||
|
|
||||||
# def is_suspicious_login(item):
|
# def is_suspicious_login(item):
|
||||||
# return len(item[1]) > 18
|
# return len(item[1]) > 18
|
||||||
|
|||||||
Reference in New Issue
Block a user