mirror of
https://github.com/iio612/DEFENDER.git
synced 2026-02-13 19:24:23 +00:00
Code Refactoring
This commit is contained in:
142
core/base.py
142
core/base.py
@@ -2,17 +2,18 @@ import asyncio
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import json
|
import json
|
||||||
import time
|
|
||||||
import socket
|
import socket
|
||||||
import threading
|
import threading
|
||||||
import ipaddress
|
import ipaddress
|
||||||
import ast
|
import ast
|
||||||
import requests
|
import requests
|
||||||
|
import concurrent.futures
|
||||||
from dataclasses import fields
|
from dataclasses import fields
|
||||||
from typing import Any, Callable, Iterable, Optional, TYPE_CHECKING
|
from typing import Any, Awaitable, Callable, Optional, TYPE_CHECKING, Union
|
||||||
from base64 import b64decode, b64encode
|
from base64 import b64decode, b64encode
|
||||||
from sqlalchemy import create_engine, Engine, Connection, CursorResult
|
from sqlalchemy import create_engine, Engine, Connection, CursorResult
|
||||||
from sqlalchemy.sql import text
|
from sqlalchemy.sql import text
|
||||||
|
import core.definition as dfn
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.loader import Loader
|
from core.loader import Loader
|
||||||
@@ -36,12 +37,15 @@ class Base:
|
|||||||
# Liste des threads en cours
|
# Liste des threads en cours
|
||||||
self.running_threads: list[threading.Thread] = self.Settings.RUNNING_THREADS
|
self.running_threads: list[threading.Thread] = self.Settings.RUNNING_THREADS
|
||||||
|
|
||||||
# List of all async tasks
|
|
||||||
self.running_asynctasks: list[asyncio.Task] = self.Settings.RUNNING_ASYNCTASKS
|
|
||||||
|
|
||||||
# Les sockets ouvert
|
# Les sockets ouvert
|
||||||
self.running_sockets: list[socket.socket] = self.Settings.RUNNING_SOCKETS
|
self.running_sockets: list[socket.socket] = self.Settings.RUNNING_SOCKETS
|
||||||
|
|
||||||
|
# List of all asyncio tasks
|
||||||
|
self.running_iotasks: list[asyncio.Task] = self.Settings.RUNNING_ASYNC_TASKS
|
||||||
|
|
||||||
|
# List of all asyncio threads pool executors
|
||||||
|
self.running_iothreads: list[dfn.MThread] = self.Settings.RUNNING_ASYNC_THREADS
|
||||||
|
|
||||||
# Liste des fonctions en attentes
|
# Liste des fonctions en attentes
|
||||||
self.periodic_func: dict[object] = self.Settings.PERIODIC_FUNC
|
self.periodic_func: dict[object] = self.Settings.PERIODIC_FUNC
|
||||||
|
|
||||||
@@ -71,7 +75,6 @@ class Base:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def __get_latest_defender_version(self) -> None:
|
def __get_latest_defender_version(self) -> None:
|
||||||
try:
|
|
||||||
self.logs.debug(f'-- Looking for a new version available on Github')
|
self.logs.debug(f'-- Looking for a new version available on Github')
|
||||||
token = ''
|
token = ''
|
||||||
json_url = f'https://raw.githubusercontent.com/adator85/DEFENDER/main/version.json'
|
json_url = f'https://raw.githubusercontent.com/adator85/DEFENDER/main/version.json'
|
||||||
@@ -80,17 +83,18 @@ class Base:
|
|||||||
'Accept': 'application/vnd.github.v3.raw' # Indique à GitHub que nous voulons le contenu brut du fichier
|
'Accept': 'application/vnd.github.v3.raw' # Indique à GitHub que nous voulons le contenu brut du fichier
|
||||||
}
|
}
|
||||||
|
|
||||||
|
with requests.Session() as sess:
|
||||||
|
try:
|
||||||
if token == '':
|
if token == '':
|
||||||
response = requests.get(json_url, timeout=self.Config.API_TIMEOUT)
|
response = sess.get(json_url, timeout=self.Config.API_TIMEOUT)
|
||||||
else:
|
else:
|
||||||
response = requests.get(json_url, headers=headers, timeout=self.Config.API_TIMEOUT)
|
response = sess.get(json_url, headers=headers, timeout=self.Config.API_TIMEOUT)
|
||||||
|
|
||||||
response.raise_for_status() # Vérifie si la requête a réussi
|
response.raise_for_status() # Vérifie si la requête a réussi
|
||||||
json_response:dict = response.json()
|
json_response:dict = response.json()
|
||||||
# self.LATEST_DEFENDER_VERSION = json_response["version"]
|
self.Config.LATEST_VERSION = json_response.get('version', '')
|
||||||
self.Config.LATEST_VERSION = json_response['version']
|
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
except requests.HTTPError as err:
|
except requests.HTTPError as err:
|
||||||
self.logs.error(f'Github not available to fetch latest version: {err}')
|
self.logs.error(f'Github not available to fetch latest version: {err}')
|
||||||
except:
|
except:
|
||||||
@@ -359,8 +363,8 @@ class Base:
|
|||||||
except Exception as err:
|
except Exception as err:
|
||||||
self.logs.error(err, exc_info=True)
|
self.logs.error(err, exc_info=True)
|
||||||
|
|
||||||
def create_asynctask(self, func: Any, *, async_name: str = None, run_once: bool = False) -> asyncio.Task:
|
def create_asynctask(self, func: Callable[..., Awaitable[Any]], *, async_name: str = None, run_once: bool = False) -> Optional[asyncio.Task]:
|
||||||
"""Create a new asynchrone and store it into running_asynctasks variable
|
"""Create a new asynchrone and store it into running_iotasks variable
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
func (Callable): The function you want to call in asynchrone way
|
func (Callable): The function you want to call in asynchrone way
|
||||||
@@ -379,26 +383,71 @@ class Base:
|
|||||||
|
|
||||||
task = asyncio.create_task(func, name=name)
|
task = asyncio.create_task(func, name=name)
|
||||||
task.add_done_callback(self.asynctask_done)
|
task.add_done_callback(self.asynctask_done)
|
||||||
self.running_asynctasks.append(task)
|
self.running_iotasks.append(task)
|
||||||
|
|
||||||
self.logs.debug(f"++ New asynchrone task created as: {task.get_name()}")
|
self.logs.debug(f"=== New IO task created as: {task.get_name()}")
|
||||||
return task
|
return task
|
||||||
|
|
||||||
def asynctask_done(self, task: asyncio.Task):
|
async def create_thread_io(self, func: Callable[..., Any], *args, run_once: bool = False, thread_flag: bool = False) -> Optional[Any]:
|
||||||
|
"""Run threads via asyncio.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
func (Callable[..., Any]): The blocking IO function
|
||||||
|
run_once (bool, optional): If it should be run once.. Defaults to False.
|
||||||
|
thread_flag (bool, optional): If you are using a endless loop, use the threading Event object. Defaults to False.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Any: The final result of the blocking IO function
|
||||||
|
"""
|
||||||
|
if run_once:
|
||||||
|
for iothread in self.running_iothreads:
|
||||||
|
if func.__name__.lower() == iothread.name.lower():
|
||||||
|
return None
|
||||||
|
|
||||||
|
with concurrent.futures.ThreadPoolExecutor(max_workers=1, thread_name_prefix=func.__name__) as executor:
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
largs = list(args)
|
||||||
|
thread_event: Optional[threading.Event] = None
|
||||||
|
if thread_flag:
|
||||||
|
thread_event = threading.Event()
|
||||||
|
thread_event.set()
|
||||||
|
largs.insert(0, thread_event)
|
||||||
|
|
||||||
|
future = loop.run_in_executor(executor, func, *tuple(largs))
|
||||||
|
future.add_done_callback(self.asynctask_done)
|
||||||
|
|
||||||
|
id_obj = self.Loader.Definition.MThread(
|
||||||
|
name=func.__name__,
|
||||||
|
thread_id=list(executor._threads)[0].native_id,
|
||||||
|
thread_event=thread_event,
|
||||||
|
thread_obj=list(executor._threads)[0],
|
||||||
|
executor=executor,
|
||||||
|
future=future)
|
||||||
|
|
||||||
|
self.running_iothreads.append(id_obj)
|
||||||
|
self.logs.debug(f"=== New thread started {func.__name__} with max workers set to: {executor._max_workers}")
|
||||||
|
result = await future
|
||||||
|
|
||||||
|
self.running_iothreads.remove(id_obj)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def asynctask_done(self, task: Union[asyncio.Task, asyncio.Future]):
|
||||||
"""Log task when done
|
"""Log task when done
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
task (asyncio.Task): The Asyncio Task callback
|
task (asyncio.Task): The Asyncio Task callback
|
||||||
"""
|
"""
|
||||||
|
name = task.get_name() if isinstance(task, asyncio.Task) else "Thread"
|
||||||
|
task_or_future = "Task" if isinstance(task, asyncio.Task) else "Future"
|
||||||
try:
|
try:
|
||||||
if task.exception():
|
if task.exception():
|
||||||
self.logs.error(f"[ASYNCIO] Task {task.get_name()} failed with exception: {task.exception()}")
|
self.logs.error(f"[ASYNCIO] {task_or_future} {name} failed with exception: {task.exception()}")
|
||||||
else:
|
else:
|
||||||
self.logs.debug(f"[ASYNCIO] Task {task.get_name()} completed successfully.")
|
self.logs.debug(f"[ASYNCIO] {task_or_future} {name} completed successfully.")
|
||||||
except asyncio.CancelledError as ce:
|
except asyncio.CancelledError as ce:
|
||||||
self.logs.debug(f"[ASYNCIO] Task {task.get_name()} terminated with cancelled error.")
|
self.logs.debug(f"[ASYNCIO] {task_or_future} {name} terminated with cancelled error. {ce}")
|
||||||
except asyncio.InvalidStateError as ie:
|
except asyncio.InvalidStateError as ie:
|
||||||
self.logs.debug(f"[ASYNCIO] Task {task.get_name()} terminated with invalid state error.")
|
self.logs.debug(f"[ASYNCIO] {task_or_future} {name} terminated with invalid state error. {ie}")
|
||||||
|
|
||||||
def is_thread_alive(self, thread_name: str) -> bool:
|
def is_thread_alive(self, thread_name: str) -> bool:
|
||||||
"""Check if the thread is still running! using the is_alive method of Threads.
|
"""Check if the thread is still running! using the is_alive method of Threads.
|
||||||
@@ -492,59 +541,6 @@ class Base:
|
|||||||
self.running_sockets.remove(soc)
|
self.running_sockets.remove(soc)
|
||||||
self.logs.debug(f"-- Socket ==> closed {str(soc.fileno())}")
|
self.logs.debug(f"-- Socket ==> closed {str(soc.fileno())}")
|
||||||
|
|
||||||
async def shutdown(self) -> None:
|
|
||||||
"""Methode qui va préparer l'arrêt complêt du service
|
|
||||||
"""
|
|
||||||
# Stop RpcServer if running
|
|
||||||
await self.Loader.RpcServer.stop_server()
|
|
||||||
|
|
||||||
# unload modules.
|
|
||||||
self.logs.debug(f"=======> Unloading all modules!")
|
|
||||||
for module in self.Loader.ModuleUtils.model_get_loaded_modules().copy():
|
|
||||||
await self.Loader.ModuleUtils.unload_one_module(module.module_name)
|
|
||||||
|
|
||||||
self.logs.debug(f"=======> Closing all Coroutines!")
|
|
||||||
try:
|
|
||||||
await asyncio.wait_for(asyncio.gather(*self.running_asynctasks), timeout=5)
|
|
||||||
except asyncio.exceptions.TimeoutError as te:
|
|
||||||
self.logs.debug(f"Asyncio Timeout reached! {te}")
|
|
||||||
for task in self.running_asynctasks:
|
|
||||||
task.cancel()
|
|
||||||
except asyncio.exceptions.CancelledError as cerr:
|
|
||||||
self.logs.debug(f"Asyncio CancelledError reached! {cerr}")
|
|
||||||
|
|
||||||
|
|
||||||
# Nettoyage des timers
|
|
||||||
self.logs.debug(f"=======> Checking for Timers to stop")
|
|
||||||
for timer in self.running_timers:
|
|
||||||
while timer.is_alive():
|
|
||||||
self.logs.debug(f"> waiting for {timer.name} to close")
|
|
||||||
timer.cancel()
|
|
||||||
await asyncio.sleep(0.2)
|
|
||||||
self.running_timers.remove(timer)
|
|
||||||
self.logs.debug(f"> Cancelling {timer.name} {timer.native_id}")
|
|
||||||
|
|
||||||
self.logs.debug(f"=======> Checking for Threads to stop")
|
|
||||||
for thread in self.running_threads:
|
|
||||||
if thread.name == 'heartbeat' and thread.is_alive():
|
|
||||||
self.execute_periodic_action()
|
|
||||||
self.logs.debug(f"> Running the last periodic action")
|
|
||||||
self.running_threads.remove(thread)
|
|
||||||
self.logs.debug(f"> Cancelling {thread.name} {thread.native_id}")
|
|
||||||
|
|
||||||
self.logs.debug(f"=======> Checking for Sockets to stop")
|
|
||||||
for soc in self.running_sockets:
|
|
||||||
soc.close()
|
|
||||||
while soc.fileno() != -1:
|
|
||||||
soc.close()
|
|
||||||
|
|
||||||
self.running_sockets.remove(soc)
|
|
||||||
self.logs.debug(f"> Socket ==> closed {str(soc.fileno())}")
|
|
||||||
|
|
||||||
self.db_close()
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
def db_init(self) -> tuple[Engine, Connection]:
|
def db_init(self) -> tuple[Engine, Connection]:
|
||||||
|
|
||||||
db_directory = self.Config.DB_PATH
|
db_directory = self.Config.DB_PATH
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import asyncio
|
||||||
import importlib
|
import importlib
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
@@ -26,7 +27,6 @@ REHASH_MODULES = [
|
|||||||
'core.classes.protocols.inspircd'
|
'core.classes.protocols.inspircd'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
async def restart_service(uplink: 'Loader', reason: str = "Restarting with no reason!") -> None:
|
async def restart_service(uplink: 'Loader', reason: str = "Restarting with no reason!") -> None:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ async def rehash_service(uplink: 'Loader', nickname: str) -> None:
|
|||||||
need_a_restart = ["SERVEUR_ID"]
|
need_a_restart = ["SERVEUR_ID"]
|
||||||
uplink.Settings.set_cache('db_commands', uplink.Commands.DB_COMMANDS)
|
uplink.Settings.set_cache('db_commands', uplink.Commands.DB_COMMANDS)
|
||||||
|
|
||||||
await uplink.RpcServer.stop_server()
|
await uplink.RpcServer.stop_rpc_server()
|
||||||
|
|
||||||
restart_flag = False
|
restart_flag = False
|
||||||
config_model_bakcup = uplink.Config
|
config_model_bakcup = uplink.Config
|
||||||
@@ -122,10 +122,68 @@ async def rehash_service(uplink: 'Loader', nickname: str) -> None:
|
|||||||
uplink.Irc.Protocol.register_command()
|
uplink.Irc.Protocol.register_command()
|
||||||
|
|
||||||
uplink.RpcServer = uplink.RpcServerModule.JSonRpcServer(uplink)
|
uplink.RpcServer = uplink.RpcServerModule.JSonRpcServer(uplink)
|
||||||
uplink.Base.create_asynctask(uplink.RpcServer.start_server())
|
uplink.Base.create_asynctask(uplink.RpcServer.start_rpc_server())
|
||||||
|
|
||||||
# Reload Service modules
|
# Reload Service modules
|
||||||
for module in uplink.ModuleUtils.model_get_loaded_modules().copy():
|
for module in uplink.ModuleUtils.model_get_loaded_modules().copy():
|
||||||
await uplink.ModuleUtils.reload_one_module(module.module_name, nickname)
|
await uplink.ModuleUtils.reload_one_module(module.module_name, nickname)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
async def shutdown(uplink: 'Loader') -> None:
|
||||||
|
"""Methode qui va préparer l'arrêt complêt du service
|
||||||
|
"""
|
||||||
|
# Stop RpcServer if running
|
||||||
|
await uplink.RpcServer.stop_rpc_server()
|
||||||
|
|
||||||
|
# unload modules.
|
||||||
|
uplink.Logs.debug(f"=======> Unloading all modules!")
|
||||||
|
for module in uplink.ModuleUtils.model_get_loaded_modules().copy():
|
||||||
|
await uplink.ModuleUtils.unload_one_module(module.module_name)
|
||||||
|
|
||||||
|
# Nettoyage des timers
|
||||||
|
uplink.Logs.debug(f"=======> Closing all timers!")
|
||||||
|
for timer in uplink.Base.running_timers:
|
||||||
|
while timer.is_alive():
|
||||||
|
uplink.Logs.debug(f"> waiting for {timer.name} to close")
|
||||||
|
timer.cancel()
|
||||||
|
await asyncio.sleep(0.2)
|
||||||
|
uplink.Logs.debug(f"> Cancelling {timer.name} {timer.native_id}")
|
||||||
|
|
||||||
|
uplink.Logs.debug(f"=======> Closing all Threads!")
|
||||||
|
for thread in uplink.Base.running_threads:
|
||||||
|
if thread.name == 'heartbeat' and thread.is_alive():
|
||||||
|
uplink.Base.execute_periodic_action()
|
||||||
|
uplink.Logs.debug(f"> Running the last periodic action")
|
||||||
|
uplink.Logs.debug(f"> Cancelling {thread.name} {thread.native_id}")
|
||||||
|
|
||||||
|
uplink.Logs.debug(f"=======> Closing all IO Threads!")
|
||||||
|
[th.thread_event.clear() for th in uplink.Base.running_iothreads]
|
||||||
|
|
||||||
|
uplink.Logs.debug(f"=======> Closing all IO TASKS!")
|
||||||
|
try:
|
||||||
|
await asyncio.wait_for(asyncio.gather(*uplink.Base.running_iotasks), timeout=5)
|
||||||
|
except asyncio.exceptions.TimeoutError as te:
|
||||||
|
uplink.Logs.debug(f"Asyncio Timeout reached! {te}")
|
||||||
|
for task in uplink.Base.running_iotasks:
|
||||||
|
task.cancel()
|
||||||
|
except asyncio.exceptions.CancelledError as cerr:
|
||||||
|
uplink.Logs.debug(f"Asyncio CancelledError reached! {cerr}")
|
||||||
|
|
||||||
|
uplink.Logs.debug(f"=======> Closing all Sockets!")
|
||||||
|
for soc in uplink.Base.running_sockets:
|
||||||
|
soc.close()
|
||||||
|
while soc.fileno() != -1:
|
||||||
|
soc.close()
|
||||||
|
uplink.Base.running_sockets.remove(soc)
|
||||||
|
uplink.Logs.debug(f"> Socket ==> closed {str(soc.fileno())}")
|
||||||
|
|
||||||
|
uplink.Base.running_timers.clear()
|
||||||
|
uplink.Base.running_threads.clear()
|
||||||
|
uplink.Base.running_iotasks.clear()
|
||||||
|
uplink.Base.running_iothreads.clear()
|
||||||
|
uplink.Base.running_sockets.clear()
|
||||||
|
|
||||||
|
uplink.Base.db_close()
|
||||||
|
|
||||||
|
return None
|
||||||
@@ -17,11 +17,11 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
class JSonRpcServer:
|
class JSonRpcServer:
|
||||||
|
|
||||||
def __init__(self, context: 'Loader', *, hostname: str = '0.0.0.0', port: int = 5000):
|
def __init__(self, context: 'Loader'):
|
||||||
self._ctx = context
|
self._ctx = context
|
||||||
self.live: bool = False
|
self.live: bool = False
|
||||||
self.host = hostname
|
self.host = context.Config.RPC_HOST
|
||||||
self.port = port
|
self.port = context.Config.RPC_PORT
|
||||||
self.routes: list[Route] = []
|
self.routes: list[Route] = []
|
||||||
self.server: Optional[uvicorn.Server] = None
|
self.server: Optional[uvicorn.Server] = None
|
||||||
|
|
||||||
@@ -34,12 +34,12 @@ class JSonRpcServer:
|
|||||||
'command.get.by.module': RPCCommand(context).command_get_by_module
|
'command.get.by.module': RPCCommand(context).command_get_by_module
|
||||||
}
|
}
|
||||||
|
|
||||||
async def start_server(self):
|
async def start_rpc_server(self):
|
||||||
|
|
||||||
if not self.live:
|
if not self.live:
|
||||||
self.routes = [Route('/api', self.request_handler, methods=['POST'])]
|
self.routes = [Route('/api', self.request_handler, methods=['POST'])]
|
||||||
self.app_jsonrpc = Starlette(debug=False, routes=self.routes)
|
self.app_jsonrpc = Starlette(debug=False, routes=self.routes)
|
||||||
config = uvicorn.Config(self.app_jsonrpc, host=self.host, port=self.port, log_level=self._ctx.Config.DEBUG_LEVEL)
|
config = uvicorn.Config(self.app_jsonrpc, host=self.host, port=self.port, log_level=self._ctx.Config.DEBUG_LEVEL+10)
|
||||||
self.server = uvicorn.Server(config)
|
self.server = uvicorn.Server(config)
|
||||||
self.live = True
|
self.live = True
|
||||||
await self._ctx.Irc.Protocol.send_priv_msg(
|
await self._ctx.Irc.Protocol.send_priv_msg(
|
||||||
@@ -52,7 +52,7 @@ class JSonRpcServer:
|
|||||||
else:
|
else:
|
||||||
self._ctx.Logs.debug("Server already running")
|
self._ctx.Logs.debug("Server already running")
|
||||||
|
|
||||||
async def stop_server(self):
|
async def stop_rpc_server(self):
|
||||||
|
|
||||||
if self.server:
|
if self.server:
|
||||||
self.server.should_exit = True
|
self.server.should_exit = True
|
||||||
|
|||||||
13
core/irc.py
13
core/irc.py
@@ -126,7 +126,11 @@ class Irc:
|
|||||||
|
|
||||||
async def listen(self):
|
async def listen(self):
|
||||||
self.ctx.Base.create_asynctask(
|
self.ctx.Base.create_asynctask(
|
||||||
self.ctx.Base.create_thread_io(self.ctx.Utils.heartbeat, True, self.ctx, self.beat)
|
self.ctx.Base.create_thread_io(
|
||||||
|
self.ctx.Utils.heartbeat,
|
||||||
|
self.ctx, self.beat,
|
||||||
|
run_once=True, thread_flag=True
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
while self.signal:
|
while self.signal:
|
||||||
@@ -343,8 +347,13 @@ class Irc:
|
|||||||
|
|
||||||
async def thread_check_for_new_version(self, fromuser: str) -> None:
|
async def thread_check_for_new_version(self, fromuser: str) -> None:
|
||||||
dnickname = self.ctx.Config.SERVICE_NICKNAME
|
dnickname = self.ctx.Config.SERVICE_NICKNAME
|
||||||
|
response = self.ctx.Base.create_asynctask(
|
||||||
|
self.ctx.Base.create_thread_io(
|
||||||
|
self.ctx.Base.check_for_new_version, True
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if self.ctx.Base.check_for_new_version(True):
|
if response:
|
||||||
await self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f" New Version available : {self.ctx.Config.CURRENT_VERSION} >>> {self.ctx.Config.LATEST_VERSION}")
|
await self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=f" New Version available : {self.ctx.Config.CURRENT_VERSION} >>> {self.ctx.Config.LATEST_VERSION}")
|
||||||
await self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=" Please run (git pull origin main) in the current folder")
|
await self.Protocol.send_notice(nick_from=dnickname, nick_to=fromuser, msg=" Please run (git pull origin main) in the current folder")
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ class Loader:
|
|||||||
|
|
||||||
self.PFactory: factory.ProtocolFactorty = factory.ProtocolFactorty(self)
|
self.PFactory: factory.ProtocolFactorty = factory.ProtocolFactorty(self)
|
||||||
|
|
||||||
self.RpcServer: rpc_mod.JSonRpcServer = rpc_mod.JSonRpcServer(self, hostname='0.0.0.0')
|
self.RpcServer: rpc_mod.JSonRpcServer = rpc_mod.JSonRpcServer(self)
|
||||||
|
|
||||||
self.Logs.debug(self.Utils.tr("Loader %s success", __name__))
|
self.Logs.debug(self.Utils.tr("Loader %s success", __name__))
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
import logging
|
||||||
from typing import Any, TYPE_CHECKING, Optional
|
from typing import Any, TYPE_CHECKING, Optional
|
||||||
from core.classes.interfaces.imodule import IModule
|
from core.classes.interfaces.imodule import IModule
|
||||||
import mods.defender.schemas as schemas
|
import mods.defender.schemas as schemas
|
||||||
@@ -26,6 +27,8 @@ class Defender(IModule):
|
|||||||
def __init__(self, context: 'Loader') -> None:
|
def __init__(self, context: 'Loader') -> None:
|
||||||
super().__init__(context)
|
super().__init__(context)
|
||||||
self._mod_config: Optional[schemas.ModConfModel] = None
|
self._mod_config: Optional[schemas.ModConfModel] = None
|
||||||
|
self.Schemas = schemas.RepDB()
|
||||||
|
self.Threads = thds
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mod_config(self) -> ModConfModel:
|
def mod_config(self) -> ModConfModel:
|
||||||
@@ -55,40 +58,43 @@ class Defender(IModule):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
async def load(self):
|
async def load(self):
|
||||||
|
|
||||||
# Variable qui va contenir les options de configuration du module Defender
|
# Variable qui va contenir les options de configuration du module Defender
|
||||||
self._mod_config: schemas.ModConfModel = self.ModConfModel()
|
self._mod_config: schemas.ModConfModel = self.ModConfModel()
|
||||||
|
|
||||||
# sync the database with local variable (Mandatory)
|
# sync the database with local variable (Mandatory)
|
||||||
await self.sync_db()
|
await self.sync_db()
|
||||||
|
|
||||||
# Add module schemas
|
|
||||||
self.Schemas = schemas
|
|
||||||
|
|
||||||
# Add module utils functions
|
# Add module utils functions
|
||||||
self.mod_utils = utils
|
self.mod_utils = utils
|
||||||
|
|
||||||
# Create module commands (Mandatory)
|
# Create module commands (Mandatory)
|
||||||
self.ctx.Irc.build_command(0, self.module_name, 'code', 'Display the code or key for access')
|
self.ctx.Commands.build_command(0, self.module_name, 'code', 'Display the code or key for access')
|
||||||
self.ctx.Irc.build_command(1, self.module_name, 'info', 'Provide information about the channel or server')
|
self.ctx.Commands.build_command(1, self.module_name, 'info', 'Provide information about the channel or server')
|
||||||
self.ctx.Irc.build_command(1, self.module_name, 'autolimit', 'Automatically set channel user limits')
|
self.ctx.Commands.build_command(1, self.module_name, 'autolimit', 'Automatically set channel user limits')
|
||||||
self.ctx.Irc.build_command(3, self.module_name, 'reputation', 'Check or manage user reputation')
|
self.ctx.Commands.build_command(3, self.module_name, 'reputation', 'Check or manage user reputation')
|
||||||
self.ctx.Irc.build_command(3, self.module_name, 'proxy_scan', 'Scan users for proxy connections')
|
self.ctx.Commands.build_command(3, self.module_name, 'proxy_scan', 'Scan users for proxy connections')
|
||||||
self.ctx.Irc.build_command(3, self.module_name, 'flood', 'Handle flood detection and mitigation')
|
self.ctx.Commands.build_command(3, self.module_name, 'flood', 'Handle flood detection and mitigation')
|
||||||
self.ctx.Irc.build_command(3, self.module_name, 'status', 'Check the status of the server or bot')
|
self.ctx.Commands.build_command(3, self.module_name, 'status', 'Check the status of the server or bot')
|
||||||
self.ctx.Irc.build_command(3, self.module_name, 'show_reputation', 'Display reputation information')
|
self.ctx.Commands.build_command(3, self.module_name, 'show_reputation', 'Display reputation information')
|
||||||
self.ctx.Irc.build_command(3, self.module_name, 'sentinel', 'Monitor and guard the channel or server')
|
self.ctx.Commands.build_command(3, self.module_name, 'sentinel', 'Monitor and guard the channel or server')
|
||||||
|
|
||||||
self.timeout = self.ctx.Config.API_TIMEOUT
|
self.timeout = self.ctx.Config.API_TIMEOUT
|
||||||
|
|
||||||
# Listes qui vont contenir les ip a scanner avec les différentes API
|
# Listes qui vont contenir les ip a scanner avec les différentes API
|
||||||
self.Schemas.DB_ABUSEIPDB_USERS = self.Schemas.DB_FREEIPAPI_USERS = self.Schemas.DB_CLOUDFILT_USERS = []
|
self.Schemas.DB_ABUSEIPDB_USERS = []
|
||||||
self.Schemas.DB_PSUTIL_USERS = self.Schemas.DB_LOCALSCAN_USERS = []
|
self.Schemas.DB_FREEIPAPI_USERS = []
|
||||||
|
self.Schemas.DB_CLOUDFILT_USERS = []
|
||||||
|
self.Schemas.DB_PSUTIL_USERS = []
|
||||||
|
self.Schemas.DB_LOCALSCAN_USERS = []
|
||||||
|
|
||||||
# Variables qui indique que les threads sont en cours d'éxecutions
|
# Variables qui indique que les threads sont en cours d'éxecutions
|
||||||
self.abuseipdb_isRunning = self.freeipapi_isRunning = self.cloudfilt_isRunning = True
|
self.abuseipdb_isRunning = True if self.mod_config.abuseipdb_scan == 1 else False
|
||||||
self.psutil_isRunning = self.localscan_isRunning = self.reputationTimer_isRunning = True
|
self.freeipapi_isRunning = True if self.mod_config.freeipapi_scan == 1 else False
|
||||||
self.autolimit_isRunning = True
|
self.cloudfilt_isRunning = True if self.mod_config.cloudfilt_scan == 1 else False
|
||||||
|
self.psutil_isRunning = True if self.mod_config.psutil_scan == 1 else False
|
||||||
|
self.localscan_isRunning = True if self.mod_config.local_scan == 1 else False
|
||||||
|
self.reputationTimer_isRunning = True if self.mod_config.reputation == 1 else False
|
||||||
|
self.autolimit_isRunning = True if self.mod_config.autolimit == 1 else False
|
||||||
|
|
||||||
# Variable qui va contenir les users
|
# Variable qui va contenir les users
|
||||||
self.flood_system = {}
|
self.flood_system = {}
|
||||||
@@ -101,19 +107,21 @@ class Defender(IModule):
|
|||||||
self.cloudfilt_key = 'r1gEtjtfgRQjtNBDMxsg'
|
self.cloudfilt_key = 'r1gEtjtfgRQjtNBDMxsg'
|
||||||
|
|
||||||
# Démarrer les threads pour démarrer les api
|
# Démarrer les threads pour démarrer les api
|
||||||
self.ctx.Base.create_asynctask(thds.coro_freeipapi_scan(self))
|
self.ctx.Base.create_asynctask(self.Threads.coro_freeipapi_scan(self)) if self.mod_config.freeipapi_scan == 1 else None
|
||||||
self.ctx.Base.create_asynctask(thds.coro_cloudfilt_scan(self))
|
self.ctx.Base.create_asynctask(self.Threads.coro_cloudfilt_scan(self)) if self.mod_config.cloudfilt_scan == 1 else None
|
||||||
self.ctx.Base.create_asynctask(thds.coro_abuseipdb_scan(self))
|
self.ctx.Base.create_asynctask(self.Threads.coro_abuseipdb_scan(self)) if self.mod_config.abuseipdb_scan == 1 else None
|
||||||
self.ctx.Base.create_asynctask(thds.coro_local_scan(self))
|
self.ctx.Base.create_asynctask(self.Threads.coro_local_scan(self)) if self.mod_config.local_scan == 1 else None
|
||||||
self.ctx.Base.create_asynctask(thds.coro_psutil_scan(self))
|
self.ctx.Base.create_asynctask(self.Threads.coro_psutil_scan(self)) if self.mod_config.psutil_scan == 1 else None
|
||||||
self.ctx.Base.create_asynctask(thds.coro_apply_reputation_sanctions(self))
|
self.ctx.Base.create_asynctask(self.Threads.coro_apply_reputation_sanctions(self)) if self.mod_config.reputation == 1 else None
|
||||||
|
self.ctx.Base.create_asynctask(self.Threads.coro_autolimit(self)) if self.mod_config.autolimit == 1 else None
|
||||||
if self.mod_config.autolimit == 1:
|
|
||||||
self.ctx.Base.create_asynctask(thds.coro_autolimit(self))
|
|
||||||
|
|
||||||
if self.mod_config.reputation == 1:
|
if self.mod_config.reputation == 1:
|
||||||
await self.ctx.Irc.Protocol.send_sjoin(self.ctx.Config.SALON_JAIL)
|
await self.ctx.Irc.Protocol.send_sjoin(self.ctx.Config.SALON_JAIL)
|
||||||
await self.ctx.Irc.Protocol.send2socket(f":{self.ctx.Config.SERVICE_NICKNAME} SAMODE {self.ctx.Config.SALON_JAIL} +o {self.ctx.Config.SERVICE_NICKNAME}")
|
await self.ctx.Irc.Protocol.send2socket(f":{self.ctx.Config.SERVICE_NICKNAME} SAMODE {self.ctx.Config.SALON_JAIL} +o {self.ctx.Config.SERVICE_NICKNAME}")
|
||||||
|
for chan in self.ctx.Channel.UID_CHANNEL_DB:
|
||||||
|
if chan.name != self.ctx.Config.SALON_JAIL:
|
||||||
|
await self.ctx.Irc.Protocol.send_set_mode('+b', channel_name=chan.name, params='~security-group:unknown-users')
|
||||||
|
await self.ctx.Irc.Protocol.send_set_mode('+eee', channel_name=chan.name, params='~security-group:webirc-users ~security-group:known-users ~security-group:websocket-users')
|
||||||
|
|
||||||
def __onload(self):
|
def __onload(self):
|
||||||
|
|
||||||
@@ -138,7 +146,7 @@ class Defender(IModule):
|
|||||||
if localscan:
|
if localscan:
|
||||||
self.Schemas.DB_LOCALSCAN_USERS = localscan
|
self.Schemas.DB_LOCALSCAN_USERS = localscan
|
||||||
|
|
||||||
def unload(self) -> None:
|
async def unload(self) -> None:
|
||||||
"""Cette methode sera executée a chaque désactivation ou
|
"""Cette methode sera executée a chaque désactivation ou
|
||||||
rechargement de module
|
rechargement de module
|
||||||
"""
|
"""
|
||||||
@@ -158,6 +166,13 @@ class Defender(IModule):
|
|||||||
|
|
||||||
self.ctx.Commands.drop_command_by_module(self.module_name)
|
self.ctx.Commands.drop_command_by_module(self.module_name)
|
||||||
|
|
||||||
|
if self.mod_config.reputation == 1:
|
||||||
|
await self.ctx.Irc.Protocol.send_part_chan(self.ctx.Config.SERVICE_ID, self.ctx.Config.SALON_JAIL)
|
||||||
|
for chan in self.ctx.Channel.UID_CHANNEL_DB:
|
||||||
|
if chan.name != self.ctx.Config.SALON_JAIL:
|
||||||
|
await self.ctx.Irc.Protocol.send_set_mode('-b', channel_name=chan.name, params='~security-group:unknown-users')
|
||||||
|
await self.ctx.Irc.Protocol.send_set_mode('-eee', channel_name=chan.name, params='~security-group:webirc-users ~security-group:known-users ~security-group:websocket-users')
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def insert_db_trusted(self, uid: str, nickname:str) -> None:
|
async def insert_db_trusted(self, uid: str, nickname:str) -> None:
|
||||||
@@ -411,22 +426,26 @@ class Defender(IModule):
|
|||||||
|
|
||||||
if self.mod_config.reputation == 1:
|
if self.mod_config.reputation == 1:
|
||||||
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {self.ctx.Config.COLORS.green}REPUTATION{self.ctx.Config.COLORS.black} ] : Already activated", channel=dchanlog)
|
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {self.ctx.Config.COLORS.green}REPUTATION{self.ctx.Config.COLORS.black} ] : Already activated", channel=dchanlog)
|
||||||
return False
|
return None
|
||||||
|
|
||||||
# self.update_db_configuration('reputation', 1)
|
|
||||||
await self.update_configuration(key, 1)
|
await self.update_configuration(key, 1)
|
||||||
|
self.ctx.Base.create_asynctask(self.Threads.coro_apply_reputation_sanctions(self))
|
||||||
|
|
||||||
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {self.ctx.Config.COLORS.green}REPUTATION{self.ctx.Config.COLORS.black} ] : Activated by {fromuser}", channel=dchanlog)
|
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {self.ctx.Config.COLORS.green}REPUTATION{self.ctx.Config.COLORS.black} ] : Activated by {fromuser}", channel=dchanlog)
|
||||||
|
|
||||||
await self.ctx.Irc.Protocol.send_join_chan(uidornickname=dnickname, channel=jail_chan)
|
await self.ctx.Irc.Protocol.send_join_chan(uidornickname=dnickname, channel=jail_chan)
|
||||||
await self.ctx.Irc.Protocol.send2socket(f":{service_id} SAMODE {jail_chan} +{dumodes} {dnickname}")
|
await self.ctx.Irc.Protocol.send2socket(f":{service_id} SAMODE {jail_chan} +{dumodes} {dnickname}")
|
||||||
await self.ctx.Irc.Protocol.send2socket(f":{service_id} MODE {jail_chan} +{jail_chan_mode}")
|
await self.ctx.Irc.Protocol.send_set_mode(f'+{jail_chan_mode}', channel_name=jail_chan)
|
||||||
|
|
||||||
if self.mod_config.reputation_sg == 1:
|
if self.mod_config.reputation_sg == 1:
|
||||||
for chan in self.ctx.Channel.UID_CHANNEL_DB:
|
for chan in self.ctx.Channel.UID_CHANNEL_DB:
|
||||||
if chan.name != jail_chan:
|
if chan.name != jail_chan:
|
||||||
await self.ctx.Irc.Protocol.send2socket(f":{service_id} MODE {chan.name} +b ~security-group:unknown-users")
|
await self.ctx.Irc.Protocol.send_set_mode('+b', channel_name=chan.name, params='~security-group:unknown-users')
|
||||||
await self.ctx.Irc.Protocol.send2socket(f":{service_id} MODE {chan.name} +eee ~security-group:webirc-users ~security-group:known-users ~security-group:websocket-users")
|
await self.ctx.Irc.Protocol.send_set_mode(
|
||||||
|
'+eee',
|
||||||
|
channel_name=chan.name,
|
||||||
|
params='~security-group:webirc-users ~security-group:known-users ~security-group:websocket-users'
|
||||||
|
)
|
||||||
|
|
||||||
await self.ctx.Channel.db_query_channel('add', self.module_name, jail_chan)
|
await self.ctx.Channel.db_query_channel('add', self.module_name, jail_chan)
|
||||||
|
|
||||||
@@ -441,20 +460,26 @@ class Defender(IModule):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
await self.update_configuration(key, 0)
|
await self.update_configuration(key, 0)
|
||||||
|
self.reputationTimer_isRunning = False
|
||||||
|
|
||||||
await self.ctx.Irc.Protocol.send_priv_msg(
|
await self.ctx.Irc.Protocol.send_priv_msg(
|
||||||
nick_from=dnickname,
|
nick_from=dnickname,
|
||||||
msg=f"[ {self.ctx.Config.COLORS.red}REPUTATION{self.ctx.Config.COLORS.black} ] : Deactivated by {fromuser}",
|
msg=f"[ {self.ctx.Config.COLORS.red}REPUTATION{self.ctx.Config.COLORS.black} ] : Deactivated by {fromuser}",
|
||||||
channel=dchanlog
|
channel=dchanlog
|
||||||
)
|
)
|
||||||
|
|
||||||
await self.ctx.Irc.Protocol.send2socket(f":{service_id} SAMODE {jail_chan} -{dumodes} {dnickname}")
|
await self.ctx.Irc.Protocol.send2socket(f":{service_id} SAMODE {jail_chan} -{dumodes} {dnickname}")
|
||||||
await self.ctx.Irc.Protocol.send2socket(f":{service_id} MODE {jail_chan} -sS")
|
await self.ctx.Irc.Protocol.send_set_mode('-sS', channel_name=jail_chan)
|
||||||
await self.ctx.Irc.Protocol.send2socket(f":{service_id} PART {jail_chan}")
|
await self.ctx.Irc.Protocol.send_part_chan(service_id, jail_chan)
|
||||||
|
|
||||||
for chan in self.ctx.Channel.UID_CHANNEL_DB:
|
for chan in self.ctx.Channel.UID_CHANNEL_DB:
|
||||||
if chan.name != jail_chan:
|
if chan.name != jail_chan:
|
||||||
await self.ctx.Irc.Protocol.send2socket(f":{service_id} MODE {chan.name} -b ~security-group:unknown-users")
|
await self.ctx.Irc.Protocol.send_set_mode('-b', channel_name=chan.name, params='~security-group:unknown-users')
|
||||||
await self.ctx.Irc.Protocol.send2socket(f":{service_id} MODE {chan.name} -eee ~security-group:webirc-users ~security-group:known-users ~security-group:websocket-users")
|
await self.ctx.Irc.Protocol.send_set_mode(
|
||||||
|
'-eee',
|
||||||
|
channel_name=chan.name,
|
||||||
|
params='~security-group:webirc-users ~security-group:known-users ~security-group:websocket-users'
|
||||||
|
)
|
||||||
|
|
||||||
await self.ctx.Channel.db_query_channel('del', self.module_name, jail_chan)
|
await self.ctx.Channel.db_query_channel('del', self.module_name, jail_chan)
|
||||||
|
|
||||||
@@ -464,12 +489,17 @@ class Defender(IModule):
|
|||||||
match get_options:
|
match get_options:
|
||||||
case 'release':
|
case 'release':
|
||||||
# .reputation release [nick]
|
# .reputation release [nick]
|
||||||
p = await self.ctx.Irc.Protocol
|
|
||||||
link = self.ctx.Config.SERVEUR_LINK
|
link = self.ctx.Config.SERVEUR_LINK
|
||||||
jailed_salon = self.ctx.Config.SALON_JAIL
|
jailed_salon = self.ctx.Config.SALON_JAIL
|
||||||
welcome_salon = self.ctx.Config.SALON_LIBERER
|
welcome_salon = self.ctx.Config.SALON_LIBERER
|
||||||
client_obj = self.ctx.User.get_user(str(cmd[2]))
|
client_obj = self.ctx.User.get_user(str(cmd[2]))
|
||||||
|
|
||||||
|
if self.mod_config.reputation != 1:
|
||||||
|
await self.ctx.Irc.Protocol.send_notice(nick_from=dnickname,
|
||||||
|
nick_to=fromuser,
|
||||||
|
msg="The reputation system is not activated!")
|
||||||
|
return None
|
||||||
|
|
||||||
if client_obj is None:
|
if client_obj is None:
|
||||||
await self.ctx.Irc.Protocol.send_notice(nick_from=dnickname,
|
await self.ctx.Irc.Protocol.send_notice(nick_from=dnickname,
|
||||||
nick_to=fromuser,
|
nick_to=fromuser,
|
||||||
@@ -658,6 +688,7 @@ class Defender(IModule):
|
|||||||
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Already activated", channel=dchanlog)
|
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Already activated", channel=dchanlog)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
self.ctx.Base.create_asynctask(self.Threads.coro_local_scan(self))
|
||||||
await self.update_configuration(option, 1)
|
await self.update_configuration(option, 1)
|
||||||
|
|
||||||
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Activated by {fromuser}", channel=dchanlog)
|
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Activated by {fromuser}", channel=dchanlog)
|
||||||
@@ -667,6 +698,7 @@ class Defender(IModule):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
await self.update_configuration(option, 0)
|
await self.update_configuration(option, 0)
|
||||||
|
self.localscan_isRunning = False
|
||||||
|
|
||||||
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_red}PROXY_SCAN {option.upper()}{color_black} ] : Deactivated by {fromuser}", channel=dchanlog)
|
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_red}PROXY_SCAN {option.upper()}{color_black} ] : Deactivated by {fromuser}", channel=dchanlog)
|
||||||
|
|
||||||
@@ -676,6 +708,7 @@ class Defender(IModule):
|
|||||||
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Already activated", channel=dchanlog)
|
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Already activated", channel=dchanlog)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
self.ctx.Base.create_asynctask(self.Threads.coro_psutil_scan(self))
|
||||||
await self.update_configuration(option, 1)
|
await self.update_configuration(option, 1)
|
||||||
|
|
||||||
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Activated by {fromuser}", channel=dchanlog)
|
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Activated by {fromuser}", channel=dchanlog)
|
||||||
@@ -685,6 +718,7 @@ class Defender(IModule):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
await self.update_configuration(option, 0)
|
await self.update_configuration(option, 0)
|
||||||
|
self.psutil_isRunning = False
|
||||||
|
|
||||||
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_red}PROXY_SCAN {option.upper()}{color_black} ] : Deactivated by {fromuser}", channel=dchanlog)
|
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_red}PROXY_SCAN {option.upper()}{color_black} ] : Deactivated by {fromuser}", channel=dchanlog)
|
||||||
|
|
||||||
@@ -694,6 +728,7 @@ class Defender(IModule):
|
|||||||
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Already activated", channel=dchanlog)
|
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Already activated", channel=dchanlog)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
self.ctx.Base.create_asynctask(self.Threads.coro_abuseipdb_scan(self))
|
||||||
await self.update_configuration(option, 1)
|
await self.update_configuration(option, 1)
|
||||||
|
|
||||||
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Activated by {fromuser}", channel=dchanlog)
|
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Activated by {fromuser}", channel=dchanlog)
|
||||||
@@ -703,6 +738,7 @@ class Defender(IModule):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
await self.update_configuration(option, 0)
|
await self.update_configuration(option, 0)
|
||||||
|
self.abuseipdb_isRunning = False
|
||||||
|
|
||||||
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_red}PROXY_SCAN {option.upper()}{color_black} ] : Deactivated by {fromuser}", channel=dchanlog)
|
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_red}PROXY_SCAN {option.upper()}{color_black} ] : Deactivated by {fromuser}", channel=dchanlog)
|
||||||
|
|
||||||
@@ -712,6 +748,7 @@ class Defender(IModule):
|
|||||||
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Already activated", channel=dchanlog)
|
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Already activated", channel=dchanlog)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
self.ctx.Base.create_asynctask(self.Threads.coro_freeipapi_scan(self))
|
||||||
await self.update_configuration(option, 1)
|
await self.update_configuration(option, 1)
|
||||||
|
|
||||||
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Activated by {fromuser}", channel=dchanlog)
|
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Activated by {fromuser}", channel=dchanlog)
|
||||||
@@ -721,6 +758,7 @@ class Defender(IModule):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
await self.update_configuration(option, 0)
|
await self.update_configuration(option, 0)
|
||||||
|
self.freeipapi_isRunning = False
|
||||||
|
|
||||||
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_red}PROXY_SCAN {option.upper()}{color_black} ] : Deactivated by {fromuser}", channel=dchanlog)
|
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_red}PROXY_SCAN {option.upper()}{color_black} ] : Deactivated by {fromuser}", channel=dchanlog)
|
||||||
|
|
||||||
@@ -730,6 +768,7 @@ class Defender(IModule):
|
|||||||
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Already activated", channel=dchanlog)
|
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Already activated", channel=dchanlog)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
self.ctx.Base.create_asynctask(self.Threads.coro_cloudfilt_scan(self))
|
||||||
await self.update_configuration(option, 1)
|
await self.update_configuration(option, 1)
|
||||||
|
|
||||||
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Activated by {fromuser}", channel=dchanlog)
|
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_green}PROXY_SCAN {option.upper()}{color_black} ] : Activated by {fromuser}", channel=dchanlog)
|
||||||
@@ -739,6 +778,7 @@ class Defender(IModule):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
await self.update_configuration(option, 0)
|
await self.update_configuration(option, 0)
|
||||||
|
self.cloudfilt_isRunning = False
|
||||||
|
|
||||||
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_red}PROXY_SCAN {option.upper()}{color_black} ] : Deactivated by {fromuser}", channel=dchanlog)
|
await self.ctx.Irc.Protocol.send_priv_msg(nick_from=dnickname, msg=f"[ {color_red}PROXY_SCAN {option.upper()}{color_black} ] : Deactivated by {fromuser}", channel=dchanlog)
|
||||||
|
|
||||||
@@ -915,3 +955,6 @@ class Defender(IModule):
|
|||||||
await self.join_saved_channels()
|
await self.join_saved_channels()
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
case _:
|
||||||
|
pass
|
||||||
@@ -28,6 +28,8 @@ class FloodUser(MainModel):
|
|||||||
nbr_msg: int = 0
|
nbr_msg: int = 0
|
||||||
first_msg_time: int = 0
|
first_msg_time: int = 0
|
||||||
|
|
||||||
|
|
||||||
|
class RepDB:
|
||||||
DB_FLOOD_USERS: list[FloodUser] = []
|
DB_FLOOD_USERS: list[FloodUser] = []
|
||||||
DB_ABUSEIPDB_USERS: list[MUser] = []
|
DB_ABUSEIPDB_USERS: list[MUser] = []
|
||||||
DB_FREEIPAPI_USERS: list[MUser] = []
|
DB_FREEIPAPI_USERS: list[MUser] = []
|
||||||
|
|||||||
@@ -1,89 +1,251 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING, Optional
|
||||||
from time import sleep
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from mods.defender.mod_defender import Defender
|
from mods.defender.mod_defender import Defender
|
||||||
|
|
||||||
async def coro_apply_reputation_sanctions(uplink: 'Defender'):
|
async def coro_apply_reputation_sanctions(uplink: 'Defender'):
|
||||||
|
uplink.reputationTimer_isRunning = True
|
||||||
while uplink.reputationTimer_isRunning:
|
while uplink.reputationTimer_isRunning:
|
||||||
await uplink.mod_utils.action_apply_reputation_santions(uplink)
|
await uplink.mod_utils.action_apply_reputation_santions(uplink)
|
||||||
await asyncio.sleep(5)
|
await asyncio.sleep(5)
|
||||||
|
|
||||||
async def coro_cloudfilt_scan(uplink: 'Defender'):
|
async def coro_cloudfilt_scan(uplink: 'Defender'):
|
||||||
|
uplink.cloudfilt_isRunning = True
|
||||||
|
service_id = uplink.ctx.Config.SERVICE_ID
|
||||||
|
service_chanlog = uplink.ctx.Config.SERVICE_CHANLOG
|
||||||
|
color_red = uplink.ctx.Config.COLORS.red
|
||||||
|
nogc = uplink.ctx.Config.COLORS.nogc
|
||||||
|
nogc = uplink.ctx.Config.COLORS.nogc
|
||||||
|
p = uplink.ctx.Irc.Protocol
|
||||||
|
|
||||||
while uplink.cloudfilt_isRunning:
|
while uplink.cloudfilt_isRunning:
|
||||||
|
try:
|
||||||
list_to_remove:list = []
|
list_to_remove:list = []
|
||||||
for user in uplink.Schemas.DB_CLOUDFILT_USERS:
|
for user in uplink.Schemas.DB_CLOUDFILT_USERS:
|
||||||
await uplink.mod_utils.action_scan_client_with_cloudfilt(uplink, user)
|
if user.remote_ip not in uplink.ctx.Config.WHITELISTED_IP:
|
||||||
|
result: Optional[dict] = await uplink.ctx.Base.create_thread_io(
|
||||||
|
uplink.mod_utils.action_scan_client_with_cloudfilt,
|
||||||
|
uplink, user
|
||||||
|
)
|
||||||
list_to_remove.append(user)
|
list_to_remove.append(user)
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
continue
|
||||||
|
|
||||||
|
remote_ip = user.remote_ip
|
||||||
|
fullname = f'{user.nickname}!{user.username}@{user.hostname}'
|
||||||
|
|
||||||
|
r_host = result.get('host', None)
|
||||||
|
r_countryiso = result.get('countryiso', None)
|
||||||
|
r_listed = result.get('listed', False)
|
||||||
|
r_listedby = result.get('listed_by', None)
|
||||||
|
|
||||||
|
await p.send_priv_msg(
|
||||||
|
nick_from=service_id,
|
||||||
|
msg=f"[ {color_red}CLOUDFILT_SCAN{nogc} ] : Connexion de {fullname} ({remote_ip}) ==> Host: {r_host} | country: {r_countryiso} | listed: {r_listed} | listed by : {r_listedby}",
|
||||||
|
channel=service_chanlog)
|
||||||
|
|
||||||
|
uplink.ctx.Logs.debug(f"[CLOUDFILT SCAN] ({fullname}) connected from ({r_countryiso}), Listed: {r_listed}, by: {r_listedby}")
|
||||||
|
|
||||||
|
if r_listed:
|
||||||
|
await p.send2socket(f":{service_id} GLINE +*@{remote_ip} {uplink.ctx.Config.GLINE_DURATION} Your connexion is listed as dangerous {r_listed} {r_listedby} - detected by cloudfilt")
|
||||||
|
uplink.ctx.Logs.debug(f"[CLOUDFILT SCAN GLINE] Dangerous connection ({fullname}) from ({r_countryiso}) Listed: {r_listed}, by: {r_listedby}")
|
||||||
|
|
||||||
|
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
for user_model in list_to_remove:
|
for user_model in list_to_remove:
|
||||||
uplink.Schemas.DB_CLOUDFILT_USERS.remove(user_model)
|
uplink.Schemas.DB_CLOUDFILT_USERS.remove(user_model)
|
||||||
|
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1.5)
|
||||||
|
except ValueError as ve:
|
||||||
|
uplink.ctx.Logs.debug(f"The value to remove is not in the list. {ve}")
|
||||||
|
except TimeoutError as te:
|
||||||
|
uplink.ctx.Logs.debug(f"Timeout Error {te}")
|
||||||
|
|
||||||
async def coro_freeipapi_scan(uplink: 'Defender'):
|
async def coro_freeipapi_scan(uplink: 'Defender'):
|
||||||
|
uplink.freeipapi_isRunning = True
|
||||||
|
service_id = uplink.ctx.Config.SERVICE_ID
|
||||||
|
service_chanlog = uplink.ctx.Config.SERVICE_CHANLOG
|
||||||
|
color_red = uplink.ctx.Config.COLORS.red
|
||||||
|
nogc = uplink.ctx.Config.COLORS.nogc
|
||||||
|
p = uplink.ctx.Irc.Protocol
|
||||||
|
|
||||||
while uplink.freeipapi_isRunning:
|
while uplink.freeipapi_isRunning:
|
||||||
|
try:
|
||||||
list_to_remove: list = []
|
list_to_remove: list = []
|
||||||
for user in uplink.Schemas.DB_FREEIPAPI_USERS:
|
for user in uplink.Schemas.DB_FREEIPAPI_USERS:
|
||||||
await uplink.mod_utils.action_scan_client_with_freeipapi(uplink, user)
|
if user.remote_ip not in uplink.ctx.Config.WHITELISTED_IP:
|
||||||
|
result: Optional[dict] = await uplink.ctx.Base.create_thread_io(
|
||||||
|
uplink.mod_utils.action_scan_client_with_freeipapi,
|
||||||
|
uplink, user
|
||||||
|
)
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# pseudo!ident@host
|
||||||
|
remote_ip = user.remote_ip
|
||||||
|
fullname = f'{user.nickname}!{user.username}@{user.hostname}'
|
||||||
|
|
||||||
|
await p.send_priv_msg(
|
||||||
|
nick_from=service_id,
|
||||||
|
msg=f"[ {color_red}FREEIPAPI_SCAN{nogc} ] : Connexion de {fullname} ({remote_ip}) ==> Proxy: {str(result['isProxy'])} | Country : {str(result['countryCode'])}",
|
||||||
|
channel=service_chanlog)
|
||||||
|
uplink.ctx.Logs.debug(f"[FREEIPAPI SCAN] ({fullname}) connected from ({result['countryCode']}), Proxy: {result['isProxy']}")
|
||||||
|
|
||||||
|
if result['isProxy']:
|
||||||
|
await p.send2socket(f":{service_id} GLINE +*@{remote_ip} {uplink.ctx.Config.GLINE_DURATION} This server do not allow proxy connexions {str(result['isProxy'])} - detected by freeipapi")
|
||||||
|
uplink.ctx.Logs.debug(f"[FREEIPAPI SCAN GLINE] Server do not allow proxy connexions {result['isProxy']}")
|
||||||
|
|
||||||
list_to_remove.append(user)
|
list_to_remove.append(user)
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
|
# remove users from the list
|
||||||
for user_model in list_to_remove:
|
for user_model in list_to_remove:
|
||||||
uplink.Schemas.DB_FREEIPAPI_USERS.remove(user_model)
|
uplink.Schemas.DB_FREEIPAPI_USERS.remove(user_model)
|
||||||
|
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1.5)
|
||||||
|
except ValueError as ve:
|
||||||
|
uplink.ctx.Logs.debug(f"The value to remove is not in the list. {ve}")
|
||||||
|
except TimeoutError as te:
|
||||||
|
uplink.ctx.Logs.debug(f"Timeout Error {te}")
|
||||||
|
|
||||||
async def coro_abuseipdb_scan(uplink: 'Defender'):
|
async def coro_abuseipdb_scan(uplink: 'Defender'):
|
||||||
|
|
||||||
while uplink.abuseipdb_isRunning:
|
uplink.abuseipdb_isRunning = True
|
||||||
|
service_id = uplink.ctx.Config.SERVICE_ID
|
||||||
|
service_chanlog = uplink.ctx.Config.SERVICE_CHANLOG
|
||||||
|
color_red = uplink.ctx.Config.COLORS.red
|
||||||
|
nogc = uplink.ctx.Config.COLORS.nogc
|
||||||
|
p = uplink.ctx.Irc.Protocol
|
||||||
|
|
||||||
|
while uplink.abuseipdb_isRunning:
|
||||||
|
try:
|
||||||
list_to_remove: list = []
|
list_to_remove: list = []
|
||||||
print(uplink.Schemas.DB_ABUSEIPDB_USERS)
|
|
||||||
for user in uplink.Schemas.DB_ABUSEIPDB_USERS:
|
for user in uplink.Schemas.DB_ABUSEIPDB_USERS:
|
||||||
await uplink.mod_utils.action_scan_client_with_abuseipdb(uplink, user)
|
if user.remote_ip not in uplink.ctx.Config.WHITELISTED_IP:
|
||||||
|
|
||||||
|
result: Optional[dict] = await uplink.ctx.Base.create_thread_io(
|
||||||
|
uplink.mod_utils.action_scan_client_with_abuseipdb,
|
||||||
|
uplink, user
|
||||||
|
)
|
||||||
list_to_remove.append(user)
|
list_to_remove.append(user)
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
continue
|
||||||
|
|
||||||
|
remote_ip = user.remote_ip
|
||||||
|
fullname = f'{user.nickname}!{user.username}@{user.hostname}'
|
||||||
|
|
||||||
|
await p.send_priv_msg(
|
||||||
|
nick_from=service_id,
|
||||||
|
msg=f"[ {color_red}ABUSEIPDB_SCAN{nogc} ] : Connexion de {fullname} ({remote_ip}) ==> Score: {str(result['score'])} | Country : {result['country']} | Tor : {str(result['isTor'])} | Total Reports : {str(result['totalReports'])}",
|
||||||
|
channel=service_chanlog
|
||||||
|
)
|
||||||
|
uplink.ctx.Logs.debug(f"[ABUSEIPDB SCAN] ({fullname}) connected from ({result['country']}), Score: {result['score']}, Tor: {result['isTor']}")
|
||||||
|
|
||||||
|
if result['isTor']:
|
||||||
|
await p.send2socket(f":{service_id} GLINE +*@{remote_ip} {uplink.ctx.Config.GLINE_DURATION} This server do not allow Tor connexions {str(result['isTor'])} - Detected by Abuseipdb")
|
||||||
|
uplink.ctx.Logs.debug(f"[ABUSEIPDB SCAN GLINE] Server do not allow Tor connections Tor: {result['isTor']}, Score: {result['score']}")
|
||||||
|
elif result['score'] >= 95:
|
||||||
|
await p.send2socket(f":{service_id} GLINE +*@{remote_ip} {uplink.ctx.Config.GLINE_DURATION} You were banned from this server because your abuse score is = {str(result['score'])} - Detected by Abuseipdb")
|
||||||
|
uplink.ctx.Logs.debug(f"[ABUSEIPDB SCAN GLINE] Server do not high risk connections Country: {result['country']}, Score: {result['score']}")
|
||||||
|
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
print(list_to_remove)
|
|
||||||
for user_model in list_to_remove:
|
for user_model in list_to_remove:
|
||||||
uplink.Schemas.DB_ABUSEIPDB_USERS.remove(user_model)
|
uplink.Schemas.DB_ABUSEIPDB_USERS.remove(user_model)
|
||||||
|
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1.5)
|
||||||
|
except ValueError as ve:
|
||||||
|
uplink.ctx.Logs.debug(f"The value to remove is not in the list. {ve}", exc_info=True)
|
||||||
|
except TimeoutError as te:
|
||||||
|
uplink.ctx.Logs.debug(f"Timeout Error {te}", exc_info=True)
|
||||||
|
|
||||||
async def coro_local_scan(uplink: 'Defender'):
|
async def coro_local_scan(uplink: 'Defender'):
|
||||||
|
uplink.localscan_isRunning = True
|
||||||
|
service_id = uplink.ctx.Config.SERVICE_ID
|
||||||
|
service_chanlog = uplink.ctx.Config.SERVICE_CHANLOG
|
||||||
|
color_red = uplink.ctx.Config.COLORS.red
|
||||||
|
nogc = uplink.ctx.Config.COLORS.nogc
|
||||||
|
p = uplink.ctx.Irc.Protocol
|
||||||
|
|
||||||
while uplink.localscan_isRunning:
|
while uplink.localscan_isRunning:
|
||||||
|
try:
|
||||||
list_to_remove:list = []
|
list_to_remove:list = []
|
||||||
for user in uplink.Schemas.DB_LOCALSCAN_USERS:
|
for user in uplink.Schemas.DB_LOCALSCAN_USERS:
|
||||||
await uplink.mod_utils.action_scan_client_with_local_socket(uplink, user)
|
if user.remote_ip not in uplink.ctx.Config.WHITELISTED_IP:
|
||||||
list_to_remove.append(user)
|
list_to_remove.append(user)
|
||||||
|
result = await uplink.ctx.Base.create_thread_io(
|
||||||
|
uplink.mod_utils.action_scan_client_with_local_socket,
|
||||||
|
uplink, user
|
||||||
|
)
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
continue
|
||||||
|
|
||||||
|
fullname = f'{user.nickname}!{user.username}@{user.hostname}'
|
||||||
|
opened_ports = result['opened_ports']
|
||||||
|
closed_ports = result['closed_ports']
|
||||||
|
if opened_ports:
|
||||||
|
await p.send_priv_msg(
|
||||||
|
nick_from=service_id,
|
||||||
|
msg=f"[ {color_red}LOCAL_SCAN{nogc} ] {fullname} ({user.remote_ip}) : The Port(s) {opened_ports} are opened on this remote ip [{user.remote_ip}]",
|
||||||
|
channel=service_chanlog
|
||||||
|
)
|
||||||
|
if closed_ports:
|
||||||
|
await p.send_priv_msg(
|
||||||
|
nick_from=service_id,
|
||||||
|
msg=f"[ {color_red}LOCAL_SCAN{nogc} ] {fullname} ({user.remote_ip}) : The Port(s) {closed_ports} are closed on this remote ip [{user.remote_ip}]",
|
||||||
|
channel=service_chanlog
|
||||||
|
)
|
||||||
|
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
for user_model in list_to_remove:
|
for user_model in list_to_remove:
|
||||||
uplink.Schemas.DB_LOCALSCAN_USERS.remove(user_model)
|
uplink.Schemas.DB_LOCALSCAN_USERS.remove(user_model)
|
||||||
|
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1.5)
|
||||||
|
except ValueError as ve:
|
||||||
|
uplink.ctx.Logs.debug(f"The value to remove is not in the list. {ve}")
|
||||||
|
except TimeoutError as te:
|
||||||
|
uplink.ctx.Logs.debug(f"Timeout Error {te}")
|
||||||
|
|
||||||
async def coro_psutil_scan(uplink: 'Defender'):
|
async def coro_psutil_scan(uplink: 'Defender'):
|
||||||
|
uplink.psutil_isRunning = True
|
||||||
|
service_id = uplink.ctx.Config.SERVICE_ID
|
||||||
|
service_chanlog = uplink.ctx.Config.SERVICE_CHANLOG
|
||||||
|
color_red = uplink.ctx.Config.COLORS.red
|
||||||
|
nogc = uplink.ctx.Config.COLORS.nogc
|
||||||
|
p = uplink.ctx.Irc.Protocol
|
||||||
|
|
||||||
while uplink.psutil_isRunning:
|
while uplink.psutil_isRunning:
|
||||||
|
try:
|
||||||
list_to_remove:list = []
|
list_to_remove:list = []
|
||||||
for user in uplink.Schemas.DB_PSUTIL_USERS:
|
for user in uplink.Schemas.DB_PSUTIL_USERS:
|
||||||
await uplink.mod_utils.action_scan_client_with_psutil(uplink, user)
|
result = await uplink.ctx.Base.create_thread_io(uplink.mod_utils.action_scan_client_with_psutil, uplink, user)
|
||||||
list_to_remove.append(user)
|
list_to_remove.append(user)
|
||||||
|
if not result:
|
||||||
|
continue
|
||||||
|
|
||||||
|
fullname = f'{user.nickname}!{user.username}@{user.hostname}'
|
||||||
|
await p.send_priv_msg(
|
||||||
|
nick_from=service_id,
|
||||||
|
msg=f"[ {color_red}PSUTIL_SCAN{nogc} ] {fullname} ({user.remote_ip}) is using ports {result}",
|
||||||
|
channel=service_chanlog
|
||||||
|
)
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
for user_model in list_to_remove:
|
for user_model in list_to_remove:
|
||||||
uplink.Schemas.DB_PSUTIL_USERS.remove(user_model)
|
uplink.Schemas.DB_PSUTIL_USERS.remove(user_model)
|
||||||
|
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1.5)
|
||||||
|
except ValueError as ve:
|
||||||
|
uplink.ctx.Logs.debug(f"The value to remove is not in the list. {ve}")
|
||||||
|
except TimeoutError as te:
|
||||||
|
uplink.ctx.Logs.debug(f"Timeout Error {te}")
|
||||||
|
|
||||||
async def coro_autolimit(uplink: 'Defender'):
|
async def coro_autolimit(uplink: 'Defender'):
|
||||||
|
|
||||||
@@ -104,7 +266,6 @@ async def coro_autolimit(uplink: 'Defender'):
|
|||||||
chan_list: list[str] = [c.name for c in uplink.ctx.Channel.UID_CHANNEL_DB]
|
chan_list: list[str] = [c.name for c in uplink.ctx.Channel.UID_CHANNEL_DB]
|
||||||
|
|
||||||
while uplink.autolimit_isRunning:
|
while uplink.autolimit_isRunning:
|
||||||
|
|
||||||
if uplink.mod_config.autolimit == 0:
|
if uplink.mod_config.autolimit == 0:
|
||||||
uplink.ctx.Logs.debug("autolimit deactivated ... stopping the current thread")
|
uplink.ctx.Logs.debug("autolimit deactivated ... stopping the current thread")
|
||||||
break
|
break
|
||||||
@@ -112,7 +273,7 @@ async def coro_autolimit(uplink: 'Defender'):
|
|||||||
for chan in uplink.ctx.Channel.UID_CHANNEL_DB:
|
for chan in uplink.ctx.Channel.UID_CHANNEL_DB:
|
||||||
for chan_copy in chanObj_copy:
|
for chan_copy in chanObj_copy:
|
||||||
if chan_copy["name"] == chan.name and len(chan.uids) != chan_copy["uids_count"]:
|
if chan_copy["name"] == chan.name and len(chan.uids) != chan_copy["uids_count"]:
|
||||||
await p.send2socket(f":{uplink.ctx.Config.SERVICE_ID} MODE {chan.name} +l {len(chan.uids) + uplink.mod_config.autolimit_amount}")
|
await p.send_set_mode('+l', channel_name=chan.name, params=len(chan.uids) + uplink.mod_config.autolimit_amount)
|
||||||
chan_copy["uids_count"] = len(chan.uids)
|
chan_copy["uids_count"] = len(chan.uids)
|
||||||
|
|
||||||
if chan.name not in chan_list:
|
if chan.name not in chan_list:
|
||||||
@@ -128,13 +289,13 @@ async def coro_autolimit(uplink: 'Defender'):
|
|||||||
# Si c'est la premiere execution
|
# Si c'est la premiere execution
|
||||||
if INIT == 1:
|
if INIT == 1:
|
||||||
for chan in uplink.ctx.Channel.UID_CHANNEL_DB:
|
for chan in uplink.ctx.Channel.UID_CHANNEL_DB:
|
||||||
await p.send2socket(f":{uplink.ctx.Config.SERVICE_ID} MODE {chan.name} +l {len(chan.uids) + uplink.mod_config.autolimit_amount}")
|
await p.send_set_mode('+l', channel_name=chan.name, params=len(chan.uids) + uplink.mod_config.autolimit_amount)
|
||||||
|
|
||||||
# Si le nouveau amount est différent de l'initial
|
# Si le nouveau amount est différent de l'initial
|
||||||
if init_amount != uplink.mod_config.autolimit_amount:
|
if init_amount != uplink.mod_config.autolimit_amount:
|
||||||
init_amount = uplink.mod_config.autolimit_amount
|
init_amount = uplink.mod_config.autolimit_amount
|
||||||
for chan in uplink.ctx.Channel.UID_CHANNEL_DB:
|
for chan in uplink.ctx.Channel.UID_CHANNEL_DB:
|
||||||
await p.send2socket(f":{uplink.ctx.Config.SERVICE_ID} MODE {chan.name} +l {len(chan.uids) + uplink.mod_config.autolimit_amount}")
|
await p.send_set_mode('+l', channel_name=chan.name, params=len(chan.uids) + uplink.mod_config.autolimit_amount)
|
||||||
|
|
||||||
INIT = 0
|
INIT = 0
|
||||||
|
|
||||||
@@ -142,7 +303,6 @@ async def coro_autolimit(uplink: 'Defender'):
|
|||||||
await asyncio.sleep(uplink.mod_config.autolimit_interval)
|
await asyncio.sleep(uplink.mod_config.autolimit_interval)
|
||||||
|
|
||||||
for chan in uplink.ctx.Channel.UID_CHANNEL_DB:
|
for chan in uplink.ctx.Channel.UID_CHANNEL_DB:
|
||||||
# await p.send2socket(f":{uplink.ctx.Config.SERVICE_ID} MODE {chan.name} -l")
|
|
||||||
await p.send_set_mode('-l', channel_name=chan.name)
|
await p.send_set_mode('-l', channel_name=chan.name)
|
||||||
|
|
||||||
uplink.ctx.Irc.autolimit_started = False
|
uplink.ctx.Irc.autolimit_started = False
|
||||||
@@ -158,7 +318,6 @@ async def coro_release_mode_mute(uplink: 'Defender', action: str, channel: str):
|
|||||||
channel (str): The related channel
|
channel (str): The related channel
|
||||||
|
|
||||||
"""
|
"""
|
||||||
service_id = uplink.ctx.Config.SERVICE_ID
|
|
||||||
timeout = uplink.mod_config.flood_timer
|
timeout = uplink.mod_config.flood_timer
|
||||||
await asyncio.sleep(timeout)
|
await asyncio.sleep(timeout)
|
||||||
|
|
||||||
@@ -169,6 +328,6 @@ async def coro_release_mode_mute(uplink: 'Defender', action: str, channel: str):
|
|||||||
match action:
|
match action:
|
||||||
case 'mode-m':
|
case 'mode-m':
|
||||||
# Action -m sur le salon
|
# Action -m sur le salon
|
||||||
await uplink.ctx.Irc.Protocol.send2socket(f":{service_id} MODE {channel} -m")
|
await uplink.ctx.Irc.Protocol.send_set_mode('-m', channel_name=channel)
|
||||||
case _:
|
case _:
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -267,6 +267,7 @@ async def handle_on_uid(uplink: 'Defender', srvmsg: list[str]):
|
|||||||
####################
|
####################
|
||||||
# [:<sid>] UID <uid> <ts> <nick> <real-host> <displayed-host> <real-user> <ip> <signon> <modes> [<mode-parameters>]+ :<real>
|
# [:<sid>] UID <uid> <ts> <nick> <real-host> <displayed-host> <real-user> <ip> <signon> <modes> [<mode-parameters>]+ :<real>
|
||||||
# [:<sid>] UID nickname hopcount timestamp username hostname uid servicestamp umodes virthost cloakedhost ip :gecos
|
# [:<sid>] UID nickname hopcount timestamp username hostname uid servicestamp umodes virthost cloakedhost ip :gecos
|
||||||
|
|
||||||
async def action_on_flood(uplink: 'Defender', srvmsg: list[str]):
|
async def action_on_flood(uplink: 'Defender', srvmsg: list[str]):
|
||||||
|
|
||||||
confmodel = uplink.mod_config
|
confmodel = uplink.mod_config
|
||||||
@@ -316,17 +317,16 @@ async def action_on_flood(uplink: 'Defender', srvmsg: list[str]):
|
|||||||
fu.nbr_msg = 0
|
fu.nbr_msg = 0
|
||||||
get_diff_secondes = unixtime - fu.first_msg_time
|
get_diff_secondes = unixtime - fu.first_msg_time
|
||||||
elif fu.nbr_msg > flood_message:
|
elif fu.nbr_msg > flood_message:
|
||||||
uplink.ctx.Logs.info('system de flood detecté')
|
await p.send_set_mode('+m', channel_name=channel)
|
||||||
await p.send_priv_msg(
|
await p.send_priv_msg(
|
||||||
nick_from=dnickname,
|
nick_from=dnickname,
|
||||||
msg=f"{color_red} {color_bold} Flood detected. Apply the +m mode (Ô_o)",
|
msg=f"{color_red} {color_bold} Flood detected. Apply the +m mode (Ô_o)",
|
||||||
channel=channel
|
channel=channel
|
||||||
)
|
)
|
||||||
await p.send2socket(f":{service_id} MODE {channel} +m")
|
uplink.ctx.Logs.debug(f'[FLOOD] {get_detected_nickname} triggered +m mode on the channel {channel}')
|
||||||
uplink.ctx.Logs.info(f'FLOOD Détecté sur {get_detected_nickname} mode +m appliqué sur le salon {channel}')
|
|
||||||
fu.nbr_msg = 0
|
fu.nbr_msg = 0
|
||||||
fu.first_msg_time = unixtime
|
fu.first_msg_time = unixtime
|
||||||
uplink.ctx.Base.create_asynctask(dthreads.coro_release_mode_mute(uplink, 'mode-m', channel))
|
uplink.ctx.Base.create_asynctask(uplink.Threads.coro_release_mode_mute(uplink, 'mode-m', channel))
|
||||||
|
|
||||||
async def action_add_reputation_sanctions(uplink: 'Defender', jailed_uid: str ):
|
async def action_add_reputation_sanctions(uplink: 'Defender', jailed_uid: str ):
|
||||||
|
|
||||||
@@ -336,10 +336,14 @@ async def action_add_reputation_sanctions(uplink: 'Defender', jailed_uid: str ):
|
|||||||
confmodel = uplink.mod_config
|
confmodel = uplink.mod_config
|
||||||
|
|
||||||
get_reputation = uplink.ctx.Reputation.get_reputation(jailed_uid)
|
get_reputation = uplink.ctx.Reputation.get_reputation(jailed_uid)
|
||||||
|
|
||||||
if get_reputation is None:
|
if get_reputation is None:
|
||||||
uplink.ctx.Logs.warning(f'UID {jailed_uid} has not been found')
|
uplink.ctx.Logs.warning(f'UID {jailed_uid} has not been found')
|
||||||
return
|
return None
|
||||||
|
|
||||||
|
if get_reputation.isWebirc or get_reputation.isWebsocket:
|
||||||
|
uplink.ctx.Logs.debug(f'This nickname is exampted from the reputation system (Webirc or Websocket). {get_reputation.nickname} ({get_reputation.uid})')
|
||||||
|
uplink.ctx.Reputation.delete(get_reputation.uid)
|
||||||
|
return None
|
||||||
|
|
||||||
salon_logs = gconfig.SERVICE_CHANLOG
|
salon_logs = gconfig.SERVICE_CHANLOG
|
||||||
salon_jail = gconfig.SALON_JAIL
|
salon_jail = gconfig.SALON_JAIL
|
||||||
@@ -360,7 +364,7 @@ async def action_add_reputation_sanctions(uplink: 'Defender', jailed_uid: str ):
|
|||||||
# Si le user ne vient pas de webIrc
|
# Si le user ne vient pas de webIrc
|
||||||
await p.send_sajoin(nick_to_sajoin=jailed_nickname, channel_name=salon_jail)
|
await p.send_sajoin(nick_to_sajoin=jailed_nickname, channel_name=salon_jail)
|
||||||
await p.send_priv_msg(nick_from=gconfig.SERVICE_NICKNAME,
|
await p.send_priv_msg(nick_from=gconfig.SERVICE_NICKNAME,
|
||||||
msg=f" [{color_red} REPUTATION {nogc}] : Connexion de {jailed_nickname} ({jailed_score}) ==> {salon_jail}",
|
msg=f" [ {color_red}REPUTATION{nogc} ]: The nickname {jailed_nickname} has been sent to {salon_jail} because his reputation score is ({jailed_score})",
|
||||||
channel=salon_logs
|
channel=salon_logs
|
||||||
)
|
)
|
||||||
await p.send_notice(
|
await p.send_notice(
|
||||||
@@ -371,7 +375,7 @@ async def action_add_reputation_sanctions(uplink: 'Defender', jailed_uid: str ):
|
|||||||
if reputation_ban_all_chan == 1:
|
if reputation_ban_all_chan == 1:
|
||||||
for chan in uplink.ctx.Channel.UID_CHANNEL_DB:
|
for chan in uplink.ctx.Channel.UID_CHANNEL_DB:
|
||||||
if chan.name != salon_jail:
|
if chan.name != salon_jail:
|
||||||
await p.send2socket(f":{service_id} MODE {chan.name} +b {jailed_nickname}!*@*")
|
await p.send_set_mode('+b', channel_name=chan.name, params=f'{jailed_nickname}!*@*')
|
||||||
await p.send2socket(f":{service_id} KICK {chan.name} {jailed_nickname}")
|
await p.send2socket(f":{service_id} KICK {chan.name} {jailed_nickname}")
|
||||||
|
|
||||||
uplink.ctx.Logs.info(f"[REPUTATION] {jailed_nickname} jailed (UID: {jailed_uid}, score: {jailed_score})")
|
uplink.ctx.Logs.info(f"[REPUTATION] {jailed_nickname} jailed (UID: {jailed_uid}, score: {jailed_score})")
|
||||||
@@ -419,14 +423,14 @@ async def action_apply_reputation_santions(uplink: 'Defender') -> None:
|
|||||||
for chan in uplink.ctx.Channel.UID_CHANNEL_DB:
|
for chan in uplink.ctx.Channel.UID_CHANNEL_DB:
|
||||||
if chan.name != salon_jail and ban_all_chan == 1:
|
if chan.name != salon_jail and ban_all_chan == 1:
|
||||||
get_user_reputation = uplink.ctx.Reputation.get_reputation(uid)
|
get_user_reputation = uplink.ctx.Reputation.get_reputation(uid)
|
||||||
await p.send2socket(f":{service_id} MODE {chan.name} -b {get_user_reputation.nickname}!*@*")
|
await p.send_set_mode('-b', channel_name=chan.name, params=f"{get_user_reputation.nickname}!*@*")
|
||||||
|
|
||||||
# Lorsqu'un utilisateur quitte, il doit être supprimé de {UID_DB}.
|
# Lorsqu'un utilisateur quitte, il doit être supprimé de {UID_DB}.
|
||||||
uplink.ctx.Channel.delete_user_from_all_channel(uid)
|
uplink.ctx.Channel.delete_user_from_all_channel(uid)
|
||||||
uplink.ctx.Reputation.delete(uid)
|
uplink.ctx.Reputation.delete(uid)
|
||||||
uplink.ctx.User.delete(uid)
|
uplink.ctx.User.delete(uid)
|
||||||
|
|
||||||
async def action_scan_client_with_cloudfilt(uplink: 'Defender', user_model: 'MUser') -> Optional[dict[str, str]]:
|
def action_scan_client_with_cloudfilt(uplink: 'Defender', user_model: 'MUser') -> Optional[dict[str, str]]:
|
||||||
"""Analyse l'ip avec cloudfilt
|
"""Analyse l'ip avec cloudfilt
|
||||||
Cette methode devra etre lancer toujours via un thread ou un timer.
|
Cette methode devra etre lancer toujours via un thread ou un timer.
|
||||||
Args:
|
Args:
|
||||||
@@ -438,11 +442,6 @@ async def action_scan_client_with_cloudfilt(uplink: 'Defender', user_model: 'MUs
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
remote_ip = user_model.remote_ip
|
remote_ip = user_model.remote_ip
|
||||||
username = user_model.username
|
|
||||||
hostname = user_model.hostname
|
|
||||||
nickname = user_model.nickname
|
|
||||||
p = uplink.ctx.Irc.Protocol
|
|
||||||
|
|
||||||
if remote_ip in uplink.ctx.Config.WHITELISTED_IP:
|
if remote_ip in uplink.ctx.Config.WHITELISTED_IP:
|
||||||
return None
|
return None
|
||||||
if uplink.mod_config.cloudfilt_scan == 0:
|
if uplink.mod_config.cloudfilt_scan == 0:
|
||||||
@@ -450,19 +449,11 @@ async def action_scan_client_with_cloudfilt(uplink: 'Defender', user_model: 'MUs
|
|||||||
if uplink.cloudfilt_key == '':
|
if uplink.cloudfilt_key == '':
|
||||||
return None
|
return None
|
||||||
|
|
||||||
service_id = uplink.ctx.Config.SERVICE_ID
|
|
||||||
service_chanlog = uplink.ctx.Config.SERVICE_CHANLOG
|
|
||||||
color_red = uplink.ctx.Config.COLORS.red
|
|
||||||
nogc = uplink.ctx.Config.COLORS.nogc
|
|
||||||
|
|
||||||
url = "https://developers18334.cloudfilt.com/"
|
url = "https://developers18334.cloudfilt.com/"
|
||||||
|
data = {'ip': remote_ip, 'key': uplink.cloudfilt_key}
|
||||||
|
with requests.Session() as sess:
|
||||||
|
response = sess.post(url=url, data=data)
|
||||||
|
|
||||||
data = {
|
|
||||||
'ip': remote_ip,
|
|
||||||
'key': uplink.cloudfilt_key
|
|
||||||
}
|
|
||||||
|
|
||||||
response = requests.post(url=url, data=data)
|
|
||||||
# Formatted output
|
# Formatted output
|
||||||
decoded_response: dict = loads(response.text)
|
decoded_response: dict = loads(response.text)
|
||||||
status_code = response.status_code
|
status_code = response.status_code
|
||||||
@@ -472,30 +463,14 @@ async def action_scan_client_with_cloudfilt(uplink: 'Defender', user_model: 'MUs
|
|||||||
|
|
||||||
result = {
|
result = {
|
||||||
'countryiso': decoded_response.get('countryiso', None),
|
'countryiso': decoded_response.get('countryiso', None),
|
||||||
'listed': decoded_response.get('listed', None),
|
'listed': decoded_response.get('listed', False),
|
||||||
'listed_by': decoded_response.get('listed_by', None),
|
'listed_by': decoded_response.get('listed_by', None),
|
||||||
'host': decoded_response.get('host', None)
|
'host': decoded_response.get('host', None)
|
||||||
}
|
}
|
||||||
|
|
||||||
# pseudo!ident@host
|
|
||||||
fullname = f'{nickname}!{username}@{hostname}'
|
|
||||||
|
|
||||||
await p.send_priv_msg(
|
|
||||||
nick_from=service_id,
|
|
||||||
msg=f"[ {color_red}CLOUDFILT_SCAN{nogc} ] : Connexion de {fullname} ({remote_ip}) ==> Host: {str(result['host'])} | country: {str(result['countryiso'])} | listed: {str(result['listed'])} | listed by : {str(result['listed_by'])}",
|
|
||||||
channel=service_chanlog)
|
|
||||||
|
|
||||||
uplink.ctx.Logs.debug(f"[CLOUDFILT SCAN] ({fullname}) connected from ({result['countryiso']}), Listed: {result['listed']}, by: {result['listed_by']}")
|
|
||||||
|
|
||||||
if result['listed']:
|
|
||||||
await p.send2socket(f":{service_id} GLINE +*@{remote_ip} {uplink.ctx.Config.GLINE_DURATION} Your connexion is listed as dangerous {str(result['listed'])} {str(result['listed_by'])} - detected by cloudfilt")
|
|
||||||
uplink.ctx.Logs.debug(f"[CLOUDFILT SCAN GLINE] Dangerous connection ({fullname}) from ({result['countryiso']}) Listed: {result['listed']}, by: {result['listed_by']}")
|
|
||||||
|
|
||||||
response.close()
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
async def action_scan_client_with_freeipapi(uplink: 'Defender', user_model: 'MUser') -> Optional[dict[str, str]]:
|
def action_scan_client_with_freeipapi(uplink: 'Defender', user_model: 'MUser') -> Optional[dict[str, str]]:
|
||||||
"""Analyse l'ip avec Freeipapi
|
"""Analyse l'ip avec Freeipapi
|
||||||
Cette methode devra etre lancer toujours via un thread ou un timer.
|
Cette methode devra etre lancer toujours via un thread ou un timer.
|
||||||
Args:
|
Args:
|
||||||
@@ -505,29 +480,16 @@ async def action_scan_client_with_freeipapi(uplink: 'Defender', user_model: 'MUs
|
|||||||
dict[str, any] | None: les informations du provider
|
dict[str, any] | None: les informations du provider
|
||||||
keys : 'countryCode', 'isProxy'
|
keys : 'countryCode', 'isProxy'
|
||||||
"""
|
"""
|
||||||
p = uplink.ctx.Irc.Protocol
|
|
||||||
remote_ip = user_model.remote_ip
|
remote_ip = user_model.remote_ip
|
||||||
username = user_model.username
|
|
||||||
hostname = user_model.hostname
|
|
||||||
nickname = user_model.nickname
|
|
||||||
|
|
||||||
if remote_ip in uplink.ctx.Config.WHITELISTED_IP:
|
if remote_ip in uplink.ctx.Config.WHITELISTED_IP:
|
||||||
return None
|
return None
|
||||||
if uplink.mod_config.freeipapi_scan == 0:
|
if uplink.mod_config.freeipapi_scan == 0:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
service_id = uplink.ctx.Config.SERVICE_ID
|
with requests.Session() as sess:
|
||||||
service_chanlog = uplink.ctx.Config.SERVICE_CHANLOG
|
|
||||||
color_red = uplink.ctx.Config.COLORS.red
|
|
||||||
nogc = uplink.ctx.Config.COLORS.nogc
|
|
||||||
|
|
||||||
url = f'https://freeipapi.com/api/json/{remote_ip}'
|
url = f'https://freeipapi.com/api/json/{remote_ip}'
|
||||||
|
headers = {'Accept': 'application/json'}
|
||||||
headers = {
|
response = sess.request(method='GET', url=url, headers=headers, timeout=uplink.timeout)
|
||||||
'Accept': 'application/json',
|
|
||||||
}
|
|
||||||
|
|
||||||
response = requests.request(method='GET', url=url, headers=headers, timeout=uplink.timeout)
|
|
||||||
|
|
||||||
# Formatted output
|
# Formatted output
|
||||||
decoded_response: dict = loads(response.text)
|
decoded_response: dict = loads(response.text)
|
||||||
@@ -544,25 +506,9 @@ async def action_scan_client_with_freeipapi(uplink: 'Defender', user_model: 'MUs
|
|||||||
'countryCode': decoded_response.get('countryCode', None),
|
'countryCode': decoded_response.get('countryCode', None),
|
||||||
'isProxy': decoded_response.get('isProxy', None)
|
'isProxy': decoded_response.get('isProxy', None)
|
||||||
}
|
}
|
||||||
|
|
||||||
# pseudo!ident@host
|
|
||||||
fullname = f'{nickname}!{username}@{hostname}'
|
|
||||||
|
|
||||||
await p.send_priv_msg(
|
|
||||||
nick_from=service_id,
|
|
||||||
msg=f"[ {color_red}FREEIPAPI_SCAN{nogc} ] : Connexion de {fullname} ({remote_ip}) ==> Proxy: {str(result['isProxy'])} | Country : {str(result['countryCode'])}",
|
|
||||||
channel=service_chanlog)
|
|
||||||
uplink.ctx.Logs.debug(f"[FREEIPAPI SCAN] ({fullname}) connected from ({result['countryCode']}), Proxy: {result['isProxy']}")
|
|
||||||
|
|
||||||
if result['isProxy']:
|
|
||||||
await p.send2socket(f":{service_id} GLINE +*@{remote_ip} {uplink.ctx.Config.GLINE_DURATION} This server do not allow proxy connexions {str(result['isProxy'])} - detected by freeipapi")
|
|
||||||
uplink.ctx.Logs.debug(f"[FREEIPAPI SCAN GLINE] Server do not allow proxy connexions {result['isProxy']}")
|
|
||||||
|
|
||||||
response.close()
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
async def action_scan_client_with_abuseipdb(uplink: 'Defender', user_model: 'MUser') -> Optional[dict[str, str]]:
|
def action_scan_client_with_abuseipdb(uplink: 'Defender', user_model: 'MUser') -> Optional[dict[str, str]]:
|
||||||
"""Analyse l'ip avec AbuseIpDB
|
"""Analyse l'ip avec AbuseIpDB
|
||||||
Cette methode devra etre lancer toujours via un thread ou un timer.
|
Cette methode devra etre lancer toujours via un thread ou un timer.
|
||||||
Args:
|
Args:
|
||||||
@@ -572,32 +518,28 @@ async def action_scan_client_with_abuseipdb(uplink: 'Defender', user_model: 'MUs
|
|||||||
Returns:
|
Returns:
|
||||||
dict[str, str] | None: les informations du provider
|
dict[str, str] | None: les informations du provider
|
||||||
"""
|
"""
|
||||||
p = uplink.ctx.Irc.Protocol
|
|
||||||
remote_ip = user_model.remote_ip
|
remote_ip = user_model.remote_ip
|
||||||
username = user_model.username
|
|
||||||
hostname = user_model.hostname
|
|
||||||
nickname = user_model.nickname
|
|
||||||
|
|
||||||
if remote_ip in uplink.ctx.Config.WHITELISTED_IP:
|
if remote_ip in uplink.ctx.Config.WHITELISTED_IP:
|
||||||
return None
|
return None
|
||||||
if uplink.mod_config.abuseipdb_scan == 0:
|
if uplink.mod_config.abuseipdb_scan == 0:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if uplink.abuseipdb_key == '':
|
if uplink.abuseipdb_key == '':
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
with requests.Session() as sess:
|
||||||
url = 'https://api.abuseipdb.com/api/v2/check'
|
url = 'https://api.abuseipdb.com/api/v2/check'
|
||||||
querystring = {
|
querystring = {'ipAddress': remote_ip, 'maxAgeInDays': '90'}
|
||||||
'ipAddress': remote_ip,
|
|
||||||
'maxAgeInDays': '90'
|
|
||||||
}
|
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
'Key': uplink.abuseipdb_key
|
'Key': uplink.abuseipdb_key
|
||||||
}
|
}
|
||||||
|
|
||||||
response = requests.request(method='GET', url=url, headers=headers, params=querystring, timeout=uplink.timeout)
|
response = sess.request(method='GET', url=url, headers=headers, params=querystring, timeout=uplink.timeout)
|
||||||
|
|
||||||
|
if response.status_code != 200:
|
||||||
|
uplink.ctx.Logs.warning(f'status code = {str(response.status_code)}')
|
||||||
|
return None
|
||||||
|
|
||||||
# Formatted output
|
# Formatted output
|
||||||
decoded_response: dict[str, dict] = loads(response.text)
|
decoded_response: dict[str, dict] = loads(response.text)
|
||||||
@@ -612,81 +554,45 @@ async def action_scan_client_with_abuseipdb(uplink: 'Defender', user_model: 'MUs
|
|||||||
'totalReports': decoded_response.get('data', {}).get('totalReports', 0)
|
'totalReports': decoded_response.get('data', {}).get('totalReports', 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
service_id = uplink.ctx.Config.SERVICE_ID
|
|
||||||
service_chanlog = uplink.ctx.Config.SERVICE_CHANLOG
|
|
||||||
color_red = uplink.ctx.Config.COLORS.red
|
|
||||||
nogc = uplink.ctx.Config.COLORS.nogc
|
|
||||||
|
|
||||||
# pseudo!ident@host
|
|
||||||
fullname = f'{nickname}!{username}@{hostname}'
|
|
||||||
|
|
||||||
await p.send_priv_msg(
|
|
||||||
nick_from=service_id,
|
|
||||||
msg=f"[ {color_red}ABUSEIPDB_SCAN{nogc} ] : Connexion de {fullname} ({remote_ip}) ==> Score: {str(result['score'])} | Country : {result['country']} | Tor : {str(result['isTor'])} | Total Reports : {str(result['totalReports'])}",
|
|
||||||
channel=service_chanlog
|
|
||||||
)
|
|
||||||
uplink.ctx.Logs.debug(f"[ABUSEIPDB SCAN] ({fullname}) connected from ({result['country']}), Score: {result['score']}, Tor: {result['isTor']}")
|
|
||||||
|
|
||||||
if result['isTor']:
|
|
||||||
await p.send2socket(f":{service_id} GLINE +*@{remote_ip} {uplink.ctx.Config.GLINE_DURATION} This server do not allow Tor connexions {str(result['isTor'])} - Detected by Abuseipdb")
|
|
||||||
uplink.ctx.Logs.debug(f"[ABUSEIPDB SCAN GLINE] Server do not allow Tor connections Tor: {result['isTor']}, Score: {result['score']}")
|
|
||||||
elif result['score'] >= 95:
|
|
||||||
await p.send2socket(f":{service_id} GLINE +*@{remote_ip} {uplink.ctx.Config.GLINE_DURATION} You were banned from this server because your abuse score is = {str(result['score'])} - Detected by Abuseipdb")
|
|
||||||
uplink.ctx.Logs.debug(f"[ABUSEIPDB SCAN GLINE] Server do not high risk connections Country: {result['country']}, Score: {result['score']}")
|
|
||||||
|
|
||||||
response.close()
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
async def action_scan_client_with_local_socket(uplink: 'Defender', user_model: 'MUser'):
|
def action_scan_client_with_local_socket(uplink: 'Defender', user_model: 'MUser') -> Optional[dict[str, str]]:
|
||||||
"""local_scan
|
"""local_scan
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
uplink (Defender): Defender instance object
|
uplink (Defender): Defender instance object
|
||||||
user_model (MUser): l'objet User qui contient l'ip
|
user_model (MUser): l'objet User qui contient l'ip
|
||||||
"""
|
"""
|
||||||
p = uplink.ctx.Irc.Protocol
|
|
||||||
remote_ip = user_model.remote_ip
|
remote_ip = user_model.remote_ip
|
||||||
username = user_model.username
|
|
||||||
hostname = user_model.hostname
|
|
||||||
nickname = user_model.nickname
|
|
||||||
fullname = f'{nickname}!{username}@{hostname}'
|
|
||||||
|
|
||||||
if remote_ip in uplink.ctx.Config.WHITELISTED_IP:
|
if remote_ip in uplink.ctx.Config.WHITELISTED_IP:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
result = {'opened_ports': [], 'closed_ports': []}
|
||||||
|
|
||||||
for port in uplink.ctx.Config.PORTS_TO_SCAN:
|
for port in uplink.ctx.Config.PORTS_TO_SCAN:
|
||||||
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM or socket.SOCK_NONBLOCK) as sock:
|
||||||
try:
|
try:
|
||||||
newSocket = ''
|
sock.settimeout(0.5)
|
||||||
newSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM or socket.SOCK_NONBLOCK)
|
|
||||||
newSocket.settimeout(0.5)
|
|
||||||
|
|
||||||
connection = (remote_ip, uplink.ctx.Base.int_if_possible(port))
|
connection = (remote_ip, uplink.ctx.Base.int_if_possible(port))
|
||||||
newSocket.connect(connection)
|
sock.connect(connection)
|
||||||
|
|
||||||
await p.send_priv_msg(
|
result['opened_ports'].append(port)
|
||||||
nick_from=uplink.ctx.Config.SERVICE_NICKNAME,
|
uplink.ctx.Base.running_sockets.append(sock)
|
||||||
msg=f"[ {uplink.ctx.Config.COLORS.red}PROXY_SCAN{uplink.ctx.Config.COLORS.nogc} ] {fullname} ({remote_ip}) : Port [{str(port)}] ouvert sur l'adresse ip [{remote_ip}]",
|
sock.shutdown(socket.SHUT_RDWR)
|
||||||
channel=uplink.ctx.Config.SERVICE_CHANLOG
|
uplink.ctx.Base.running_sockets.remove(sock)
|
||||||
)
|
return result
|
||||||
# print(f"=======> Le port {str(port)} est ouvert !!")
|
|
||||||
uplink.ctx.Base.running_sockets.append(newSocket)
|
|
||||||
# print(newSocket)
|
|
||||||
newSocket.shutdown(socket.SHUT_RDWR)
|
|
||||||
newSocket.close()
|
|
||||||
|
|
||||||
except (socket.timeout, ConnectionRefusedError):
|
except (socket.timeout, ConnectionRefusedError):
|
||||||
uplink.ctx.Logs.info(f"Le port {remote_ip}:{str(port)} est fermé")
|
uplink.ctx.Logs.debug(f"[LOCAL SCAN] Port {remote_ip}:{str(port)} is close.")
|
||||||
|
result['closed_ports'].append(port)
|
||||||
except AttributeError as ae:
|
except AttributeError as ae:
|
||||||
uplink.ctx.Logs.warning(f"AttributeError ({remote_ip}): {ae}")
|
uplink.ctx.Logs.warning(f"AttributeError ({remote_ip}): {ae}")
|
||||||
except socket.gaierror as err:
|
except socket.gaierror as err:
|
||||||
uplink.ctx.Logs.warning(f"Address Info Error ({remote_ip}): {err}")
|
uplink.ctx.Logs.warning(f"Address Info Error ({remote_ip}): {err}")
|
||||||
finally:
|
|
||||||
# newSocket.shutdown(socket.SHUT_RDWR)
|
|
||||||
newSocket.close()
|
|
||||||
uplink.ctx.Logs.info('=======> Fermeture de la socket')
|
|
||||||
|
|
||||||
async def action_scan_client_with_psutil(uplink: 'Defender', user_model: 'MUser') -> list[int]:
|
return result
|
||||||
|
|
||||||
|
def action_scan_client_with_psutil(uplink: 'Defender', user_model: 'MUser') -> list[int]:
|
||||||
"""psutil_scan for Linux (should be run on the same location as the unrealircd server)
|
"""psutil_scan for Linux (should be run on the same location as the unrealircd server)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -695,28 +601,16 @@ async def action_scan_client_with_psutil(uplink: 'Defender', user_model: 'MUser'
|
|||||||
Returns:
|
Returns:
|
||||||
list[int]: list of ports
|
list[int]: list of ports
|
||||||
"""
|
"""
|
||||||
p = uplink.ctx.Irc.Protocol
|
|
||||||
remote_ip = user_model.remote_ip
|
remote_ip = user_model.remote_ip
|
||||||
username = user_model.username
|
|
||||||
hostname = user_model.hostname
|
|
||||||
nickname = user_model.nickname
|
|
||||||
|
|
||||||
if remote_ip in uplink.ctx.Config.WHITELISTED_IP:
|
if remote_ip in uplink.ctx.Config.WHITELISTED_IP:
|
||||||
return None
|
return None
|
||||||
|
if uplink.mod_config.psutil_scan == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
connections = psutil.net_connections(kind='inet')
|
connections = psutil.net_connections(kind='inet')
|
||||||
fullname = f'{nickname}!{username}@{hostname}'
|
|
||||||
|
|
||||||
matching_ports = [conn.raddr.port for conn in connections if conn.raddr and conn.raddr.ip == remote_ip]
|
matching_ports = [conn.raddr.port for conn in connections if conn.raddr and conn.raddr.ip == remote_ip]
|
||||||
uplink.ctx.Logs.info(f"Connexion of {fullname} ({remote_ip}) using ports : {str(matching_ports)}")
|
uplink.ctx.Logs.debug(f"Connexion of ({remote_ip}) using ports : {str(matching_ports)}")
|
||||||
|
|
||||||
if matching_ports:
|
|
||||||
await p.send_priv_msg(
|
|
||||||
nick_from=uplink.ctx.Config.SERVICE_NICKNAME,
|
|
||||||
msg=f"[ {uplink.ctx.Config.COLORS.red}PSUTIL_SCAN{uplink.ctx.Config.COLORS.black} ] {fullname} ({remote_ip}) : is using ports {matching_ports}",
|
|
||||||
channel=uplink.ctx.Config.SERVICE_CHANLOG
|
|
||||||
)
|
|
||||||
|
|
||||||
return matching_ports
|
return matching_ports
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import asyncio
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
|||||||
Reference in New Issue
Block a user