10 Commits

Author SHA1 Message Date
adator
66ea492593 removing old code 2024-09-16 00:57:27 +02:00
adator
d459fd662f Changing hostname modification 2024-09-16 00:41:43 +02:00
adator
5d3a2b0e64 Changing Proxy_scan to PSUTIL_scan 2024-09-15 23:32:44 +02:00
adator
2f681db2d7 Adding Geoip to the UserModel 2024-09-15 23:29:32 +02:00
adator
7585db4f62 V5.2.2 2024-09-15 22:39:34 +02:00
adator
1984511db8 V5.2.1 2024-09-15 03:08:49 +02:00
adator
ce47739a93 update mode clone 2024-09-15 02:49:42 +02:00
adator
c7047ec3d6 V5.2.0 2024-09-15 02:03:38 +02:00
adator
eddba81cf0 remove mod_jsonrpc.py 2024-09-14 01:32:16 +02:00
adator
59e634951f V5.1.9 2024-09-14 01:25:13 +02:00
12 changed files with 392 additions and 446 deletions

4
.gitignore vendored
View File

@@ -2,7 +2,7 @@
db/ db/
logs/ logs/
__pycache__/ __pycache__/
mods/mod_jsonrpc.py
configuration.json configuration.json
install.log *.log
test.py test.py
# mods/mod_ia.py

View File

@@ -10,12 +10,15 @@ class User:
uid: str uid: str
nickname: str nickname: str
username: str username: str
realname: str
hostname: str hostname: str
umodes: str umodes: str
vhost: str vhost: str
isWebirc: bool isWebirc: bool
isWebsocket: bool
remote_ip: str remote_ip: str
score_connexion: int score_connexion: int
geoip: str = None
connexion_datetime: datetime = field(default=datetime.now()) connexion_datetime: datetime = field(default=datetime.now())
UID_DB: list[UserModel] = [] UID_DB: list[UserModel] = []
@@ -410,6 +413,8 @@ class Clones:
alive: bool alive: bool
nickname: str nickname: str
username: str username: str
realname: str
connected: bool = False
UID_CLONE_DB: list[CloneModel] = [] UID_CLONE_DB: list[CloneModel] = []

View File

@@ -218,7 +218,7 @@ class Base:
"""Supprime les modules de la base de données """Supprime les modules de la base de données
Args: Args:
cmd (str): le module a enregistrer cmd (str): le module a supprimer
""" """
insert_cmd_query = f"DELETE FROM {self.Config.table_module} WHERE module_name = :module_name" insert_cmd_query = f"DELETE FROM {self.Config.table_module} WHERE module_name = :module_name"
mes_donnees = {'module_name': module_name} mes_donnees = {'module_name': module_name}

View File

@@ -7,13 +7,15 @@ from typing import Union
class Connection: class Connection:
def __init__(self, server_port: int, nickname: str, username: str, channels:list[str], CloneObject: Clones, ssl:bool = False) -> None: def __init__(self, server_port: int, nickname: str, username: str, realname: str, channels:list[str], CloneObject: Clones, ssl:bool = False) -> None:
self.Config = Config().ConfigObject self.Config = Config().ConfigObject
self.Base = Base(self.Config) self.Base = Base(self.Config)
self.IrcSocket: Union[socket.socket, SSLSocket] = None self.IrcSocket: Union[socket.socket, SSLSocket] = None
self.nickname = nickname self.nickname = nickname
self.username = username self.username = username
self.realname = realname
self.chanlog = '#clones'
self.channels:list[str] = channels self.channels:list[str] = channels
self.CHARSET = ['utf-8', 'iso-8859-1'] self.CHARSET = ['utf-8', 'iso-8859-1']
self.Clones = CloneObject self.Clones = CloneObject
@@ -97,10 +99,11 @@ class Connection:
try: try:
nickname = self.nickname nickname = self.nickname
username = self.username username = self.username
realname = self.realname
# Envoyer un message d'identification # Envoyer un message d'identification
writer.send(f"USER {nickname} {username} {username} {nickname} {username} :{username}\r\n".encode('utf-8')) writer.send(f"USER {nickname} {username} {username} {nickname} {username} :{username}\r\n".encode('utf-8'))
writer.send(f"USER {username} {username} {username} :{username}\r\n".encode('utf-8')) writer.send(f"USER {username} {username} {username} :{realname}\r\n".encode('utf-8'))
writer.send(f"NICK {nickname}\r\n".encode('utf-8')) writer.send(f"NICK {nickname}\r\n".encode('utf-8'))
self.Base.logs.debug('Link information sent to the server') self.Base.logs.debug('Link information sent to the server')
@@ -162,6 +165,7 @@ class Connection:
for data in cmd: for data in cmd:
response = data.decode(self.CHARSET[0]).split() response = data.decode(self.CHARSET[0]).split()
self.signal = self.currentCloneObject.alive self.signal = self.currentCloneObject.alive
current_clone_nickname = self.currentCloneObject.nickname
# print(response) # print(response)
match response[0]: match response[0]:
@@ -176,6 +180,7 @@ class Connection:
match response[1]: match response[1]:
case '376': case '376':
self.currentCloneObject.connected = True
for channel in self.channels: for channel in self.channels:
self.send2socket(f"JOIN {channel}") self.send2socket(f"JOIN {channel}")
return None return None
@@ -184,6 +189,14 @@ class Connection:
self.Base.logs.debug(f'{self.currentCloneObject.nickname} - {self.currentCloneObject.alive}') self.Base.logs.debug(f'{self.currentCloneObject.nickname} - {self.currentCloneObject.alive}')
fullname = str(response[0]).replace(':', '') fullname = str(response[0]).replace(':', '')
nickname = fullname.split('!')[0].replace(':','') nickname = fullname.split('!')[0].replace(':','')
if response[2] == current_clone_nickname:
message = []
for i in range(3, len(response)):
message.append(response[i])
final_message = ' '.join(message)
self.send2socket(f"PRIVMSG {self.chanlog} :{fullname} => {final_message[1:]}")
if nickname == self.Config.SERVICE_NICKNAME: if nickname == self.Config.SERVICE_NICKNAME:
command = str(response[3]).replace(':','') command = str(response[3]).replace(':','')

View File

@@ -36,8 +36,6 @@ class Install:
if self.skip_install: if self.skip_install:
return None return None
print(f'Configuration loaded : {self.config}')
# Sinon tester les dependances python et les installer avec pip # Sinon tester les dependances python et les installer avec pip
if self.do_install(): if self.do_install():

View File

@@ -453,6 +453,7 @@ class Irc:
except ModuleNotFoundError as moduleNotFound: except ModuleNotFoundError as moduleNotFound:
self.Base.logs.error(f"MODULE_NOT_FOUND: {moduleNotFound}") self.Base.logs.error(f"MODULE_NOT_FOUND: {moduleNotFound}")
self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :[ {self.Config.CONFIG_COLOR['rouge']}MODULE_NOT_FOUND{self.Config.CONFIG_COLOR['noire']} ]: {moduleNotFound}") self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :[ {self.Config.CONFIG_COLOR['rouge']}MODULE_NOT_FOUND{self.Config.CONFIG_COLOR['noire']} ]: {moduleNotFound}")
self.Base.db_delete_module(module_name)
except Exception as e: except Exception as e:
self.Base.logs.error(f"Something went wrong with a module you want to load : {e}") self.Base.logs.error(f"Something went wrong with a module you want to load : {e}")
self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :[ {self.Config.CONFIG_COLOR['rouge']}ERROR{self.Config.CONFIG_COLOR['noire']} ]: {e}") self.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :[ {self.Config.CONFIG_COLOR['rouge']}ERROR{self.Config.CONFIG_COLOR['noire']} ]: {e}")
@@ -812,13 +813,13 @@ class Irc:
self.Base.logs.error(f'Index Error: {ie}') self.Base.logs.error(f'Index Error: {ie}')
case 'UID': case 'UID':
try:
# ['@s2s-md/geoip=cc=GB|cd=United\\sKingdom|asn=16276|asname=OVH\\sSAS;s2s-md/tls_cipher=TLSv1.3-TLS_CHACHA20_POLY1305_SHA256;s2s-md/creationtime=1721564601', # ['@s2s-md/geoip=cc=GB|cd=United\\sKingdom|asn=16276|asname=OVH\\sSAS;s2s-md/tls_cipher=TLSv1.3-TLS_CHACHA20_POLY1305_SHA256;s2s-md/creationtime=1721564601',
# ':001', 'UID', 'albatros', '0', '1721564597', 'albatros', 'vps-91b2f28b.vps.ovh.net', # ':001', 'UID', 'albatros', '0', '1721564597', 'albatros', 'vps-91b2f28b.vps.ovh.net',
# '001HB8G04', '0', '+iwxz', 'Clk-A62F1D18.vps.ovh.net', 'Clk-A62F1D18.vps.ovh.net', 'MyZBwg==', ':...'] # '001HB8G04', '0', '+iwxz', 'Clk-A62F1D18.vps.ovh.net', 'Clk-A62F1D18.vps.ovh.net', 'MyZBwg==', ':...']
if 'webirc' in original_response[0]:
isWebirc = True isWebirc = True if 'webirc' in original_response[0] else False
else: isWebsocket = True if 'websocket' in original_response[0] else False
isWebirc = False
uid = str(original_response[8]) uid = str(original_response[8])
nickname = str(original_response[3]) nickname = str(original_response[3])
@@ -826,11 +827,28 @@ class Irc:
hostname = str(original_response[7]) hostname = str(original_response[7])
umodes = str(original_response[10]) umodes = str(original_response[10])
vhost = str(original_response[11]) vhost = str(original_response[11])
if not 'S' in umodes: if not 'S' in umodes:
remote_ip = self.Base.decode_ip(str(original_response[13])) remote_ip = self.Base.decode_ip(str(original_response[13]))
else: else:
remote_ip = '127.0.0.1' remote_ip = '127.0.0.1'
# extract realname
realname_list = []
for i in range(14, len(original_response)):
realname_list.append(original_response[i])
realname = ' '.join(realname_list)[1:]
# Extract Geoip information
pattern = r'^.*geoip=cc=(\S{2}).*$'
geoip_match = re.match(pattern, original_response[0])
if geoip_match:
geoip = geoip_match.group(1)
else:
geoip = None
score_connexion = self.first_score score_connexion = self.first_score
self.User.insert( self.User.insert(
@@ -838,11 +856,14 @@ class Irc:
uid=uid, uid=uid,
nickname=nickname, nickname=nickname,
username=username, username=username,
realname=realname,
hostname=hostname, hostname=hostname,
umodes=umodes, umodes=umodes,
vhost=vhost, vhost=vhost,
isWebirc=isWebirc, isWebirc=isWebirc,
isWebsocket=isWebsocket,
remote_ip=remote_ip, remote_ip=remote_ip,
geoip=geoip,
score_connexion=score_connexion, score_connexion=score_connexion,
connexion_datetime=datetime.now() connexion_datetime=datetime.now()
) )
@@ -851,6 +872,9 @@ class Irc:
for classe_name, classe_object in self.loaded_classes.items(): for classe_name, classe_object in self.loaded_classes.items():
classe_object.cmd(original_response) classe_object.cmd(original_response)
except Exception as err:
self.Base.logs.error(f'General Error: {err}')
case 'PRIVMSG': case 'PRIVMSG':
try: try:
# Supprimer la premiere valeur # Supprimer la premiere valeur
@@ -1341,7 +1365,7 @@ class Irc:
case 'show_users': case 'show_users':
for db_user in self.User.UID_DB: for db_user in self.User.UID_DB:
self.send2socket(f":{dnickname} NOTICE {fromuser} :UID : {db_user.uid} - isWebirc: {db_user.isWebirc} - Nickname: {db_user.nickname} - Connection: {db_user.connexion_datetime}") self.send2socket(f":{dnickname} NOTICE {fromuser} :UID : {db_user.uid} - isWebirc: {db_user.isWebirc} - isWebSocket: {db_user.isWebsocket} - Nickname: {db_user.nickname} - Connection: {db_user.connexion_datetime}")
case 'show_admins': case 'show_admins':
for db_admin in self.Admin.UID_ADMIN_DB: for db_admin in self.Admin.UID_ADMIN_DB:

View File

@@ -122,9 +122,26 @@ class Clone():
return None return None
def thread_create_clones(self, nickname: str, username: str, channels: list, server_port: int, ssl: bool) -> None: def thread_change_hostname(self):
Connection(server_port=server_port, nickname=nickname, username=username, channels=channels, CloneObject=self.Clone, ssl=ssl) fake = faker.Faker('en_GB')
for clone in self.Clone.UID_CLONE_DB:
rand_1 = fake.random_elements(['A','B','C','D','E','F','0','1','2','3','4','5','6','7','8','9'], unique=True, length=8)
rand_2 = fake.random_elements(['A','B','C','D','E','F','0','1','2','3','4','5','6','7','8','9'], unique=True, length=8)
rand_3 = fake.random_elements(['A','B','C','D','E','F','0','1','2','3','4','5','6','7','8','9'], unique=True, length=8)
rand_ip = ''.join(rand_1) + '.' + ''.join(rand_2) + '.' + ''.join(rand_3) + '.IP'
found = False
while not found:
if clone.connected:
self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} CHGHOST {clone.nickname} {rand_ip}')
found = True
break
def thread_create_clones(self, nickname: str, username: str, realname: str, channels: list, server_port: int, ssl: bool) -> None:
Connection(server_port=server_port, nickname=nickname, username=username, realname=realname, channels=channels, CloneObject=self.Clone, ssl=ssl)
return None return None
@@ -140,33 +157,38 @@ class Clone():
self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone.nickname} :JOIN {channel_name}') self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone.nickname} :JOIN {channel_name}')
time.sleep(wait) time.sleep(wait)
def generate_names(self) -> tuple[str, str]: def generate_names(self) -> tuple[str, str, str]:
try: try:
fake = faker.Faker('en_GB') fake = faker.Faker('en_GB')
nickname = fake.first_name() nickname = fake.first_name()
username = fake.last_name() # username = fake.last_name()
# Generate Username
chaine = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
new_username = fake.random_sample(chaine, 9)
username = ''.join(new_username)
# Create realname XX F|M Department
gender = fake.random_choices(['F','M'], 1)
gender = ''.join(gender)
age = random.randint(20, 60)
fake_fr = faker.Faker(['fr_FR', 'en_GB'])
department = fake_fr.department_name()
realname = f'{age} {gender} {department}'
if self.Clone.exists(nickname=nickname): if self.Clone.exists(nickname=nickname):
caracteres = '0123456789' caracteres = '0123456789'
randomize = ''.join(random.choice(caracteres) for _ in range(2)) randomize = ''.join(random.choice(caracteres) for _ in range(2))
nickname = nickname + str(randomize) nickname = nickname + str(randomize)
self.Clone.insert( self.Clone.insert(
self.Clone.CloneModel(alive=True, nickname=nickname, username=username) self.Clone.CloneModel(alive=True, nickname=nickname, username=username, realname=realname)
) )
else: else:
self.Clone.insert( self.Clone.insert(
self.Clone.CloneModel(alive=True, nickname=nickname, username=username) self.Clone.CloneModel(alive=True, nickname=nickname, username=username, realname=realname)
) )
# if not nickname in self.ModConfig.clone_nicknames: return (nickname, username, realname)
# self.ModConfig.clone_nicknames.append(nickname)
# else:
# caracteres = '0123456789'
# randomize = ''.join(random.choice(caracteres) for _ in range(2))
# nickname = nickname + str(randomize)
# self.ModConfig.clone_nicknames.append(nickname)
return (nickname, username)
except AttributeError as ae: except AttributeError as ae:
self.Logs.error(f'Attribute Error : {ae}') self.Logs.error(f'Attribute Error : {ae}')
@@ -188,6 +210,7 @@ class Clone():
def _hcmds(self, user:str, channel: any, cmd: list, fullcmd: list = []) -> None: def _hcmds(self, user:str, channel: any, cmd: list, fullcmd: list = []) -> None:
try:
command = str(cmd[0]).lower() command = str(cmd[0]).lower()
fromuser = user fromuser = user
@@ -196,27 +219,34 @@ class Clone():
match command: match command:
case 'clone': case 'clone':
option = str(cmd[1]).lower()
if len(command) == 1: if len(cmd) == 1:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} clone connect 6') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} clone connect 6')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} clone kill [all | nickname]') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} clone kill [all | nickname]')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} clone join [all | nickname] #channel') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} clone join [all | nickname] #channel')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} clone list') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} clone list')
option = str(cmd[1]).lower()
match option: match option:
case 'connect': case 'connect':
try: try:
number_of_clones = int(cmd[2]) number_of_clones = int(cmd[2])
for i in range(number_of_clones): for i in range(number_of_clones):
nickname, username = self.generate_names() nickname, username, realname = self.generate_names()
self.Base.create_thread( self.Base.create_thread(
self.thread_create_clones, self.thread_create_clones,
(nickname, username, [], 6697, True) (nickname, username, realname, ['#clones'], 6697, True)
)
self.Base.create_thread(
self.thread_change_hostname,
run_once=True
) )
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :{str(number_of_clones)} clones joined the network') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :{str(number_of_clones)} clones joined the network')
except Exception as err: except Exception as err:
self.Logs.error(f'{err}') self.Logs.error(f'{err}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} clone connect [number of clone you want to connect]') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} clone connect [number of clone you want to connect]')
@@ -269,8 +299,7 @@ class Clone():
case 'list': case 'list':
try: try:
for clone_name in self.Clone.UID_CLONE_DB: for clone_name in self.Clone.UID_CLONE_DB:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :>> {clone_name.nickname} | {clone_name.username}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :>> Nickname: {clone_name.nickname} | Username: {clone_name.username}')
pass
except Exception as err: except Exception as err:
self.Logs.error(f'{err}') self.Logs.error(f'{err}')
@@ -302,3 +331,7 @@ class Clone():
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} clone join [all | nickname] #channel') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} clone join [all | nickname] #channel')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} clone say [clone_nickname] #channel [message]') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} clone say [clone_nickname] #channel [message]')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} clone list') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :/msg {dnickname} clone list')
except IndexError as ie:
self.Logs.error(f'Index Error: {ie}')
except Exception as err:
self.Logs.error(f'Index Error: {err}')

View File

@@ -4,6 +4,7 @@ from typing import Union
import re, socket, psutil, requests, json, time import re, socket, psutil, requests, json, time
from sys import exit from sys import exit
from core.irc import Irc from core.irc import Irc
from core.Model import User
# Le module crée devra réspecter quelques conditions # Le module crée devra réspecter quelques conditions
# 1. Le nom de la classe devra toujours s'appeler comme le module. Exemple => nom de class Defender | nom du module mod_defender # 1. Le nom de la classe devra toujours s'appeler comme le module. Exemple => nom de class Defender | nom du module mod_defender
@@ -43,11 +44,13 @@ class Defender():
nickname: str nickname: str
username: str username: str
hostname: str hostname: str
realname: str
umodes: str umodes: str
vhost: str vhost: str
ip: str ip: str
score: int score: int
isWebirc: bool isWebirc: bool
isWebsocket: bool
secret_code: str secret_code: str
connected_datetime: str connected_datetime: str
updated_datetime: str updated_datetime: str
@@ -107,12 +110,13 @@ class Defender():
# self.join_saved_channels() # self.join_saved_channels()
self.timeout = self.Config.API_TIMEOUT self.timeout = self.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.freeipapi_remote_ip:list = [] self.abuseipdb_UserModel: list[User.UserModel] = []
self.cloudfilt_remote_ip:list = [] self.freeipapi_UserModel: list[User.UserModel] = []
self.abuseipdb_remote_ip:list = [] self.cloudfilt_UserModel: list[User.UserModel] = []
self.psutil_remote_ip:list = [] self.psutil_UserModel: list[User.UserModel] = []
self.localscan_remote_ip:list = [] self.localscan_UserModel: list[User.UserModel] = []
# 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:bool = True self.abuseipdb_isRunning:bool = True
@@ -226,11 +230,11 @@ class Defender():
"""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
""" """
self.abuseipdb_remote_ip:list = [] # Liste qui va contenir les adresses ip a scanner avec abuseipdb self.abuseipdb_UserModel: list[User.UserModel] = []
self.freeipapi_remote_ip:list = [] # Liste qui va contenir les adresses ip a scanner avec freeipapi self.freeipapi_UserModel: list[User.UserModel] = []
self.cloudfilt_remote_ip:list = [] # Liste qui va contenir les adresses ip a scanner avec cloudfilt self.cloudfilt_UserModel: list[User.UserModel] = []
self.psutil_remote_ip:list = [] # Liste qui va contenir les adresses ip a scanner avec psutil_scan self.psutil_UserModel: list[User.UserModel] = []
self.localscan_remote_ip:list = [] # Liste qui va contenir les adresses ip a scanner avec local_scan self.localscan_UserModel: list[User.UserModel] = []
self.abuseipdb_isRunning:bool = False self.abuseipdb_isRunning:bool = False
self.freeipapi_isRunning:bool = False self.freeipapi_isRunning:bool = False
@@ -605,28 +609,38 @@ class Defender():
return None return None
def scan_ports(self, remote_ip: str) -> None: def scan_ports(self, userModel: User.UserModel) -> None:
"""local_scan """local_scan
Args: Args:
remote_ip (str): _description_ userModel (UserModel): _description_
""" """
User = userModel
remote_ip = User.remote_ip
username = User.username
hostname = User.hostname
nickname = User.nickname
fullname = f'{nickname}!{username}@{hostname}'
if remote_ip in self.Config.WHITELISTED_IP: if remote_ip in self.Config.WHITELISTED_IP:
return None return None
for port in self.Config.PORTS_TO_SCAN: for port in self.Config.PORTS_TO_SCAN:
try:
newSocket = '' newSocket = ''
newSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM or socket.SOCK_NONBLOCK) newSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM or socket.SOCK_NONBLOCK)
newSocket.settimeout(0.5) newSocket.settimeout(0.5)
try:
connection = (remote_ip, self.Base.int_if_possible(port)) connection = (remote_ip, self.Base.int_if_possible(port))
newSocket.connect(connection) newSocket.connect(connection)
self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :[ {self.Config.CONFIG_COLOR['rouge']}PROXY_SCAN{self.Config.CONFIG_COLOR['noire']} ] : Port [{str(port)}] ouvert sur l'adresse ip [{remote_ip}]")
self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :[ {self.Config.CONFIG_COLOR['rouge']}PROXY_SCAN{self.Config.CONFIG_COLOR['noire']} ] {fullname} ({remote_ip}) : Port [{str(port)}] ouvert sur l'adresse ip [{remote_ip}]")
# print(f"=======> Le port {str(port)} est ouvert !!") # print(f"=======> Le port {str(port)} est ouvert !!")
self.Base.running_sockets.append(newSocket) self.Base.running_sockets.append(newSocket)
# print(newSocket) # print(newSocket)
newSocket.shutdown(socket.SHUT_RDWR) newSocket.shutdown(socket.SHUT_RDWR)
newSocket.close() newSocket.close()
except (socket.timeout, ConnectionRefusedError): except (socket.timeout, ConnectionRefusedError):
self.Logs.info(f"Le port {remote_ip}:{str(port)} est fermé") self.Logs.info(f"Le port {remote_ip}:{str(port)} est fermé")
except AttributeError as ae: except AttributeError as ae:
@@ -638,20 +652,18 @@ class Defender():
newSocket.close() newSocket.close()
self.Logs.info('=======> Fermeture de la socket') self.Logs.info('=======> Fermeture de la socket')
pass
def thread_local_scan(self) -> None: def thread_local_scan(self) -> None:
try: try:
while self.localscan_isRunning: while self.localscan_isRunning:
list_to_remove:list = [] list_to_remove:list = []
for ip in self.localscan_remote_ip: for user in self.localscan_UserModel:
self.scan_ports(ip) self.scan_ports(user)
list_to_remove.append(ip) list_to_remove.append(user)
time.sleep(1) time.sleep(1)
for ip_to_remove in list_to_remove: for user_model in list_to_remove:
self.localscan_remote_ip.remove(ip_to_remove) self.localscan_UserModel.remove(user_model)
time.sleep(1) time.sleep(1)
@@ -659,23 +671,33 @@ class Defender():
except ValueError as ve: except ValueError as ve:
self.Logs.warning(f"thread_local_scan Error : {ve}") self.Logs.warning(f"thread_local_scan Error : {ve}")
def get_ports_connexion(self, remote_ip: str) -> list[int]: def get_ports_connexion(self, userModel: User.UserModel) -> list[int]:
"""psutil_scan for Linux """psutil_scan for Linux (should be run on the same location as the unrealircd server)
Args: Args:
remote_ip (str): The remote ip address userModel (UserModel): The User Model Object
Returns: Returns:
list[int]: list of ports list[int]: list of ports
""" """
try: try:
User = userModel
remote_ip = User.remote_ip
username = User.username
hostname = User.hostname
nickname = User.nickname
if remote_ip in self.Config.WHITELISTED_IP: if remote_ip in self.Config.WHITELISTED_IP:
return None return None
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]
self.Logs.info(f"Connexion of {remote_ip} using ports : {str(matching_ports)}") self.Logs.info(f"Connexion of {fullname} ({remote_ip}) using ports : {str(matching_ports)}")
if matching_ports:
self.Irc.send2socket(f":{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :[ {self.Config.CONFIG_COLOR['rouge']}PSUTIL_SCAN{self.Config.CONFIG_COLOR['noire']} ] {fullname} ({remote_ip}) : is using ports {matching_ports}")
return matching_ports return matching_ports
@@ -688,13 +710,13 @@ class Defender():
while self.psutil_isRunning: while self.psutil_isRunning:
list_to_remove:list = [] list_to_remove:list = []
for ip in self.psutil_remote_ip: for user in self.psutil_UserModel:
self.get_ports_connexion(ip) self.get_ports_connexion(user)
list_to_remove.append(ip) list_to_remove.append(user)
time.sleep(1) time.sleep(1)
for ip_to_remove in list_to_remove: for user_model in list_to_remove:
self.psutil_remote_ip.remove(ip_to_remove) self.psutil_UserModel.remove(user_model)
time.sleep(1) time.sleep(1)
@@ -702,16 +724,22 @@ class Defender():
except ValueError as ve: except ValueError as ve:
self.Logs.warning(f"thread_psutil_scan Error : {ve}") self.Logs.warning(f"thread_psutil_scan Error : {ve}")
def abuseipdb_scan(self, remote_ip:str) -> Union[dict[str, any], None]: def abuseipdb_scan(self, userModel: User.UserModel) -> Union[dict[str, any], None]:
"""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:
remote_ip (_type_): l'ip a analyser userModel (UserModel): l'objet User qui contient l'ip
Returns: Returns:
dict[str, any] | None: les informations du provider dict[str, any] | None: les informations du provider
keys : 'score', 'country', 'isTor', 'totalReports' keys : 'score', 'country', 'isTor', 'totalReports'
""" """
User = userModel
remote_ip = User.remote_ip
username = User.username
hostname = User.hostname
nickname = User.nickname
if remote_ip in self.Config.WHITELISTED_IP: if remote_ip in self.Config.WHITELISTED_IP:
return None return None
if self.ModConfig.abuseipdb_scan == 0: if self.ModConfig.abuseipdb_scan == 0:
@@ -731,11 +759,12 @@ class Defender():
'Key': self.abuseipdb_key 'Key': self.abuseipdb_key
} }
try:
response = requests.request(method='GET', url=url, headers=headers, params=querystring, timeout=self.timeout) response = requests.request(method='GET', url=url, headers=headers, params=querystring, timeout=self.timeout)
# Formatted output # Formatted output
decodedResponse = json.loads(response.text) decodedResponse = json.loads(response.text)
try:
if not 'data' in decodedResponse: if not 'data' in decodedResponse:
return None return None
@@ -751,7 +780,10 @@ class Defender():
color_red = self.Config.CONFIG_COLOR['rouge'] color_red = self.Config.CONFIG_COLOR['rouge']
color_black = self.Config.CONFIG_COLOR['noire'] color_black = self.Config.CONFIG_COLOR['noire']
self.Irc.send2socket(f":{service_id} PRIVMSG {service_chanlog} :[ {color_red}ABUSEIPDB_SCAN{color_black} ] : Connexion de {remote_ip} ==> Score: {str(result['score'])} | Country : {result['country']} | Tor : {str(result['isTor'])} | Total Reports : {str(result['totalReports'])}") # pseudo!ident@host
fullname = f'{nickname}!{username}@{hostname}'
self.Irc.send2socket(f":{service_id} PRIVMSG {service_chanlog} :[ {color_red}ABUSEIPDB_SCAN{color_black} ] : Connexion de {fullname} ({remote_ip}) ==> Score: {str(result['score'])} | Country : {result['country']} | Tor : {str(result['isTor'])} | Total Reports : {str(result['totalReports'])}")
if result['isTor']: if result['isTor']:
self.Irc.send2socket(f":{service_id} GLINE +*@{remote_ip} {self.Config.GLINE_DURATION} This server do not allow Tor connexions {str(result['isTor'])} - Detected by Abuseipdb") self.Irc.send2socket(f":{service_id} GLINE +*@{remote_ip} {self.Config.GLINE_DURATION} This server do not allow Tor connexions {str(result['isTor'])} - Detected by Abuseipdb")
@@ -767,6 +799,8 @@ class Defender():
self.Logs.error(f"AbuseIpDb Timeout : {rt}") self.Logs.error(f"AbuseIpDb Timeout : {rt}")
except requests.ConnectionError as ce: except requests.ConnectionError as ce:
self.Logs.error(f"AbuseIpDb Connection Error : {ce}") self.Logs.error(f"AbuseIpDb Connection Error : {ce}")
except Exception as err:
self.Logs.error(f"General Error Abuseipdb : {err}")
def thread_abuseipdb_scan(self) -> None: def thread_abuseipdb_scan(self) -> None:
try: try:
@@ -774,13 +808,13 @@ class Defender():
while self.abuseipdb_isRunning: while self.abuseipdb_isRunning:
list_to_remove: list = [] list_to_remove: list = []
for ip in self.abuseipdb_remote_ip: for user in self.abuseipdb_UserModel:
self.abuseipdb_scan(ip) self.abuseipdb_scan(user)
list_to_remove.append(ip) list_to_remove.append(user)
time.sleep(1) time.sleep(1)
for ip_to_remove in list_to_remove: for user_model in list_to_remove:
self.abuseipdb_remote_ip.remove(ip_to_remove) self.abuseipdb_UserModel.remove(user_model)
time.sleep(1) time.sleep(1)
@@ -788,7 +822,7 @@ class Defender():
except ValueError as ve: except ValueError as ve:
self.Logs.error(f"thread_abuseipdb_scan Error : {ve}") self.Logs.error(f"thread_abuseipdb_scan Error : {ve}")
def freeipapi_scan(self, remote_ip:str) -> Union[dict[str, any], None]: def freeipapi_scan(self, userModel: User.UserModel) -> Union[dict[str, any], None]:
"""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:
@@ -798,6 +832,12 @@ class Defender():
dict[str, any] | None: les informations du provider dict[str, any] | None: les informations du provider
keys : 'countryCode', 'isProxy' keys : 'countryCode', 'isProxy'
""" """
User = userModel
remote_ip = User.remote_ip
username = User.username
hostname = User.hostname
nickname = User.nickname
if remote_ip in self.Config.WHITELISTED_IP: if remote_ip in self.Config.WHITELISTED_IP:
return None return None
if self.ModConfig.freeipapi_scan == 0: if self.ModConfig.freeipapi_scan == 0:
@@ -814,11 +854,12 @@ class Defender():
'Accept': 'application/json', 'Accept': 'application/json',
} }
try:
response = requests.request(method='GET', url=url, headers=headers, timeout=self.timeout) response = requests.request(method='GET', url=url, headers=headers, timeout=self.timeout)
# Formatted output # Formatted output
decodedResponse = json.loads(response.text) decodedResponse = json.loads(response.text)
try:
status_code = response.status_code status_code = response.status_code
if status_code == 429: if status_code == 429:
self.Logs.warning(f'Too Many Requests - The rate limit for the API has been exceeded.') self.Logs.warning(f'Too Many Requests - The rate limit for the API has been exceeded.')
@@ -832,7 +873,10 @@ class Defender():
'isProxy': decodedResponse['isProxy'] if 'isProxy' in decodedResponse else None 'isProxy': decodedResponse['isProxy'] if 'isProxy' in decodedResponse else None
} }
self.Irc.send2socket(f":{service_id} PRIVMSG {service_chanlog} :[ {color_red}FREEIPAPI_SCAN{color_black} ] : Connexion de {remote_ip} ==> Proxy: {str(result['isProxy'])} | Country : {str(result['countryCode'])}") # pseudo!ident@host
fullname = f'{nickname}!{username}@{hostname}'
self.Irc.send2socket(f":{service_id} PRIVMSG {service_chanlog} :[ {color_red}FREEIPAPI_SCAN{color_black} ] : Connexion de {fullname} ({remote_ip}) ==> Proxy: {str(result['isProxy'])} | Country : {str(result['countryCode'])}")
if result['isProxy']: if result['isProxy']:
self.Irc.send2socket(f":{service_id} GLINE +*@{remote_ip} {self.Config.GLINE_DURATION} This server do not allow proxy connexions {str(result['isProxy'])} - detected by freeipapi") self.Irc.send2socket(f":{service_id} GLINE +*@{remote_ip} {self.Config.GLINE_DURATION} This server do not allow proxy connexions {str(result['isProxy'])} - detected by freeipapi")
@@ -841,20 +885,22 @@ class Defender():
return result return result
except KeyError as ke: except KeyError as ke:
self.Logs.error(f"FREEIPAPI_SCAN KeyError : {ke}") self.Logs.error(f"FREEIPAPI_SCAN KeyError : {ke}")
except Exception as err:
self.Logs.error(f"General Error Freeipapi : {err}")
def thread_freeipapi_scan(self) -> None: def thread_freeipapi_scan(self) -> None:
try: try:
while self.freeipapi_isRunning: while self.freeipapi_isRunning:
list_to_remove:list = [] list_to_remove: list[User.UserModel] = []
for ip in self.freeipapi_remote_ip: for user in self.freeipapi_UserModel:
self.freeipapi_scan(ip) self.freeipapi_scan(user)
list_to_remove.append(ip) list_to_remove.append(user)
time.sleep(1) time.sleep(1)
for ip_to_remove in list_to_remove: for user_model in list_to_remove:
self.freeipapi_remote_ip.remove(ip_to_remove) self.freeipapi_UserModel.remove(user_model)
time.sleep(1) time.sleep(1)
@@ -862,7 +908,7 @@ class Defender():
except ValueError as ve: except ValueError as ve:
self.Logs.error(f"thread_freeipapi_scan Error : {ve}") self.Logs.error(f"thread_freeipapi_scan Error : {ve}")
def cloudfilt_scan(self, remote_ip:str) -> Union[dict[str, any], None]: def cloudfilt_scan(self, userModel: User.UserModel) -> Union[dict[str, any], None]:
"""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:
@@ -872,6 +918,12 @@ class Defender():
dict[str, any] | None: les informations du provider dict[str, any] | None: les informations du provider
keys : 'countryCode', 'isProxy' keys : 'countryCode', 'isProxy'
""" """
User = userModel
remote_ip = User.remote_ip
username = User.username
hostname = User.hostname
nickname = User.nickname
if remote_ip in self.Config.WHITELISTED_IP: if remote_ip in self.Config.WHITELISTED_IP:
return None return None
if self.ModConfig.cloudfilt_scan == 0: if self.ModConfig.cloudfilt_scan == 0:
@@ -891,11 +943,10 @@ class Defender():
'key': self.cloudfilt_key 'key': self.cloudfilt_key
} }
try:
response = requests.post(url=url, data=data) response = requests.post(url=url, data=data)
# Formatted output # Formatted output
decodedResponse = json.loads(response.text) decodedResponse = json.loads(response.text)
try:
status_code = response.status_code status_code = response.status_code
if status_code != 200: if status_code != 200:
self.Logs.warning(f'Error connecting to cloudfilt API | Code: {str(status_code)}') self.Logs.warning(f'Error connecting to cloudfilt API | Code: {str(status_code)}')
@@ -908,7 +959,10 @@ class Defender():
'host': decodedResponse['host'] if 'host' in decodedResponse else None 'host': decodedResponse['host'] if 'host' in decodedResponse else None
} }
self.Irc.send2socket(f":{service_id} PRIVMSG {service_chanlog} :[ {color_red}CLOUDFILT_SCAN{color_black} ] : Connexion de {str(remote_ip)} ==> Host: {str(result['host'])} | country: {str(result['countryiso'])} | listed: {str(result['listed'])} | listed by : {str(result['listed_by'])}") # pseudo!ident@host
fullname = f'{nickname}!{username}@{hostname}'
self.Irc.send2socket(f":{service_id} PRIVMSG {service_chanlog} :[ {color_red}CLOUDFILT_SCAN{color_black} ] : Connexion de {fullname} ({remote_ip}) ==> Host: {str(result['host'])} | country: {str(result['countryiso'])} | listed: {str(result['listed'])} | listed by : {str(result['listed_by'])}")
if result['listed']: if result['listed']:
self.Irc.send2socket(f":{service_id} GLINE +*@{remote_ip} {self.Config.GLINE_DURATION} You connexion is listed as dangerous {str(result['listed'])} {str(result['listed_by'])} - detected by cloudfilt") self.Irc.send2socket(f":{service_id} GLINE +*@{remote_ip} {self.Config.GLINE_DURATION} You connexion is listed as dangerous {str(result['listed'])} {str(result['listed_by'])} - detected by cloudfilt")
@@ -926,13 +980,13 @@ class Defender():
while self.cloudfilt_isRunning: while self.cloudfilt_isRunning:
list_to_remove:list = [] list_to_remove:list = []
for ip in self.cloudfilt_remote_ip: for user in self.cloudfilt_UserModel:
self.cloudfilt_scan(ip) self.cloudfilt_scan(user)
list_to_remove.append(ip) list_to_remove.append(user)
time.sleep(1) time.sleep(1)
for ip_to_remove in list_to_remove: for user_model in list_to_remove:
self.cloudfilt_remote_ip.remove(ip_to_remove) self.cloudfilt_UserModel.remove(user_model)
time.sleep(1) time.sleep(1)
@@ -966,22 +1020,6 @@ class Defender():
if not self.Base.is_valid_ip(cmd[2]): if not self.Base.is_valid_ip(cmd[2]):
return None return None
# self.Base.scan_ports(cmd[2])
if self.ModConfig.local_scan == 1 and not cmd[2] in self.Config.WHITELISTED_IP:
self.localscan_remote_ip.append(cmd[2])
if self.ModConfig.psutil_scan == 1 and not cmd[2] in self.Config.WHITELISTED_IP:
self.psutil_remote_ip.append(cmd[2])
if self.ModConfig.abuseipdb_scan == 1 and not cmd[2] in self.Config.WHITELISTED_IP:
self.abuseipdb_remote_ip.append(cmd[2])
if self.ModConfig.freeipapi_scan == 1 and not cmd[2] in self.Config.WHITELISTED_IP:
self.freeipapi_remote_ip.append(cmd[2])
if self.ModConfig.cloudfilt_scan == 1 and not cmd[2] in self.Config.WHITELISTED_IP:
self.cloudfilt_remote_ip.append(cmd[2])
# Possibilité de déclancher les bans a ce niveau. # Possibilité de déclancher les bans a ce niveau.
except IndexError as ie: except IndexError as ie:
self.Logs.error(f'cmd reputation: index error: {ie}') self.Logs.error(f'cmd reputation: index error: {ie}')
@@ -1005,6 +1043,15 @@ class Defender():
# Get User information # Get User information
_User = self.User.get_User(str(cmd[7])) _User = self.User.get_User(str(cmd[7]))
# If user is not service or IrcOp then scan them
if not re.match(fr'^.*[S|o?].*$', _User.umodes):
self.abuseipdb_UserModel.append(_User) if self.ModConfig.abuseipdb_scan == 1 and not _User.remote_ip in self.Config.WHITELISTED_IP else None
self.freeipapi_UserModel.append(_User) if self.ModConfig.freeipapi_scan == 1 and not _User.remote_ip in self.Config.WHITELISTED_IP else None
self.cloudfilt_UserModel.append(_User) if self.ModConfig.cloudfilt_scan == 1 and not _User.remote_ip in self.Config.WHITELISTED_IP else None
self.psutil_UserModel.append(_User) if self.ModConfig.psutil_scan == 1 and not _User.remote_ip in self.Config.WHITELISTED_IP else None
self.localscan_UserModel.append(_User) if self.ModConfig.local_scan == 1 and not _User.remote_ip in self.Config.WHITELISTED_IP else None
if _User is None: if _User is None:
self.Logs.critical(f'This UID: [{cmd[7]}] is not available please check why') self.Logs.critical(f'This UID: [{cmd[7]}] is not available please check why')
return None return None
@@ -1019,9 +1066,9 @@ class Defender():
currentDateTime = self.Base.get_datetime() currentDateTime = self.Base.get_datetime()
self.reputation_insert( self.reputation_insert(
self.ReputationModel( self.ReputationModel(
uid=_User.uid, nickname=_User.nickname, username=_User.username, hostname=_User.hostname, uid=_User.uid, nickname=_User.nickname, username=_User.username, realname=_User.realname,
umodes=_User.umodes, vhost=_User.vhost, ip=_User.remote_ip, score=_User.score_connexion, hostname=_User.hostname, umodes=_User.umodes, vhost=_User.vhost, ip=_User.remote_ip, score=_User.score_connexion,
secret_code=self.Base.get_random(8), isWebirc=_User.isWebirc, connected_datetime=currentDateTime, secret_code=self.Base.get_random(8), isWebirc=_User.isWebirc, isWebsocket=_User.isWebsocket, connected_datetime=currentDateTime,
updated_datetime=currentDateTime updated_datetime=currentDateTime
) )
) )
@@ -1044,6 +1091,9 @@ class Defender():
get_reputation = self.reputation_get_Reputation(parsed_UID) get_reputation = self.reputation_get_Reputation(parsed_UID)
self.Irc.send2socket(f":{service_id} MODE {parsed_chan} +b ~security-group:unknown-users")
self.Irc.send2socket(f":{service_id} MODE {parsed_chan} +eee ~security-group:webirc-users ~security-group:known-users ~security-group:websocket-users")
if not get_reputation is None: if not get_reputation is None:
isWebirc = get_reputation.isWebirc isWebirc = get_reputation.isWebirc
@@ -1067,20 +1117,20 @@ class Defender():
if not self.Base.is_valid_ip(cmd[7]): if not self.Base.is_valid_ip(cmd[7]):
return None return None
if self.ModConfig.local_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP: # if self.ModConfig.local_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP:
self.localscan_remote_ip.append(cmd[7]) # self.localscan_remote_ip.append(cmd[7])
if self.ModConfig.psutil_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP: # if self.ModConfig.psutil_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP:
self.psutil_remote_ip.append(cmd[7]) # self.psutil_remote_ip.append(cmd[7])
if self.ModConfig.abuseipdb_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP: # if self.ModConfig.abuseipdb_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP:
self.abuseipdb_remote_ip.append(cmd[7]) # self.abuseipdb_remote_ip.append(cmd[7])
if self.ModConfig.freeipapi_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP: # if self.ModConfig.freeipapi_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP:
self.freeipapi_remote_ip.append(cmd[7]) # self.freeipapi_remote_ip.append(cmd[7])
if self.ModConfig.cloudfilt_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP: # if self.ModConfig.cloudfilt_scan == 1 and not cmd[7] in self.Config.WHITELISTED_IP:
self.cloudfilt_remote_ip.append(cmd[7]) # self.cloudfilt_remote_ip.append(cmd[7])
case 'NICK': case 'NICK':
# :0010BS24L NICK [NEWNICK] 1697917711 # :0010BS24L NICK [NEWNICK] 1697917711
@@ -1243,9 +1293,7 @@ class Defender():
for chan in self.Channel.UID_CHANNEL_DB: for chan in self.Channel.UID_CHANNEL_DB:
if chan.name != jail_chan: if chan.name != jail_chan:
self.Irc.send2socket(f":{service_id} MODE {chan.name} +b ~security-group:unknown-users") self.Irc.send2socket(f":{service_id} MODE {chan.name} +b ~security-group:unknown-users")
self.Irc.send2socket(f":{service_id} MODE {chan.name} +e ~security-group:webirc-users") self.Irc.send2socket(f":{service_id} MODE {chan.name} +eee ~security-group:webirc-users ~security-group:known-users ~security-group:websocket-users")
self.Irc.send2socket(f":{service_id} MODE {chan.name} +e ~security-group:known-users")
self.Irc.send2socket(f":{service_id} MODE {chan.name} +e ~security-group:websocket-users")
self.Base.db_query_channel('add', self.module_name, jail_chan) self.Base.db_query_channel('add', self.module_name, jail_chan)
@@ -1581,10 +1629,14 @@ class Defender():
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : UID : {UserObject.uid}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : UID : {UserObject.uid}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : NICKNAME : {UserObject.nickname}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : NICKNAME : {UserObject.nickname}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : USERNAME : {UserObject.username}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : USERNAME : {UserObject.username}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : REALNAME : {UserObject.realname}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : HOSTNAME : {UserObject.hostname}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : HOSTNAME : {UserObject.hostname}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : IP : {UserObject.remote_ip}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : REPUTATION : {UserObject.score_connexion}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : VHOST : {UserObject.vhost}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : VHOST : {UserObject.vhost}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : IP : {UserObject.remote_ip}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Country : {UserObject.geoip}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : WebIrc : {UserObject.isWebirc}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : WebWebsocket : {UserObject.isWebsocket}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : REPUTATION : {UserObject.score_connexion}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : MODES : {UserObject.umodes}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : MODES : {UserObject.umodes}')
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : CONNECTION TIME : {UserObject.connexion_datetime}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : CONNECTION TIME : {UserObject.connexion_datetime}')
else: else:

View File

@@ -1,179 +0,0 @@
from dataclasses import dataclass
from core.irc import Irc
from unrealircd_rpc_py.Live import Live
class Jsonrpc():
@dataclass
class ModConfModel:
"""The Model containing the module parameters
"""
param_exemple1: str
param_exemple2: int
def __init__(self, ircInstance:Irc) -> None:
# Module name (Mandatory)
self.module_name = 'mod_' + str(self.__class__.__name__).lower()
# Add Irc Object to the module (Mandatory)
self.Irc = ircInstance
# Add Global Configuration to the module (Mandatory)
self.Config = ircInstance.Config
# Add Base object to the module (Mandatory)
self.Base = ircInstance.Base
# Add logs object to the module (Mandatory)
self.Logs = ircInstance.Base.logs
# Add User object to the module (Mandatory)
self.User = ircInstance.User
# Add Channel object to the module (Mandatory)
self.Channel = ircInstance.Channel
# Create module commands (Mandatory)
self.commands_level = {
1: ['jsonrpc']
}
# Init the module
self.__init_module()
# Log the module
self.Logs.debug(f'Module {self.module_name} loaded ...')
def __init_module(self) -> None:
# Insert module commands into the core one (Mandatory)
self.__set_commands(self.commands_level)
# Create you own tables (Mandatory)
# self.__create_tables()
# Load module configuration and sync with core one (Mandatory)
self.__load_module_configuration()
# End of mandatory methods you can start your customization #
return None
def __set_commands(self, commands:dict[int, list[str]]) -> None:
"""### Rajoute les commandes du module au programme principal
Args:
commands (list): Liste des commandes du module
"""
for level, com in commands.items():
for c in commands[level]:
if not c in self.Irc.commands:
self.Irc.commands_level[level].append(c)
self.Irc.commands.append(c)
return None
def __create_tables(self) -> None:
"""Methode qui va créer la base de donnée si elle n'existe pas.
Une Session unique pour cette classe sera crée, qui sera utilisé dans cette classe / module
Args:
database_name (str): Nom de la base de données ( pas d'espace dans le nom )
Returns:
None: Aucun retour n'es attendu
"""
table_logs = '''CREATE TABLE IF NOT EXISTS test_logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
datetime TEXT,
server_msg TEXT
)
'''
self.Base.db_execute_query(table_logs)
return None
def callback_sent_to_irc(self, json_response: str):
dnickname = self.Config.SERVICE_NICKNAME
dchanlog = self.Config.SERVICE_CHANLOG
self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :{json_response}")
pass
def thread_start_jsonrpc(self):
liveRpc = Live(path_to_socket_file='/home/adator/IRC/unrealircd6.1.2.1/data/rpc.socket',
callback_object_instance=self,
callback_method_name='callback_sent_to_irc'
)
liveRpc.execute_async_method()
pass
def __load_module_configuration(self) -> None:
"""### Load Module Configuration
"""
try:
# Build the default configuration model (Mandatory)
self.ModConfig = self.ModConfModel(param_exemple1='param value 1', param_exemple2=1)
# Sync the configuration with core configuration (Mandatory)
#self.Base.db_sync_core_config(self.module_name, self.ModConfig)
return None
except TypeError as te:
self.Logs.critical(te)
def __update_configuration(self, param_key: str, param_value: str):
"""Update the local and core configuration
Args:
param_key (str): The parameter key
param_value (str): The parameter value
"""
self.Base.db_update_core_config(self.module_name, self.ModConfig, param_key, param_value)
def unload(self) -> None:
return None
def cmd(self, data:list) -> None:
return None
def _hcmds(self, user:str, channel: any, cmd: list, fullcmd: list = []) -> None:
command = str(cmd[0]).lower()
dnickname = self.Config.SERVICE_NICKNAME
fromuser = user
fromchannel = str(channel) if not channel is None else None
match command:
case 'jsonrpc':
self.Base.create_thread(self.thread_start_jsonrpc, run_once=True)
pass
case 'ia':
try:
self.Base.create_thread(self.thread_ask_ia, ('',))
self.Irc.send2socket(f":{dnickname} NOTICE {fromuser} : This is a notice to the sender ...")
self.Irc.send2socket(f":{dnickname} PRIVMSG {fromuser} : This is private message to the sender ...")
if not fromchannel is None:
self.Irc.send2socket(f":{dnickname} PRIVMSG {fromchannel} : This is channel message to the sender ...")
# How to update your module configuration
self.__update_configuration('param_exemple2', 7)
# Log if you want the result
self.Logs.debug(f"Test logs ready")
except Exception as err:
self.Logs.error(f"Unknown Error: {err}")

Binary file not shown.

View File

@@ -1,3 +1,3 @@
{ {
"version": "5.1.9" "version": "5.2.2"
} }