Découvrez les projets sur lesquels j'ai travaillé
Configuration complète du firewall, règles LAN/DMZ/WAN, proxy, FTP, SSH et MySQL.
Analyse et configuration d'une topologie multi-routeurs avec tables de routage complètes.
Configuration complète du routage statique, des machines virtuelles et du firewall PfSense.
Suite d'outils PHP permettant d'explorer, lister et tester des machines sur un réseau local.
Système de conversion d'argent sale → propre avec sécurité, logs Discord et interface utilisateur.
Marché noir complet avec menu RageUI, gestion de l'argent sale et système de logs Discord.
Ce projet consiste à configurer un firewall Pfsense selon un cahier des charges précis. L'objectif était de sécuriser l'infrastructure, d'isoler les zones LAN / DMZ / WAN et d'appliquer des règles fines pour chaque machine. Le travail inclut DHCP, filtrage, proxy, restrictions d'accès, services (FTP, SSH, MySQL) et autorisations spécifiques.
PfSense
Routage & NAT
Squid Proxy
Services (FTP, SSH)
Ce projet consiste à concevoir et configurer une architecture réseau complète composée de quatre routeurs, plusieurs LAN distincts et un accès Internet simulé. L'objectif était de mettre en place un plan d'adressage cohérent, configurer le routage statique, assurer la communication entre les réseaux (10.21.21.0 / 192.168.11.0 / 172.59.10.0 / 192.168.100.0 / 192.168.101.0) et permettre l'accès Internet via le routeur R3.
| Destination | Passerelle | Masque | Interface |
|---|---|---|---|
| 192.168.11.0 | 192.168.11.254 | 255.255.255.0 | 192.168.157.2 |
| 192.168.100.0 | 192.168.100.2 | 255.255.255.0 | 192.168.100.2 |
| 0.0.0.0 | 192.168.100.1 | 0.0.0.0 | 192.168.100.2 |
| Destination | Passerelle | Masque | Interface |
|---|---|---|---|
| 10.0.0.0 | 10.21.21.21 | 255.0.0.0 | 10.21.21.21 |
| 192.168.157.0 | 192.168.157.2 | 255.255.255.0 | 192.168.157.2 |
| 0.0.0.0 | 192.168.157.1 | 0.0.0.0 | 192.168.157.2 |
| Destination | Passerelle | Masque | Interface |
|---|---|---|---|
| 192.168.157.0 | 192.168.157.1 | 255.255.255.0 | 192.168.157.1 |
| 172.59.0.0 | 172.59.10.10 | 255.255.0.0 | 172.59.10.10 |
| 192.168.101.0 | 192.168.101.2 | 255.255.255.0 | 192.168.101.2 |
| 10.0.0.0 | 192.168.157.2 | 255.0.0.0 | 192.168.157.1 |
| 0.0.0.0 | 192.168.101.1 | 0.0.0.0 | 192.168.101.2 |
| Destination | Passerelle | Masque | Interface |
|---|---|---|---|
| 192.168.100.0 | 192.168.100.1 | 255.255.255.0 | 192.168.100.1 |
| 192.168.101.0 | 192.168.101.1 | 255.255.255.0 | 192.168.101.1 |
| 12.0.0.0 | 12.141.14.18 | 255.0.0.0 | 12.141.14.18 |
| 192.168.11.0 | 192.168.100.2 | 255.255.255.0 | 192.168.100.1 |
| 172.59.0.0 | 192.168.101.2 | 255.255.0.0 | 192.168.101.1 |
| 10.0.0.0 | 192.168.101.2 | 255.0.0.0 | 192.168.101.1 |
| 0.0.0.0 | 12.141.1.1 | 0.0.0.0 | 12.141.14.18 |
Cisco IOS
Routage Statique
NAT & Internet
Plan IP
Ce projet combine une architecture réseau complexe multi-routeurs avec une sécurisation complète via PfSense. J'ai réalisé l'adressage IP, la configuration du routage statique sur toutes les machines et routeurs, et la mise en place de règles de firewall strictes pour isoler et contrôler les zones (LAN, DMZ, WAN).
PfSense
Routage Statique
Linux / Windows
Topologie Réseau
Le projet lgmHosts est une suite de scripts PHP développée en environnement Linux. Il permet d'explorer un réseau local, de stocker les machines détectées et de vérifier leur disponibilité via des commandes système.
Ce script parcourt toutes les adresses IP potentielles d'une salle et
teste leur disponibilité à l'aide de la commande ping.
Toute nouvelle machine détectée est ajoutée dans un fichier de
sauvegarde.
Ce script lit le fichier contenant les machines détectées et affiche uniquement celles correspondant à la salle demandée, sous forme de tableau lisible dans le terminal.
Ce script permet de tester si les machines précédemment détectées répondent toujours au ping. Il est possible de filtrer par salle ou de tester l'ensemble des machines.
PHP
Linux / Shell
Réseau IPv4
Ce script ajoute un système complet de conversion d'argent sale → propre, avec taxes dynamiques, tickets d'accès, téléportations, animations, sécurité renforcée et logs Discord. L'objectif : une laverie immersive, configurable et optimisée.
local LavageEnCours = false
local DansLaverie = false
local TempsRecharge = false
local function DelaiRecharge()
TempsRecharge = true
Wait(config_blanchiment.DelaiRecharge)
TempsRecharge = false
end
local function JouerAnimation()
SetEntityHeading(PlayerPedId(), config_blanchiment.Animations.heading)
TaskPlayAnim(PlayerPedId(), config_blanchiment.Animations.dict, config_blanchiment.Animations.name, 2.0, 2.0, config_blanchiment.Animations.duration, config_blanchiment.Animations.flag, 0, 0, 0)
end
function LaverArgent()
if LavageEnCours then
lib.notify({title='Lavage en cours', description="Vous lavez déjà de l'argent", type='erreur'})
return
end
if config_blanchiment.TicketsRequis then
local ticket = exports.ox_inventory:Search('count', config_blanchiment.Items.ticket)
if ticket < 1 then
lib.notify({title='Accès refusé', description="Vous avez besoin d'un ticket de lavage", type='erreur'})
return
end
end
if TempsRecharge then
lib.notify({title='Temps de recharge actif', description='Le refroidissement du lavage est actif', type='erreur'})
return
end
JouerAnimation()
local input = lib.inputDialog('Quantité de lavage', {'Combien voulez-vous laver?'})
if not input then return end
local MontantALaver = tonumber(input[1])
TriggerServerEvent('roxoz:blanchirArgent', MontantALaver)
Wait(500)
ClearPedTasksImmediately(PlayerPedId())
end
function EntrerDansLaverie()
if config_blanchiment.UtiliserCarteEntree then
local carte = exports.ox_inventory:Search('count', config_blanchiment.Items.carte)
if carte < 1 then
lib.notify({title='Accès refusé', description="Vous avez besoin d'une carte de blanchiment", type='erreur'})
return
end
end
DoScreenFadeOut(100)
Wait(1000)
SetEntityCoords(PlayerPedId(), config_blanchiment.Teleports.entree.x, config_blanchiment.Teleports.entree.y, config_blanchiment.Teleports.entree.z)
SetEntityHeading(PlayerPedId(), config_blanchiment.Teleports.entree.heading)
Wait(1000)
DoScreenFadeIn(100)
DansLaverie = true
end
function SortirLaverie()
if LavageEnCours then
lib.notify({title='Lavage en cours', description='Vous ne pouvez pas quitter le LaundryMat pendant le lavage', type='erreur'})
return
end
DansLaverie = false
DoScreenFadeOut(100)
Wait(500)
SetEntityCoords(PlayerPedId(), config_blanchiment.Teleports.sortie.x, config_blanchiment.Teleports.sortie.y, config_blanchiment.Teleports.sortie.z)
SetEntityHeading(PlayerPedId(), config_blanchiment.Teleports.sortie.heading)
Wait(1000)
DoScreenFadeIn(100)
end
RegisterNetEvent('roxoz:processusLavage')
AddEventHandler('roxoz:processusLavage', function()
LavageEnCours = true
lib.notify({title='Commencé', description='Vous avez commencé le processus de lavage.', type='information'})
if lib.progressBar({duration=config_blanchiment.DureeBlanchiment, label="Blanchiment de l'argent...", useWhileDead=false, canCancel=false}) then
lib.notify({title='Fini', description='Vous avez fini de laver votre argent', type='information'})
end
LavageEnCours = false
DelaiRecharge()
end)
Citizen.CreateThread(function()
while true do
local wait = 750
local playerPed = PlayerPedId()
local plyCoords = GetEntityCoords(playerPed, false)
for _, marker in pairs(config_blanchiment.Markers) do
local dist = Vdist(plyCoords.x, plyCoords.y, plyCoords.z, marker.x, marker.y, marker.z)
if dist <= 5.0 then
wait = 0
DrawMarker(config_blanchiment.MarkerType, marker.x, marker.y, marker.z - 0.98, 0.0, 0.0, 0.0, -90.0, 0.0, 0.0,
config_blanchiment.MarkerSize.x, config_blanchiment.MarkerSize.y, config_blanchiment.MarkerSize.z,
config_blanchiment.MarkerColor.r, config_blanchiment.MarkerColor.g, config_blanchiment.MarkerColor.b,
config_blanchiment.MarkerColor.a, config_blanchiment.MarkerSaute, true, 2, config_blanchiment.MarkerTourne)
end
if dist <= 2.0 then
wait = 0
Visual.Subtitle(marker.text, 1)
if IsControlJustPressed(1, 51) then
if marker == config_blanchiment.Markers.entree then EntrerDansLaverie()
elseif marker == config_blanchiment.Markers.sortie then SortirLaverie()
elseif marker == config_blanchiment.Markers.lavage then LaverArgent()
end
end
end
end
Citizen.Wait(wait)
end
end)
ESX = exports["es_extended"]:getSharedObject()
local ox_inventory = exports.ox_inventory
RegisterServerEvent('roxoz:blanchirArgent')
AddEventHandler('roxoz:blanchirArgent', function(Amount)
local Player = source
local WashTax = Amount * config_blanchiment.TaxRate
local WashTotal = Amount - WashTax
local black_money = exports.ox_inventory:Search(Player, 'count', config_blanchiment.Items.argent_noir)
local ticket = exports.ox_inventory:Search(Player, 'count', config_blanchiment.Items.ticket)
if black_money < Amount then
TriggerClientEvent('esx:showAdvancedNotification', Player, '', "Blanchisseur", "Vous n'avez pas assez d'argent sale.")
return
end
if config_blanchiment.TicketsRequis and ticket < 1 then
TriggerClientEvent('esx:showAdvancedNotification', Player, '', "Blanchisseur", "Vous n'avez pas de ticket de lavage.")
return
end
exports.ox_inventory:RemoveItem(Player, config_blanchiment.Items.argent_noir, Amount)
if config_blanchiment.TicketsRequis then
exports.ox_inventory:RemoveItem(Player, config_blanchiment.Items.ticket, 1)
end
TriggerClientEvent('roxoz:processusLavage', Player)
Citizen.Wait(config_blanchiment.DureeBlanchiment)
exports.ox_inventory:AddItem(Player, config_blanchiment.Items.argent_blanc, WashTotal)
local embed = {
title = 'Lavage d\'argent réussi',
description = string.format("**Joueur :** `%s` (ID : `%s`)\n**Montant noir :** `%s$`\n**Taxe :** `%s$`\n**Nettoyé :** `%s$`\n**Ticket utilisé :** `%s`",
GetPlayerName(Player), Player, Amount, WashTax, WashTotal, (ticket >= 1 and "Oui" or "Non")),
color = 65280,
webhook = 'blanchiment',
}
EnvoieWebhook(embed)
end)
config_blanchiment = {}
-- MARKERS
config_blanchiment.Markers = {
entree = {x = 1561.4556, y = -1693.0305, z = 89.2134, text = "Appuyez sur ~g~[E] ~s~pour Entrer dans le Blanchiment ~s~!"},
sortie = {x = 1138.1396, y = -3198.7817, z = -40.6657, text = "Appuyez sur ~g~[E] ~s~pour sortir du Blanchiment~s~!"},
lavage = {x = 1122.2937, y = -3194.9509, z = -41.4014, text = "Appuyez sur ~g~[E] ~s~pour laver l'argent sale~s~!"}
}
config_blanchiment.MarkerType = 6
config_blanchiment.MarkerSize = {x = 0.5, y = 0.5, z = 0.5}
config_blanchiment.MarkerColor = {r = 205, g = 205, b = 59, a = 300}
config_blanchiment.MarkerSaute = false
config_blanchiment.MarkerTourne = false
-- DELAIS & TEMPS
config_blanchiment.DelaiRecharge = 600000 -- Temps de recharge avant un nouveau lavage (ms)
config_blanchiment.DureeBlanchiment = 3000 -- Durée du processus de lavage
-- TAXES & CONDITIONS
config_blanchiment.TaxRate = 0.30 -- Taxe prélevée sur le montant lavé
config_blanchiment.UtiliserCarteEntree = true -- Carte nécessaire pour entrer
config_blanchiment.TicketsRequis = true -- Ticket nécessaire pour laver
-- ITEMS
config_blanchiment.Items = {
argent_noir = "black_money",
argent_blanc = "money",
ticket = "ticket_lavage",
carte = "carte_blanchiment"
}
-- ANIMATIONS
config_blanchiment.Animations = {
heading = 349.9048,
dict = "gestures@f@standing@casual",
name = "gesture_shrug_hard",
flag = 16,
duration = 1000
}
-- TELEPORTS
config_blanchiment.Teleports = {
sortie = {x = 1561.4556, y = -1693.0305, z = 89.2134, heading = 275.8793},
entree = {x = 1138.1396, y = -3198.7817, z = -40.6657, heading = 6}
}
Système de traçabilité complet permettant de surveiller les transactions importantes. Chaque blanchiment génère un log détaillé incluant le montant initial, la taxe appliquée et le montant final reçu.
Lua
ESX / Ox
Discord Webhook
Ce script propose un système de marché noir complet pour les serveurs Roleplay. Il permet aux joueurs d'acheter des armes, munitions et objets illégaux en utilisant uniquement leur argent sale. Développé avec l'UI RageUI pour une expérience fluide.
ESX = exports["es_extended"]:getSharedObject()
local EtatMagasin = false
local quantityToBuy = 1
local currentItem = {}
local MenuMagasin = RageUI.CreateMenu("", "Nos rayons : ")
local armeblancheMenu = RageUI.CreateSubMenu(MenuMagasin, "", "Sélectionnez une arme blanche : ")
local armesMenu = RageUI.CreateSubMenu(MenuMagasin, "", "Sélectionnez une arme : ")
local balleMenu = RageUI.CreateSubMenu(MenuMagasin, "", "Sélectionnez des munitions : ")
local objectMenu = RageUI.CreateSubMenu(MenuMagasin, "", "Sélectionnez un objet : ")
local payementMenu = RageUI.CreateSubMenu(MenuMagasin, "", "Sélectionnez un paiement : ")
MenuMagasin.Closed = function()
EtatMagasin = false
FreezeEntityPosition(PlayerPedId(), false)
end
local function SelectItem(item)
currentItem = item
quantityToBuy = 1
end
function Blackmarket()
if EtatMagasin then
EtatMagasin = false
RageUI.Visible(MenuMagasin, false)
return
else
EtatMagasin = true
RageUI.Visible(MenuMagasin, true)
FreezeEntityPosition(PlayerPedId(), true)
end
CreateThread(function()
while EtatMagasin do
Wait(1)
RageUI.IsVisible(MenuMagasin, function()
RageUI.Separator("~o~↓↓~s~ Blackmarket ~o~↓↓~s~")
RageUI.Button("Armes Blanches", nil, {RightLabel = "→→"}, true, {}, armeblancheMenu)
RageUI.Button("Armes Létales", nil, {RightLabel = "→→"}, true, {}, armesMenu)
RageUI.Button("Munitions", nil, {RightLabel = "→→"}, true, {}, balleMenu)
RageUI.Button("Objets", nil, {RightLabel = "→→"}, true, {}, objectMenu)
end)
local function DrawItemsMenu(items)
for _,v in pairs(items) do
RageUI.Button(v.label, nil, {RightLabel = ("~y~%s$~s~ →→"):format(v.price)}, true, {
onSelected = function() SelectItem(v) end
}, payementMenu)
end
end
RageUI.IsVisible(armeblancheMenu, function() DrawItemsMenu(config_blackmarket.ArmesBlanches) end)
RageUI.IsVisible(armesMenu, function() DrawItemsMenu(config_blackmarket.Armes) end)
RageUI.IsVisible(balleMenu, function() DrawItemsMenu(config_blackmarket.Munitions) end)
RageUI.IsVisible(objectMenu, function() DrawItemsMenu(config_blackmarket.Objets) end)
RageUI.IsVisible(payementMenu, function()
if currentItem.label then
RageUI.Separator("~b~↓↓~s~ Moyen de paiement ~b~↓↓~s~")
local money = 0
for _,acc in pairs(ESX.PlayerData.accounts) do
if acc.name == 'black_money' then money = ESX.Math.GroupDigits(acc.money) end
end
RageUI.Info("Vos informations", {
("Argent sale : ~y~%s$~s~"):format(money),
("%s - ~y~%s$~s~"):format(currentItem.label, currentItem.price * quantityToBuy)
}, {})
RageUI.Button("Définir la quantité :", nil, {RightLabel = ("%s"):format(quantityToBuy)}, true, {
onSelected = function()
local qty = tonumber(KeyboardInput("Combien souhaitez-vous en acheter ?", "", 3))
if qty then quantityToBuy = qty else ESX.ShowNotification("~r~Erreur : seuls les chiffres sont autorisés") end
end
})
RageUI.Button("Payer en Argent Sale", nil, {RightLabel = "→→"}, true, {
onSelected = function()
TriggerServerEvent('roxoz:Payement', currentItem.label, currentItem.name, currentItem.price, quantityToBuy)
RageUI.GoBack()
end
})
end
end)
end
end)
end
CreateThread(function()
local pos = config_blackmarket.PositionOpenMenu
while true do
local waitTime = 1000
local playerCoords = GetEntityCoords(PlayerPedId())
local distance = #(playerCoords - vector3(pos.x, pos.y, pos.z))
if distance < 6.0 then
waitTime = 0
DrawMarker(config_blackmarket.MarkerType, pos.x, pos.y, pos.z - 0.98, 0.0, 0.0, 0.0, -90.0, 0.0, 0.0,
config_blackmarket.MarkerSize.x, config_blackmarket.MarkerSize.y, config_blackmarket.MarkerSize.z,
config_blackmarket.MarkerColor.r, config_blackmarket.MarkerColor.g, config_blackmarket.MarkerColor.b, config_blackmarket.MarkerColor.a,
config_blackmarket.MarkerSaute, true, 2, config_blackmarket.MarkerTourne)
ESX.ShowHelpNotification("Appuyez sur ~INPUT_CONTEXT~ pour ouvrir le menu")
if IsControlJustPressed(0, 51) then Blackmarket() end
end
Wait(waitTime)
end
end)
ESX = exports["es_extended"]:getSharedObject()
RegisterServerEvent("roxoz:Payement")
AddEventHandler("roxoz:Payement", function(label, name, price, quantity)
local xPlayer = ESX.GetPlayerFromId(source)
local total = price * quantity
if xPlayer.getAccount('black_money').money >= total then
xPlayer.removeAccountMoney('black_money', total)
xPlayer.addInventoryItem(name, quantity)
TriggerClientEvent('esx:showNotification', source,
("[~g~Succès~s~] Vous avez acheté %sx %s. (~y~-%s$~s~)"):format(quantity, label, total))
local embed = {
title = 'Achat Argent Sale',
description = ("**Action :** `Achat d'objets avec argent sale`\n**Joueur :** `%s` (ID : `%s`)\n**Objet :** `%s`\n**Quantité :** `%s`\n**Montant Dépensé :** `%s$`"):format(
GetPlayerName(source), source, label, quantity, total),
color = 16711680,
webhook = 'blackmarket',
}
EnvoieWebhook(embed)
else
TriggerClientEvent('esx:showNotification', source, "[~y~Impossible~s~] Vous n'avez pas assez d'argent sale.")
end
end)
config_blackmarket = {}
----------------------------- Menu RageUI -----------------------------
config_blackmarket.MarkerType = 6 -- Type de marker
config_blackmarket.MarkerSize = {x = 0.5, y = 0.5, z = 0.5} -- Taille du marker
config_blackmarket.MarkerColor = {r = 205, g = 205, b = 59, a = 255} -- Couleur du marker
config_blackmarket.MarkerSaute = false -- Le marker saute-t-il ?
config_blackmarket.MarkerTourne = false -- Le marker tourne-t-il ?
-- Position du menu (x, y, z, heading)
config_blackmarket.PositionOpenMenu = vector4(1351.0090, 3609.6855, 34.2449, 299.3940)
-------------------------- Catégories Armes --------------------------
config_blackmarket.Armes = {
{label = "Pétoire", name = "weapon_snspistol", price = 50000},
{label = "Berreta", name = "weapon_pistol", price = 50000},
}
config_blackmarket.Objets = {
{label = "LockPick", name = "lockpick", price = 1000},
{label = "Sac de braquage", name = "bag", price = 5000},
{label = "Forer", name = "drill", price = 50000},
{label = "Carte Blanchiment", name = "moneywash_keycard", price = 20000},
{label = "Ticket Blanchiment", name = "moneywash_ticket", price = 5000},
}
config_blackmarket.ArmesBlanches = {
{label = "Poing Américain", name = "weapon_knuckle", price = 7500},
{label = "Batte de Baseball", name = "weapon_bat", price = 5000},
{label = "Couteau", name = "weapon_knife", price = 9000},
{label = "Marteau", name = "weapon_hammer", price = 5000},
{label = "Clé à molette", name = "weapon_wrench", price = 5000},
}
config_blackmarket.Munitions = {
{label = ".22 Long Rifle", name = "ammo-22", price = 12},
{label = ".38 LC", name = "ammo-38", price = 12},
{label = ".44 Magnum", name = "ammo-44", price = 12},
{label = ".45 ACP", name = "ammo-45", price = 12},
{label = ".50 AE", name = "ammo-50", price = 12},
{label = "9mm", name = "ammo-9", price = 10},
{label = "Firework", name = "ammo-firework", price = 15},
{label = "Flare round", name = "ammo-flare", price = 15},
{label = "40mm Explosive", name = "ammo-grenade", price = 50},
{label = ".50 BMG", name = "ammo-heavysniper", price = 50},
{label = "Laser charge", name = "ammo-laser", price = 20},
{label = ".50 Ball", name = "ammo-musket", price = 20},
{label = "Railgun charge", name = "ammo-railgun", price = 20},
{label = "5.56x45", name = "ammo-rifle", price = 12},
{label = "7.62x39", name = "ammo-rifle2", price = 15},
{label = "Rocket", name = "ammo-rocket", price = 1000},
{label = "12 Gauge", name = "ammo-shotgun", price = 15},
{label = "7.62x51", name = "ammo-sniper", price = 50},
{label = "EMP round", name = "ammo-emp", price = 100},
}
Chaque transaction est enregistrée en temps réel via un Webhook Discord, permettant une surveillance administrative précise des flux.
Lua
ESX / Ox
Discord Webhook