5 Commits

Author SHA1 Message Date
adator
0f31e67be6 check python version fix 2024-09-18 19:10:15 +02:00
adator
3cd2077f63 update installation module 2024-09-18 19:08:08 +02:00
adator
9c78ad0860 Same version, copyright changed 2024-09-17 01:46:09 +02:00
adator
487f9a2762 V5.2.5 2024-09-17 01:43:24 +02:00
adator
a7de16f7ad V5.2.4 multiple changes related to clones 2024-09-17 00:14:53 +02:00
9 changed files with 254 additions and 109 deletions

148
README.md
View File

@@ -57,58 +57,146 @@ Pour Les prochains lancement de defender vous devez utiliser la commande suivant
$ sudo systemctl --user start defender $ sudo systemctl --user start defender
# Configuration # Configuration
```
SERVEUR (Serveur) SERVEUR (Serveur)
SERVEUR_IP: Adresse IP du serveur IRC à rejoindre. * SERVEUR_IP: Adresse IP du serveur IRC à rejoindre. (default : 127.0.0.1)
SERVEUR_HOSTNAME: Nom d'hôte du serveur IRC à rejoindre (optionnel). * SERVEUR_HOSTNAME: Nom d'hôte du serveur IRC à rejoindre (optionnel).
SERVEUR_LINK: Lien vers le serveur IRC (optionnel). * SERVEUR_LINK: Lien vers le serveur IRC (optionnel).
SERVEUR_PORT: Port de connexion au serveur IRC. * SERVEUR_PORT: Port de connexion au serveur IRC.
SERVEUR_PASSWORD: Mot de passe d'enregistrement du service sur le serveur IRC. * SERVEUR_PASSWORD: Mot de passe d'enregistrement du service sur le serveur IRC.
SERVEUR_ID: Identifiant unique du service. SERVEUR_ID: Identifiant unique du service. (default : 19Z)
SERVEUR_SSL: Active la connexion SSL sécurisée au serveur IRC (true/false). SERVEUR_SSL: Active la connexion SSL sécurisée au serveur IRC (true/false) (default : false).
SERVICE (Service) SERVICE (Service)
SERVICE_NAME: Nom du service IRC. SERVICE_NAME: Nom du service IRC. (default : Defender)
SERVICE_NICKNAME: Surnom utilisé par le service sur le serveur IRC. SERVICE_NICKNAME: Surnom utilisé par le service sur le serveur IRC. (default : Defender)
SERVICE_REALNAME: Nom réel du service affiché sur le serveur IRC. SERVICE_REALNAME: Nom réel du service affiché sur le serveur IRC. (default : Defender Security)
SERVICE_USERNAME: Nom d'utilisateur utilisé par le service pour se connecter au serveur IRC. SERVICE_USERNAME: Nom d'utilisateur utilisé par le service pour se connecter au serveur IRC. (default : IRCSecurity)
SERVICE_HOST: Nom d'hôte du service affiché sur le serveur IRC (optionnel). SERVICE_HOST: Nom d'hôte du service affiché sur le serveur IRC (optionnel). (default : defender.local.network)
SERVICE_INFO: Description du service. SERVICE_INFO: Description du service. (default : Defender Network IRC Service)
SERVICE_CHANLOG: Canal utilisé pour la journalisation des actions du service. SERVICE_CHANLOG: Canal utilisé pour la journalisation des actions du service. (default : #services)
SERVICE_SMODES: Modes serveur appliqués aux canaux rejoints par le service. SERVICE_SMODES: Modes serveur appliqués aux canaux rejoints par le service. (default : +ioqBS)
SERVICE_CMODES: Modes de canal appliqués aux canaux rejoints par le service. SERVICE_CMODES: Modes de canal appliqués aux canaux rejoints par le service. (default : ntsOP)
SERVICE_UMODES: Modes utilisateur appliqués au service. SERVICE_UMODES: Modes utilisateur appliqués au service. (default : o)
SERVICE_PREFIX: Caractère utilisé comme préfixe des commandes du service. SERVICE_PREFIX: Caractère utilisé comme préfixe des commandes du service. (default : !)
COMPTE (Compte) COMPTE (Compte)
OWNER: Nom d'utilisateur possédant les droits d'administration du service. OWNER: Nom d'utilisateur possédant les droits d'administration du service. (default : admin)
PASSWORD: Mot de passe de l'administrateur du service. PASSWORD: Mot de passe de l'administrateur du service. (default : admin)
CANAUX (Canaux) CANAUX (Canaux)
SALON_JAIL: Canal utilisé comme prison pour les utilisateurs sanctionnés. SALON_JAIL: Canal utilisé comme prison pour les utilisateurs sanctionnés. (default : #jail)
SALON_JAIL_MODES: Modes appliqués au canal de prison. SALON_JAIL_MODES: Modes appliqués au canal de prison. (default : sS)
SALON_LIBERER: Canal utilisé pour la libération des utilisateurs sanctionnés. SALON_LIBERER: Canal utilisé pour la libération des utilisateurs sanctionnés. (default : #welcome)
API (API) API (API)
API_TIMEOUT: Durée maximale d'attente d'une réponse de l'API en secondes. API_TIMEOUT: Durée maximale d'attente d'une réponse de l'API en secondes. (default : 2)
SCANNER (Scanner) SCANNER (Scanner)
PORTS_TO_SCAN: Liste des ports à scanner pour détecter des serveurs potentiellement malveillants. PORTS_TO_SCAN: Liste des ports à scanner pour détecter des serveurs potentiellement malveillants. (default : [])
SÉCURITÉ (Sécurité) SÉCURITÉ (Sécurité)
WHITELISTED_IP: Liste d'adresses IP autorisées à contourner certaines restrictions. WHITELISTED_IP: Liste d'adresses IP autorisées à contourner certaines restrictions. (default : ['127.0.0.1'])
GLINE_DURATION: Durée de bannissement temporaire d'un utilisateur en minutes. GLINE_DURATION: Durée de bannissement temporaire d'un utilisateur en minutes. (default : "30")
DEBUG (Debug) DEBUG (Debug)
DEBUG_LEVEL: Niveau de verbosité des messages de debug (plus grand est le nombre, plus il y a d'informations). DEBUG_LEVEL: Niveau de verbosité des messages de debug (plus grand est le nombre, plus il y a d'informations). (default : 20) Pour une production
COULEURS (Couleurs) COULEURS (Couleurs)
CONFIG_COLOR: Dictionnaire contenant des codes de couleurs IRC pour un meilleur affichage des messages. CONFIG_COLOR: Dictionnaire contenant des codes de couleurs IRC pour un meilleur affichage des messages.
```
Modification de la configuration Modification de la configuration
Vous devez modifier le fichier configuration.json en remplaçant les valeurs par défaut avec vos propres informations. Assurez-vous de bien lire la description de chaque paramètre pour une configuration optimale du service. Vous devez modifier le fichier configuration.json en remplaçant les valeurs par défaut avec vos propres informations. Assurez-vous de bien lire la description de chaque paramètre pour une configuration optimale du service.
## Exemple de configuration de base
```json
{
"SERVEUR_IP": "IP.DE.TON.SERVER",
"SERVEUR_HOSTNAME": "HOST.DE.TON.SERVER",
"SERVEUR_LINK": "LINK.DE.TON.SERVER",
"SERVEUR_PORT": 6901,
"SERVEUR_PASSWORD": "MOT_DE_PASS_DE_TON_LINK",
"SERVEUR_ID": "10Z",
"SERVEUR_SSL": true,
"SERVICE_NAME": "defender",
"SERVICE_NICKNAME": "Dev-PyDefender",
"SERVICE_REALNAME": "Python Defender Security",
"SERVICE_USERNAME": "Dev-PyDefender",
"SERVICE_HOST": "HOST.DE.TON.DEFENDER",
"OWNER": "TON_NICK_NAME",
"PASSWORD": "admin",
"CONFIG_COLOR": {
"blanche": "\\u0003\\u0030",
"noire": "\\u0003\\u0031",
"bleue": "\\u0003\\u0020",
"verte": "\\u0003\\u0033",
"rouge": "\\u0003\\u0034",
"jaune": "\\u0003\\u0036",
"gras": "\\u0002",
"nogc": "\\u0002\\u0003"
}
}
```
## Exemple complet de configuration
```json
{
"SERVEUR_IP": "YOUR.SERVER.IP",
"SERVEUR_HOSTNAME": "irc.deb.biz.st",
"SERVEUR_LINK": "defenderdev.deb.biz.st",
"SERVEUR_PORT": 6901,
"SERVEUR_PASSWORD": "yourpassword",
"SERVEUR_ID": "10Z",
"SERVEUR_SSL": true,
"SERVICE_NAME": "defender",
"SERVICE_NICKNAME": "Dev-PyDefender",
"SERVICE_REALNAME": "Python Defender Security",
"SERVICE_USERNAME": "Dev-PyDefender",
"SERVICE_HOST": "HOST.DE.TON.DEFENDER",
"SERVICE_INFO": "Network IRC Service",
"SERVICE_CHANLOG": "#services",
"SERVICE_SMODES": "+ioqBS",
"SERVICE_CMODES": "ntsOP",
"SERVICE_UMODES": "o",
"SERVICE_PREFIX": "!",
"OWNER": "TON_NICK_NAME",
"PASSWORD": "admin",
"SALON_JAIL": "#jail",
"SALON_JAIL_MODES": "sS",
"SALON_LIBERER": "#welcome",
"SALON_CLONES": "#clones",
"API_TIMEOUT": 2,
"PORTS_TO_SCAN": [3028, 8080, 1080, 1085, 4145, 9050],
"WHITELISTED_IP": ["127.0.0.1"],
"GLINE_DURATION": "30",
"DEBUG_LEVEL": 10,
"CONFIG_COLOR": {
"blanche": "\\u0003\\u0030",
"noire": "\\u0003\\u0031",
"bleue": "\\u0003\\u0020",
"verte": "\\u0003\\u0033",
"rouge": "\\u0003\\u0034",
"jaune": "\\u0003\\u0036",
"gras": "\\u0002",
"nogc": "\\u0002\\u0003"
}
}
```
# \\!/ Attention \\!/ # \\!/ Attention \\!/
Le mot de passe de l'administrateur et le mot de passe du service doivent être modifiés pour des raisons de sécurité. Le mot de passe de l'administrateur et le mot de passe du service doivent être modifiés pour des raisons de sécurité.
Ne partagez pas vos informations de connexion au serveur IRC avec des tiers. Ne partagez pas vos informations de connexion au serveur IRC avec des tiers.

View File

@@ -414,6 +414,8 @@ class Clones:
nickname: str nickname: str
username: str username: str
realname: str realname: str
channels: list
vhost: str = None
connected: bool = False connected: bool = False
UID_CLONE_DB: list[CloneModel] = [] UID_CLONE_DB: list[CloneModel] = []

View File

@@ -429,7 +429,7 @@ class Base:
except AssertionError as ae: except AssertionError as ae:
self.logs.error(f'Assertion Error -> {ae}') self.logs.error(f'Assertion Error -> {ae}')
def create_thread(self, func:object, func_args: tuple = (), run_once:bool = False) -> None: def create_thread(self, func:object, func_args: tuple = (), run_once:bool = False, daemon: bool = True) -> None:
"""Create a new thread and store it into running_threads variable """Create a new thread and store it into running_threads variable
Args: Args:
@@ -445,7 +445,7 @@ class Base:
if thread.getName() == func_name: if thread.getName() == func_name:
return None return None
th = threading.Thread(target=func, args=func_args, name=str(func_name), daemon=True) th = threading.Thread(target=func, args=func_args, name=str(func_name), daemon=daemon)
th.start() th.start()
self.running_threads.append(th) self.running_threads.append(th)

View File

@@ -15,7 +15,7 @@ class Connection:
self.nickname = nickname self.nickname = nickname
self.username = username self.username = username
self.realname = realname self.realname = realname
self.chanlog = '#clones' self.clone_chanlog = self.Config.SALON_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
@@ -62,7 +62,7 @@ class Connection:
self.Base.logs.critical(f"AttributeError __create_socket: {ae} - {soc.fileno()}") self.Base.logs.critical(f"AttributeError __create_socket: {ae} - {soc.fileno()}")
return False return False
def send2socket(self, send_message:str) -> None: def send2socket(self, send_message:str, disconnect: bool = False) -> None:
"""Envoit les commandes à envoyer au serveur. """Envoit les commandes à envoyer au serveur.
Args: Args:
@@ -70,9 +70,8 @@ class Connection:
""" """
try: try:
with self.Base.lock: with self.Base.lock:
# print(f">{str(send_message)}")
self.IrcSocket.send(f"{send_message}\r\n".encode(self.CHARSET[0])) self.IrcSocket.send(f"{send_message}\r\n".encode(self.CHARSET[0]))
self.Base.logs.debug(f'{send_message}') self.Base.logs.debug(f'<<{self.currentCloneObject.nickname}>>: {send_message}')
except UnicodeDecodeError: except UnicodeDecodeError:
self.Base.logs.error(f'Decode Error try iso-8859-1 - message: {send_message}') self.Base.logs.error(f'Decode Error try iso-8859-1 - message: {send_message}')
@@ -114,7 +113,6 @@ class Connection:
def connect(self): def connect(self):
try: try:
while self.signal: while self.signal:
try: try:
# 4072 max what the socket can grab # 4072 max what the socket can grab
@@ -132,6 +130,7 @@ class Connection:
data = data_in_bytes.splitlines(True) data = data_in_bytes.splitlines(True)
if not data: if not data:
# If no data then quit the loop
break break
self.parser(data) self.parser(data)
@@ -145,10 +144,6 @@ class Connection:
self.Base.logs.error(f"OSError __connect_to_irc: {oe} - {data}") self.Base.logs.error(f"OSError __connect_to_irc: {oe} - {data}")
self.signal = False self.signal = False
self.IrcSocket.shutdown(socket.SHUT_RDWR)
self.IrcSocket.close()
self.Base.logs.info("--> Clone Disconnected ...")
except AssertionError as ae: except AssertionError as ae:
self.Base.logs.error(f'Assertion error : {ae}') self.Base.logs.error(f'Assertion error : {ae}')
except ValueError as ve: except ValueError as ve:
@@ -159,12 +154,17 @@ class Connection:
self.Base.logs.critical(f"{atte}") self.Base.logs.critical(f"{atte}")
except Exception as e: except Exception as e:
self.Base.logs.error(f"Exception: {e}") self.Base.logs.error(f"Exception: {e}")
finally:
self.IrcSocket.shutdown(socket.SHUT_WR)
self.IrcSocket.shutdown(socket.SHUT_RD)
self.Base.logs.info(f"<<{self.currentCloneObject.nickname}>> Clone Disconnected ...")
# self.IrcSocket.close()
def parser(self, cmd:list[bytes]): def parser(self, cmd:list[bytes]):
try: try:
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
current_clone_nickname = self.currentCloneObject.nickname current_clone_nickname = self.currentCloneObject.nickname
# print(response) # print(response)
@@ -176,7 +176,8 @@ class Connection:
case 'ERROR': case 'ERROR':
error_value = str(response[1]).replace(':','') error_value = str(response[1]).replace(':','')
if error_value == 'Closing': if error_value == 'Closing':
self.signal = False self.Base.logs.info(f"<<{self.currentCloneObject.nickname}>> {response} ...")
# self.signal = False
match response[1]: match response[1]:
case '376': case '376':
@@ -184,33 +185,37 @@ class Connection:
self.currentCloneObject.connected = True self.currentCloneObject.connected = True
for channel in self.channels: for channel in self.channels:
self.send2socket(f"JOIN {channel}") self.send2socket(f"JOIN {channel}")
self.send2socket(f"JOIN {self.clone_chanlog}")
return None return None
case '422': case '422':
# Missing MOTD # Missing MOTD
self.currentCloneObject.connected = True self.currentCloneObject.connected = True
for channel in self.channels: for channel in self.channels:
self.send2socket(f"JOIN {channel}") self.send2socket(f"JOIN {channel}")
self.send2socket(f"JOIN {self.clone_chanlog}")
return None return None
case 'PRIVMSG': case 'PRIVMSG':
self.Base.logs.debug(response) self.Base.logs.debug(f'<<{self.currentCloneObject.nickname}>> Response: {response}')
self.Base.logs.debug(f'{self.currentCloneObject.nickname} - {self.currentCloneObject.alive}') self.Base.logs.debug(f'<<{self.currentCloneObject.nickname}>> Alive: {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: if response[2] == current_clone_nickname and nickname != self.Config.SERVICE_NICKNAME:
message = [] message = []
for i in range(3, len(response)): for i in range(3, len(response)):
message.append(response[i]) message.append(response[i])
final_message = ' '.join(message) final_message = ' '.join(message)
self.send2socket(f"PRIVMSG {self.chanlog} :{fullname} => {final_message[1:]}") self.send2socket(f"PRIVMSG {self.clone_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(':','')
if command == 'KILL': if command == 'KILL':
self.send2socket(f'QUIT :Thanks and goodbye') self.send2socket(f'QUIT :Thanks and goodbye', disconnect=True)
self.signal = self.currentCloneObject.alive
if command == 'JOIN': if command == 'JOIN':
channel_to_join = str(response[4]) channel_to_join = str(response[4])

View File

@@ -28,22 +28,17 @@ class Install:
self.set_configuration() self.set_configuration()
if not self.check_python_version(): if self.skip_install:
# Tester si c'est la bonne version de python return None
exit("Python Version Error")
else:
if self.skip_install: # Sinon tester les dependances python et les installer avec pip
return None if self.do_install():
# Sinon tester les dependances python et les installer avec pip self.install_dependencies()
if self.do_install():
self.install_dependencies() self.create_service_file()
self.create_service_file() self.print_final_message()
self.print_final_message()
return None return None
@@ -74,13 +69,24 @@ class Install:
venv_python_executable=f'{os.path.join(defender_install_folder, venv_folder, "bin")}{os.sep}python' venv_python_executable=f'{os.path.join(defender_install_folder, venv_folder, "bin")}{os.sep}python'
) )
# Exclude Windows OS if not self.check_python_version():
# If the Python version is not good then Exit
exit("/!\\ Python version error /!\\")
if not os.path.exists(os.path.join(self.config.defender_install_folder, 'core', 'configuration.json')):
# If configuration file do not exist
exit("/!\\ Configuration file (configuration.json) doesn't exist /!\\")
# Exclude Windows OS from the installation
if os.name == 'nt': if os.name == 'nt':
#print('/!\\ Skip installation /!\\') #print('/!\\ Skip installation /!\\')
self.skip_install = True self.skip_install = True
else: return False
if self.is_root():
self.skip_install = True if self.is_root():
exit(f'/!\\ I highly not recommend running Defender as root /!\\')
self.skip_install = True
return False
def is_root(self) -> bool: def is_root(self) -> bool:

View File

@@ -1376,7 +1376,7 @@ class Irc:
self.send2socket(f':{dnickname} NOTICE {fromuser} : {uptime}') self.send2socket(f':{dnickname} NOTICE {fromuser} : {uptime}')
case 'copyright': case 'copyright':
self.send2socket(f':{dnickname} NOTICE {fromuser} : # Defender V.{self.Config.current_version} Developped by adator® and dktmb® #') self.send2socket(f':{dnickname} NOTICE {fromuser} : # Defender V.{self.Config.current_version} Developped by adator® #')
case 'checkversion': case 'checkversion':

View File

@@ -82,6 +82,9 @@ class ConfigDataModel:
SALON_LIBERER: str SALON_LIBERER: str
"""Channel where the nickname will be released""" """Channel where the nickname will be released"""
SALON_CLONES: str
"""Channel to host clones"""
API_TIMEOUT: int API_TIMEOUT: int
"""Default api timeout in second""" """Default api timeout in second"""
@@ -147,8 +150,33 @@ class Config:
with open(conf_filename, 'r') as configuration_data: with open(conf_filename, 'r') as configuration_data:
configuration:dict[str, Union[str, int, list, dict]] = json.load(configuration_data) configuration:dict[str, Union[str, int, list, dict]] = json.load(configuration_data)
for key, value in configuration['CONFIG_COLOR'].items(): config_dict = {"CONFIG_COLOR" : {
configuration['CONFIG_COLOR'][key] = str(value).encode('utf-8').decode('unicode_escape') "blanche": "\\u0003\\u0030",
"noire": "\\u0003\\u0031",
"bleue": "\\u0003\\u0020",
"verte": "\\u0003\\u0033",
"rouge": "\\u0003\\u0034",
"jaune": "\\u0003\\u0036",
"gras": "\\u0002",
"nogc": "\\u0002\\u0003"
}
}
missing_color = False
if not "CONFIG_COLOR" in configuration:
missing_color = True
configuration_color = config_dict
else:
configuration_color = configuration["CONFIG_COLOR"]
if missing_color:
for key, value in configuration_color.items():
configuration_color['CONFIG_COLOR'][key] = str(value).encode('utf-8').decode('unicode_escape')
configuration['CONFIG_COLOR'] = configuration_color['CONFIG_COLOR']
else:
for key, value in configuration['CONFIG_COLOR'].items():
configuration['CONFIG_COLOR'][key] = str(value).encode('utf-8').decode('unicode_escape')
return configuration return configuration
@@ -161,34 +189,35 @@ class Config:
import_config = self.__load_json_service_configuration() import_config = self.__load_json_service_configuration()
ConfigObject: ConfigDataModel = ConfigDataModel( ConfigObject: ConfigDataModel = ConfigDataModel(
SERVEUR_IP=import_config["SERVEUR_IP"], SERVEUR_IP=import_config["SERVEUR_IP"] if "SERVEUR_IP" in import_config else '127.0.0.1',
SERVEUR_HOSTNAME=import_config["SERVEUR_HOSTNAME"], SERVEUR_HOSTNAME=import_config["SERVEUR_HOSTNAME"] if "SERVEUR_HOSTNAME" in import_config else None,
SERVEUR_LINK=import_config["SERVEUR_LINK"], SERVEUR_LINK=import_config["SERVEUR_LINK"] if "SERVEUR_LINK" in import_config else None,
SERVEUR_PORT=import_config["SERVEUR_PORT"], SERVEUR_PORT=import_config["SERVEUR_PORT"] if "SERVEUR_PORT" in import_config else 6667,
SERVEUR_PASSWORD=import_config["SERVEUR_PASSWORD"], SERVEUR_PASSWORD=import_config["SERVEUR_PASSWORD"] if "SERVEUR_PASSWORD" in import_config else None,
SERVEUR_ID=import_config["SERVEUR_ID"], SERVEUR_ID=import_config["SERVEUR_ID"] if "SERVEUR_ID" in import_config else '19Z',
SERVEUR_SSL=import_config["SERVEUR_SSL"], SERVEUR_SSL=import_config["SERVEUR_SSL"] if "SERVEUR_SSL" in import_config else False,
SERVICE_NAME=import_config["SERVICE_NAME"], SERVICE_NAME=import_config["SERVICE_NAME"] if "SERVICE_NAME" in import_config else 'Defender',
SERVICE_NICKNAME=import_config["SERVICE_NICKNAME"], SERVICE_NICKNAME=import_config["SERVICE_NICKNAME"] if "SERVICE_NICKNAME" in import_config else 'Defender',
SERVICE_REALNAME=import_config["SERVICE_REALNAME"], SERVICE_REALNAME=import_config["SERVICE_REALNAME"] if "SERVICE_REALNAME" in import_config else 'Defender Security',
SERVICE_USERNAME=import_config["SERVICE_USERNAME"], SERVICE_USERNAME=import_config["SERVICE_USERNAME"] if "SERVICE_USERNAME" in import_config else 'IRCSecurity',
SERVICE_HOST=import_config["SERVICE_HOST"], SERVICE_HOST=import_config["SERVICE_HOST"] if "SERVICE_HOST" in import_config else 'defender.local.network',
SERVICE_INFO=import_config["SERVICE_INFO"], SERVICE_INFO=import_config["SERVICE_INFO"] if "SERVICE_INFO" in import_config else 'Defender Network IRC Service',
SERVICE_CHANLOG=import_config["SERVICE_CHANLOG"], SERVICE_CHANLOG=import_config["SERVICE_CHANLOG"] if "SERVICE_CHANLOG" in import_config else '#services',
SERVICE_SMODES=import_config["SERVICE_SMODES"], SERVICE_SMODES=import_config["SERVICE_SMODES"] if "SERVICE_SMODES" in import_config else '+ioqBS',
SERVICE_CMODES=import_config["SERVICE_CMODES"], SERVICE_CMODES=import_config["SERVICE_CMODES"] if "SERVICE_CMODES" in import_config else 'ntsOP',
SERVICE_UMODES=import_config["SERVICE_UMODES"], SERVICE_UMODES=import_config["SERVICE_UMODES"] if "SERVICE_UMODES" in import_config else 'o',
SERVICE_PREFIX=import_config["SERVICE_PREFIX"], SERVICE_PREFIX=import_config["SERVICE_PREFIX"] if "SERVICE_PREFIX" in import_config else '!',
OWNER=import_config["OWNER"], OWNER=import_config["OWNER"] if "OWNER" in import_config else 'admin',
PASSWORD=import_config["PASSWORD"], PASSWORD=import_config["PASSWORD"] if "PASSWORD" in import_config else 'admin',
SALON_JAIL=import_config["SALON_JAIL"], SALON_JAIL=import_config["SALON_JAIL"] if "SALON_JAIL" in import_config else '#jail',
SALON_JAIL_MODES=import_config["SALON_JAIL_MODES"], SALON_JAIL_MODES=import_config["SALON_JAIL_MODES"] if "SALON_JAIL_MODES" in import_config else 'sS',
SALON_LIBERER=import_config["SALON_LIBERER"], SALON_LIBERER=import_config["SALON_LIBERER"] if "SALON_LIBERER" in import_config else '#welcome',
API_TIMEOUT=import_config["API_TIMEOUT"], SALON_CLONES=import_config["SALON_CLONES"] if "SALON_CLONES" in import_config else '#clones',
PORTS_TO_SCAN=import_config["PORTS_TO_SCAN"], API_TIMEOUT=import_config["API_TIMEOUT"] if "API_TIMEOUT" in import_config else 2,
WHITELISTED_IP=import_config["WHITELISTED_IP"], PORTS_TO_SCAN=import_config["PORTS_TO_SCAN"] if "PORTS_TO_SCAN" in import_config else [],
GLINE_DURATION=import_config["GLINE_DURATION"], WHITELISTED_IP=import_config["WHITELISTED_IP"] if "WHITELISTED_IP" in import_config else ['127.0.0.1'],
DEBUG_LEVEL=import_config["DEBUG_LEVEL"], GLINE_DURATION=import_config["GLINE_DURATION"] if "GLINE_DURATION" in import_config else '30',
DEBUG_LEVEL=import_config["DEBUG_LEVEL"] if "DEBUG_LEVEL" in import_config else 20,
CONFIG_COLOR=import_config["CONFIG_COLOR"], CONFIG_COLOR=import_config["CONFIG_COLOR"],
table_admin='core_admin', table_admin='core_admin',
table_commande='core_command', table_commande='core_command',

View File

@@ -126,6 +126,9 @@ class Clone():
fake = faker.Faker('en_GB') fake = faker.Faker('en_GB')
for clone in self.Clone.UID_CLONE_DB: for clone in self.Clone.UID_CLONE_DB:
if not clone.vhost is None:
continue
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_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_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_3 = fake.random_elements(['A','B','C','D','E','F','0','1','2','3','4','5','6','7','8','9'], unique=True, length=8)
@@ -137,6 +140,7 @@ class Clone():
if clone.connected: if clone.connected:
self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} CHGHOST {clone.nickname} {rand_ip}') self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} CHGHOST {clone.nickname} {rand_ip}')
found = True found = True
clone.vhost = rand_ip
break break
def thread_create_clones(self, nickname: str, username: str, realname: str, channels: list, server_port: int, ssl: bool) -> None: def thread_create_clones(self, nickname: str, username: str, realname: str, channels: list, server_port: int, ssl: bool) -> None:
@@ -146,21 +150,25 @@ class Clone():
return None return None
def thread_join_channels(self, channel_name: str, wait: float, clone_name:str = None): def thread_join_channels(self, channel_name: str, wait: float, clone_name:str = None):
self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {self.Config.SERVICE_CHANLOG} :Clones start to join {channel_name} with {wait} secondes frequency')
if clone_name is None: if clone_name is None:
for clone in self.Clone.UID_CLONE_DB: for clone in self.Clone.UID_CLONE_DB:
self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone.nickname} :JOIN {channel_name}') if not channel_name in clone.channels:
time.sleep(wait) time.sleep(wait)
self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone.nickname} :JOIN {channel_name}')
clone.channels.append(channel_name)
else: else:
for clone in self.Clone.UID_CLONE_DB: for clone in self.Clone.UID_CLONE_DB:
if clone_name == clone.nickname: if clone_name == clone.nickname:
self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone.nickname} :JOIN {channel_name}') if not channel_name in clone.channels:
time.sleep(wait) time.sleep(wait)
self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone.nickname} :JOIN {channel_name}')
clone.channels.append(channel_name)
def generate_names(self) -> tuple[str, 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 # Generate Username
@@ -171,6 +179,14 @@ class Clone():
# Create realname XX F|M Department # Create realname XX F|M Department
gender = fake.random_choices(['F','M'], 1) gender = fake.random_choices(['F','M'], 1)
gender = ''.join(gender) gender = ''.join(gender)
if gender == 'F':
nickname = fake.first_name_female()
elif gender == 'M':
nickname = fake.first_name_male()
else:
nickname = fake.first_name()
age = random.randint(20, 60) age = random.randint(20, 60)
fake_fr = faker.Faker(['fr_FR', 'en_GB']) fake_fr = faker.Faker(['fr_FR', 'en_GB'])
department = fake_fr.department_name() department = fake_fr.department_name()
@@ -181,11 +197,11 @@ class Clone():
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, realname=realname) self.Clone.CloneModel(alive=True, nickname=nickname, username=username, realname=realname, channels=[])
) )
else: else:
self.Clone.insert( self.Clone.insert(
self.Clone.CloneModel(alive=True, nickname=nickname, username=username, realname=realname) self.Clone.CloneModel(alive=True, nickname=nickname, username=username, realname=realname, channels=[])
) )
return (nickname, username, realname) return (nickname, username, realname)
@@ -237,12 +253,11 @@ class Clone():
nickname, username, realname = 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, realname, ['#clones'], 6697, True) (nickname, username, realname, [], 6697, True)
) )
self.Base.create_thread( self.Base.create_thread(
self.thread_change_hostname, 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')

View File

@@ -1,3 +1,3 @@
{ {
"version": "5.2.3" "version": "5.2.5"
} }