docs: analyse complète architecture + sécurité + recommandations
This commit is contained in:
935
ANALYSIS.md
Normal file
935
ANALYSIS.md
Normal file
@@ -0,0 +1,935 @@
|
|||||||
|
# 📊 Analyse Complète : NationsGlory Web Admin Panel + Serveur Minecraft
|
||||||
|
|
||||||
|
## 📋 Table des Matières
|
||||||
|
1. [Architecture Générale](#architecture-générale)
|
||||||
|
2. [Application Web](#application-web)
|
||||||
|
3. [Serveur Minecraft](#serveur-minecraft)
|
||||||
|
4. [Intégration](#intégration)
|
||||||
|
5. [Points de Sécurité](#points-de-sécurité)
|
||||||
|
6. [Recommandations](#recommandations)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture Générale
|
||||||
|
|
||||||
|
### Stack Technique
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ Frontend (SPA Vanilla JS) │
|
||||||
|
│ - index.html, app.js, style.css │
|
||||||
|
│ - API_URL: http://<hostname>:4001/api │
|
||||||
|
└────────────────────┬────────────────────────────────────┘
|
||||||
|
│ HTTP REST
|
||||||
|
┌────────────────────▼────────────────────────────────────┐
|
||||||
|
│ Backend (Express.js + Node.js 18) │
|
||||||
|
│ - server.js (port 4001, listens on 0.0.0.0) │
|
||||||
|
│ - 7 routes: auth, server, rcon, logs, players, │
|
||||||
|
│ whitelist, backup │
|
||||||
|
└────────────────────┬────────────────────────────────────┘
|
||||||
|
│ RCON (port 25575)
|
||||||
|
┌────────────────────▼────────────────────────────────────┐
|
||||||
|
│ Minecraft Server (mcpc.jar / Forge) │
|
||||||
|
│ - Version: 1.6.4 (MCPC+) │
|
||||||
|
│ - Mods: 60+ mods (Nations UI, FlansMod, etc) │
|
||||||
|
│ - Port: 25565 (server), 25575 (RCON) │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
Déploiement:
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ Docker Compose (machine distante: 192.168.1.252) │
|
||||||
|
│ - Container webnationsglory-admin │
|
||||||
|
│ - Volume mount: /mc-server → serveur Minecraft │
|
||||||
|
│ - Restart: unless-stopped │
|
||||||
|
│ - Port mapping: 4001:4001 │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### Taille & Ressources
|
||||||
|
- **Serveur Minecraft**: 143 MB (world + config + mods)
|
||||||
|
- **Web App**: ~200 KB (frontend + backend source)
|
||||||
|
- **Docker Image**: ~200 MB (Node.js 18-alpine + modules)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Application Web
|
||||||
|
|
||||||
|
### Backend Architecture
|
||||||
|
|
||||||
|
#### 1. **Serveur Principal** (`backend/src/server.js`)
|
||||||
|
```javascript
|
||||||
|
// Configuration
|
||||||
|
const PORT = 4001;
|
||||||
|
const SERVER_DIR = '/mc-server' (Docker) ou local path
|
||||||
|
const SESSION_SECRET = process.env.SESSION_SECRET
|
||||||
|
|
||||||
|
// Middlewares
|
||||||
|
- express.json() / urlencoded
|
||||||
|
- CORS (origin: true, credentials: true)
|
||||||
|
- express-session (24h max age, httpOnly)
|
||||||
|
|
||||||
|
// Routes
|
||||||
|
/api/auth → Authentification + enregistrement
|
||||||
|
/api/server → Configuration serveur (server.properties)
|
||||||
|
/api/rcon → Exécution commandes serveur
|
||||||
|
/api/logs → Historique logs
|
||||||
|
/api/players → Liste joueurs + statut OP
|
||||||
|
/api/whitelist → Gestion whitelist
|
||||||
|
/api/backup → Gestion backups
|
||||||
|
```
|
||||||
|
|
||||||
|
**Points clés:**
|
||||||
|
- ✅ Frontend path auto-detection (Docker vs local)
|
||||||
|
- ✅ CORS enabled avec credentials
|
||||||
|
- ✅ Session 24h max
|
||||||
|
- ⚠️ Session secret en dur ("your-secret-key-change-in-prod")
|
||||||
|
- ⚠️ HTTPS désactivé (secure: false)
|
||||||
|
|
||||||
|
#### 2. **Routes d'Authentification** (`backend/src/routes/auth.js`)
|
||||||
|
|
||||||
|
**Endpoints:**
|
||||||
|
```
|
||||||
|
POST /register → Créer compte admin (vérifie que MC username est OP)
|
||||||
|
POST /login → Connexion
|
||||||
|
POST /logout → Déconnexion
|
||||||
|
GET /check → Vérifier session active
|
||||||
|
POST /change-password → Changer mot de passe
|
||||||
|
```
|
||||||
|
|
||||||
|
**Mécanisme:**
|
||||||
|
```javascript
|
||||||
|
// Enregistrement
|
||||||
|
1. Vérifier que c'est le premier compte (users.json vide)
|
||||||
|
2. Lire ops.txt OU ops.json depuis serveur
|
||||||
|
3. Vérifier que mcUsername est dans la liste OPs
|
||||||
|
4. Hash password avec bcryptjs (10 rounds)
|
||||||
|
5. Sauvegarder dans users.json
|
||||||
|
|
||||||
|
// Connexion
|
||||||
|
1. Trouver utilisateur par username
|
||||||
|
2. Comparer password avec hash bcrypt
|
||||||
|
3. Créer session req.session.user
|
||||||
|
4. Session persiste dans memory (⚠️ perd les sessions au redémarrage!)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fichiers utilisés:**
|
||||||
|
- `backend/data/users.json` → Stockage utilisateurs + passwords hashés
|
||||||
|
- `~/NationsGlory_ServeurBuild_Red/ops.txt` → Admins serveur
|
||||||
|
- `~/NationsGlory_ServeurBuild_Red/ops.json` → Alternative format OPs
|
||||||
|
|
||||||
|
**Risques de sécurité:**
|
||||||
|
- ⚠️ Sessions en mémoire uniquement (pas persistentes)
|
||||||
|
- ⚠️ users.json stocké en local/Docker (pas de base de données)
|
||||||
|
- ⚠️ Pas de rate limiting sur login
|
||||||
|
- ⚠️ Pas de 2FA
|
||||||
|
|
||||||
|
#### 3. **Routes Serveur** (`backend/src/routes/server.js`)
|
||||||
|
|
||||||
|
**Endpoints:**
|
||||||
|
```
|
||||||
|
GET / → Lire server.properties
|
||||||
|
POST /update → Modifier une propriété
|
||||||
|
GET /jvm-args → Lire arguments JVM
|
||||||
|
POST /restart → Redémarrer le serveur
|
||||||
|
POST /stop → Arrêter le serveur
|
||||||
|
POST /backup → Créer backup
|
||||||
|
```
|
||||||
|
|
||||||
|
**Implémentation:**
|
||||||
|
- Parse `server.properties` ligne par ligne
|
||||||
|
- Supporte modification de propriétés individuelles
|
||||||
|
- Contrôle via RCON pour restart/stop
|
||||||
|
|
||||||
|
#### 4. **Routes RCON** (`backend/src/routes/rcon.js`)
|
||||||
|
|
||||||
|
**Architecture RCON:**
|
||||||
|
```javascript
|
||||||
|
// Classe RconClient (backend/src/utils/rcon.js)
|
||||||
|
- Protocole: Minecraft RCON (TCP port 25575)
|
||||||
|
- Packet format: [size][id][type][payload][null]
|
||||||
|
- Type 3 = Auth, Type 2 = Command, Type 0 = Response
|
||||||
|
- Timeout: 5s (auth), 10s (command)
|
||||||
|
|
||||||
|
// Implémentation
|
||||||
|
1. Parse server.properties pour rcon.port + rcon.password
|
||||||
|
2. Créer socket TCP vers serveur
|
||||||
|
3. S'authentifier avec password
|
||||||
|
4. Envoyer commandes
|
||||||
|
5. Recevoir réponses avec stream buffer
|
||||||
|
6. Timeout après 10s
|
||||||
|
```
|
||||||
|
|
||||||
|
**Endpoints:**
|
||||||
|
```
|
||||||
|
POST /command → Exécuter commande RCON
|
||||||
|
GET /history → Historique 200 dernières commandes
|
||||||
|
DELETE /history/:id → Nettoyer historique
|
||||||
|
```
|
||||||
|
|
||||||
|
**Commandes supportées:**
|
||||||
|
- `say <msg>` → Message serveur
|
||||||
|
- `stop` → Arrêter serveur
|
||||||
|
- `restart` → Redémarrer (custom)
|
||||||
|
- `list` → Joueurs en ligne (parsé pour joueurs)
|
||||||
|
- `op <player>` → Ajouter OP
|
||||||
|
- `whitelist add <player>` → Ajouter whitelist
|
||||||
|
- Tout ce que le serveur Minecraft supporte
|
||||||
|
|
||||||
|
**Historique:**
|
||||||
|
- Stocké dans `.web-admin/rcon-history.json`
|
||||||
|
- Limité à 200 dernières commandes
|
||||||
|
- Contient: timestamp, command, response, success, error
|
||||||
|
|
||||||
|
#### 5. **Routes Joueurs** (`backend/src/routes/players.js`)
|
||||||
|
|
||||||
|
**Endpoints:**
|
||||||
|
```
|
||||||
|
GET / → Liste tous joueurs + statut OP + dernière connexion
|
||||||
|
```
|
||||||
|
|
||||||
|
**Implémentation:**
|
||||||
|
```javascript
|
||||||
|
// 1. Lire world/players/*.dat (fichiers joueurs)
|
||||||
|
// 2. Mapper UUID → Nom via usercache.json
|
||||||
|
// 3. Lire ops.txt et parser noms OPs
|
||||||
|
// 4. Ajouter champ isOp: boolean pour chaque joueur
|
||||||
|
// 5. Retourner liste avec:
|
||||||
|
{
|
||||||
|
players: [
|
||||||
|
{ uuid, name, isOp, lastPlayed }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Données sources:**
|
||||||
|
- `world/players/*.dat` → Fichiers joueurs Minecraft
|
||||||
|
- `usercache.json` → Mapping UUID ↔ Nom (si existe)
|
||||||
|
- `ops.txt` → Noms des OPs (nouvelle feature)
|
||||||
|
|
||||||
|
#### 6. **Routes Whitelist** (`backend/src/routes/whitelist.js`)
|
||||||
|
|
||||||
|
**Endpoints:**
|
||||||
|
```
|
||||||
|
GET / → Lire whitelist
|
||||||
|
POST /add → Ajouter joueur
|
||||||
|
POST /remove → Retirer joueur
|
||||||
|
```
|
||||||
|
|
||||||
|
**Support formats:**
|
||||||
|
- `whitelist.json` → Format moderne `[{name, uuid}]`
|
||||||
|
- `whitelist.txt` → Format legacy, 1 nom/ligne
|
||||||
|
|
||||||
|
**Implémentation:**
|
||||||
|
- Auto-détecte format (JSON ou TXT)
|
||||||
|
- Priorise JSON si les deux existent
|
||||||
|
- Ajoute validation de doublons
|
||||||
|
|
||||||
|
#### 7. **Routes Logs** (`backend/src/routes/logs.js`)
|
||||||
|
|
||||||
|
**Endpoints:**
|
||||||
|
```
|
||||||
|
GET / → Logs serveur (recent-latest.log + ancien logs.1, logs.2, etc)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parsing:**
|
||||||
|
- Supporte format colorisé Minecraft
|
||||||
|
- Convertit codes Minecraft (§X) en HTML
|
||||||
|
- Retourne HTML colorisé pour UI
|
||||||
|
|
||||||
|
#### 8. **Routes Backup** (`backend/src/routes/backup.js`)
|
||||||
|
|
||||||
|
**Endpoints:**
|
||||||
|
```
|
||||||
|
GET / → Lister backups existants
|
||||||
|
POST /create → Créer nouveau backup (tar.gz)
|
||||||
|
GET /download → Télécharger backup
|
||||||
|
POST /restore → Restaurer depuis backup
|
||||||
|
```
|
||||||
|
|
||||||
|
**Implémentation:**
|
||||||
|
```bash
|
||||||
|
tar --exclude='.web-admin' --exclude='*.log.lck' \
|
||||||
|
-czf "backup-<timestamp>.tar.gz" .
|
||||||
|
```
|
||||||
|
|
||||||
|
**Répertoire:** `backups/` dans SERVER_DIR
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Frontend Architecture
|
||||||
|
|
||||||
|
#### 1. **Structure SPA** (`frontend/public/js/app.js`)
|
||||||
|
```javascript
|
||||||
|
// État global
|
||||||
|
let currentUser = null;
|
||||||
|
let isAuthenticated = false
|
||||||
|
|
||||||
|
// Points d'entrée
|
||||||
|
checkAuth() // Vérifier session
|
||||||
|
showLoginPage() // Authentification
|
||||||
|
showDashboard() // Interface admin
|
||||||
|
switchTab(tabName) // Navigation
|
||||||
|
|
||||||
|
// Sections disponibles (onglets)
|
||||||
|
- Dashboard → Infos serveur + joueurs en ligne
|
||||||
|
- Joueurs → Liste tous joueurs, statut OP
|
||||||
|
- Whitelist → Gérer whitelist
|
||||||
|
- Commandes RCON → Interface ligne de commande
|
||||||
|
- Logs → Consulter logs serveur
|
||||||
|
- Serveur → Settings server.properties
|
||||||
|
- Backups → Gérer backups + restore
|
||||||
|
- Paramètres → Changement password
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. **API_URL Resolution**
|
||||||
|
```javascript
|
||||||
|
// Avant: hardcoded localhost
|
||||||
|
const API_URL = 'http://localhost:4001/api';
|
||||||
|
|
||||||
|
// Après: Dynamic hostname detection
|
||||||
|
const API_URL = window.location.hostname === 'localhost' ||
|
||||||
|
window.location.hostname === '127.0.0.1'
|
||||||
|
? 'http://localhost:4001/api'
|
||||||
|
: `http://${window.location.hostname}:4001/api`;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Impact:** Permet accès via IP (192.168.1.252) sans modification code
|
||||||
|
|
||||||
|
#### 3. **Authentification Frontend**
|
||||||
|
```javascript
|
||||||
|
// Login Flow
|
||||||
|
checkAuth() →
|
||||||
|
fetch /auth/check →
|
||||||
|
Authentifié → showDashboard()
|
||||||
|
Non-auth → showLoginPage() → handleLogin() → fetch /auth/login
|
||||||
|
|
||||||
|
// Données transmises
|
||||||
|
POST /api/auth/login {
|
||||||
|
username: string,
|
||||||
|
password: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Réponse
|
||||||
|
{ authenticated: true, user: { username, mcUsername } }
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. **Dashboard Principal**
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ NationsGlory Admin Panel 🔓 admin ▼ Logout │
|
||||||
|
├─────────────────────────────────────────────────┤
|
||||||
|
│ Tabs: [Dashboard] [Joueurs] [Whitelist] [RCON] │
|
||||||
|
│ [Logs] [Serveur] [Backups] [Settings] │
|
||||||
|
├─────────────────────────────────────────────────┤
|
||||||
|
│ 📊 Dashboard │
|
||||||
|
│ • Joueurs connectés: 0/20 ⚪ │
|
||||||
|
│ • Statut serveur: ON/OFF │
|
||||||
|
│ • Mods chargés: 60+ │
|
||||||
|
│ • World: FLAT, seed: [value] │
|
||||||
|
│ • Max build height: 256 │
|
||||||
|
├─────────────────────────────────────────────────┤
|
||||||
|
│ 👥 Joueurs en ligne │
|
||||||
|
│ [Rafraîchir] │
|
||||||
|
│ 📋 Tous les Joueurs │
|
||||||
|
│ [Table avec columns: Nom, OP, UUID, LastPlayed] │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 5. **Sections Clés**
|
||||||
|
|
||||||
|
**A. Joueurs** (`loadPlayersData()`)
|
||||||
|
- Affiche tous les joueurs jamais connectés
|
||||||
|
- Colonne OP: ✅ OP ou ❌
|
||||||
|
- Colonne UUID + dernière connexion
|
||||||
|
- Chargement RCON `list` pour joueurs en ligne en temps réel
|
||||||
|
|
||||||
|
**B. Whitelist** (`getWhitelistHTML()`)
|
||||||
|
- Ajouter / Retirer joueurs
|
||||||
|
- Support JSON et TXT formats
|
||||||
|
- Validation doublons
|
||||||
|
|
||||||
|
**C. RCON Terminal** (`getRconHTML()`)
|
||||||
|
- Interface ligne de commande
|
||||||
|
- Input texte + historique
|
||||||
|
- Exécution commandes
|
||||||
|
- Affichage résultats
|
||||||
|
|
||||||
|
**D. Logs** (`getLogsHTML()`)
|
||||||
|
- Lecture logs serveur
|
||||||
|
- Coloration codes Minecraft
|
||||||
|
- Scroll horizontal si long
|
||||||
|
|
||||||
|
**E. Serveur Settings** (`getServerHTML()`)
|
||||||
|
- Liste properties modifiables
|
||||||
|
- Boutons Start/Stop/Restart
|
||||||
|
- Actions avec confirmation
|
||||||
|
|
||||||
|
**F. Backups** (`getBackupsHTML()`)
|
||||||
|
- Lister backups
|
||||||
|
- Créer backup
|
||||||
|
- Télécharger
|
||||||
|
- Restaurer depuis backup
|
||||||
|
|
||||||
|
**G. Settings** (`getSettingsHTML()`)
|
||||||
|
- Changement mot de passe
|
||||||
|
- About version
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Serveur Minecraft
|
||||||
|
|
||||||
|
### Configuration Serveur
|
||||||
|
|
||||||
|
**Server Properties** (`server.properties`)
|
||||||
|
```properties
|
||||||
|
server-ip= # Écoute sur toutes interfaces
|
||||||
|
server-port=25565 # Port Minecraft standard
|
||||||
|
max-players=20 # Limite 20 joueurs
|
||||||
|
gamemode=1 # Creative mode
|
||||||
|
difficulty=1 # Normal
|
||||||
|
level-type=FLAT # Monde plat
|
||||||
|
level-name=world # Dossier monde
|
||||||
|
enable-rcon=true # RCON activé
|
||||||
|
rcon.port=25575 # Port RCON
|
||||||
|
rcon.password=Landau8210 # ⚠️ Password en clair!
|
||||||
|
online-mode=false # Offline mode (permet cracked clients)
|
||||||
|
pvp=true # PvP activé
|
||||||
|
allow-nether=true # Nether autorisé
|
||||||
|
spawn-animals=true # Génération animaux
|
||||||
|
white-list=false # Whitelist désactivée par défaut
|
||||||
|
```
|
||||||
|
|
||||||
|
### Structure Serveur
|
||||||
|
|
||||||
|
```
|
||||||
|
NationsGlory_ServeurBuild_Red/
|
||||||
|
├── world/ # Données du monde
|
||||||
|
│ ├── players/ # Fichiers joueurs (.dat)
|
||||||
|
│ ├── stats/ # Stats joueurs (.json)
|
||||||
|
│ ├── region/ # Chunks du monde
|
||||||
|
│ └── level.dat # Info niveau
|
||||||
|
├── mods/ # 60+ mods Minecraft
|
||||||
|
│ └── [liste complète ci-dessous]
|
||||||
|
├── plugins/ # Plugins serveur
|
||||||
|
├── config/ # Configuration mods (60+ fichiers .cfg)
|
||||||
|
├── libraries/ # Dépendances Java
|
||||||
|
├── customnpcs/ # NPCs custom
|
||||||
|
├── Flan/ # Config FlansMod
|
||||||
|
├── .web-admin/ # Historique RCON
|
||||||
|
├── mcpc.jar # Serveur MCPC+
|
||||||
|
├── server.properties # Configuration
|
||||||
|
├── ops.txt # Admins serveur (format texte)
|
||||||
|
├── ops.json # Alternative format OPs
|
||||||
|
├── whitelist.txt # Whitelist (TXT)
|
||||||
|
├── whitelist.json # Alternative whitelist (JSON)
|
||||||
|
├── banned-players.txt # Bannis
|
||||||
|
├── banned-ips.txt # IPs bannies
|
||||||
|
├── usercache.json # Cache UUID ↔ Nom (si existe)
|
||||||
|
└── backups/ # Sauvegardes (créées par app)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Taille: 143 MB**
|
||||||
|
|
||||||
|
### Mods/Plugins Identifiés
|
||||||
|
|
||||||
|
Via `config/*.cfg`:
|
||||||
|
1. **NationsGlory mods**
|
||||||
|
- ngcore.cfg → Nations Core
|
||||||
|
- ngcontent.cfg → Contenu Nations
|
||||||
|
- nationsui.cfg → Interface Nations
|
||||||
|
- nationsgui.json
|
||||||
|
- nationsmachine.cfg → Machines Nations
|
||||||
|
- NGUpgrades.json
|
||||||
|
|
||||||
|
2. **Gameplay Mods**
|
||||||
|
- FlansMod.cfg → Armes, véhicules
|
||||||
|
- WeaponMod.cfg → Armes custom
|
||||||
|
- ICBM.cfg → Missiles
|
||||||
|
- CustomNpcs.cfg → NPCs custom
|
||||||
|
- GetAllTheSeeds.cfg
|
||||||
|
- AnimalBikes.cfg
|
||||||
|
|
||||||
|
3. **Building/Tech**
|
||||||
|
- Chisel.cfg → Blocs décoratifs
|
||||||
|
- BiblioCraft.cfg → Furniture
|
||||||
|
- ArmorStatusHUD.cfg
|
||||||
|
- TLSpecialArmor.cfg
|
||||||
|
|
||||||
|
4. **Farming**
|
||||||
|
- PAM mods (multiple):
|
||||||
|
- pamtemperateplants.cfg
|
||||||
|
- pamweeeflowers.cfg
|
||||||
|
- pamrandomaplants.cfg
|
||||||
|
- pamextendedglass.cfg
|
||||||
|
|
||||||
|
5. **Infrastructure**
|
||||||
|
- Galacticraft/ → Espace
|
||||||
|
- Netherrocks → Nether
|
||||||
|
- AquaTweaks.cfg → Eau
|
||||||
|
- MelonSpawn.cfg
|
||||||
|
- Autoutils.cfg
|
||||||
|
|
||||||
|
6. **Visualization**
|
||||||
|
- MapWriter.cfg → Mini-map
|
||||||
|
- ArmorStatusHUD.cfg
|
||||||
|
|
||||||
|
7. **Framework/Admin**
|
||||||
|
- forge.cfg → Forge base
|
||||||
|
- forgeChunkLoading.cfg
|
||||||
|
- bspkrsCore.cfg → Libraire
|
||||||
|
- logging.properties
|
||||||
|
|
||||||
|
**Version:** 1.6.4 (Minecraft 1.6.4, probablement MCPC+ pour Forge)
|
||||||
|
|
||||||
|
### Architecture Serveur MCPC+
|
||||||
|
|
||||||
|
MCPC+ = Minecraft + Bukkit compatibility + Forge mods
|
||||||
|
- Combine Minecraft serveur vanilla
|
||||||
|
- Ajoute Forge pour mods
|
||||||
|
- Supporte plugins Bukkit (en parallèle)
|
||||||
|
- Version 1.6.4 (assez vieille, 2013)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Intégration
|
||||||
|
|
||||||
|
### Flux de Données
|
||||||
|
|
||||||
|
```
|
||||||
|
Frontend (Browser)
|
||||||
|
↓ fetch /api/auth/login
|
||||||
|
Backend (Express)
|
||||||
|
├─ Vérifie users.json
|
||||||
|
├─ Hash password bcrypt
|
||||||
|
├─ Crée session
|
||||||
|
└─ Return { authenticated: true }
|
||||||
|
↓ fetch /api/rcon/command
|
||||||
|
Backend RCON Client
|
||||||
|
├─ Parse server.properties
|
||||||
|
├─ Connect TCP:25575
|
||||||
|
├─ Auth avec rcon.password
|
||||||
|
├─ Send command bytes
|
||||||
|
└─ Receive/parse response
|
||||||
|
↓
|
||||||
|
Minecraft Server (MCPC+)
|
||||||
|
├─ Process command
|
||||||
|
├─ Modify world/players/ ou server.properties
|
||||||
|
└─ Send output back
|
||||||
|
↓
|
||||||
|
Backend Response
|
||||||
|
└─ Return output JSON
|
||||||
|
↓
|
||||||
|
Frontend Display
|
||||||
|
└─ Show result to user
|
||||||
|
```
|
||||||
|
|
||||||
|
### Session Management
|
||||||
|
|
||||||
|
**Current:** Express-session in-memory
|
||||||
|
```javascript
|
||||||
|
app.use(session({
|
||||||
|
secret: SESSION_SECRET,
|
||||||
|
resave: false,
|
||||||
|
saveUninitialized: true,
|
||||||
|
cookie: {
|
||||||
|
secure: false, // HTTP only (not HTTPS)
|
||||||
|
httpOnly: true, // No JS access
|
||||||
|
sameSite: 'lax', // CSRF protection
|
||||||
|
maxAge: 24 * 60 * 60 * 1000 // 24 hours
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
```
|
||||||
|
|
||||||
|
**Problème:** Sessions perdues au redémarrage Docker
|
||||||
|
- ✅ currentUser reste authentifié tant que session active
|
||||||
|
- ❌ Redémarrage container = logout automatique
|
||||||
|
- **Solution:** Utiliser connect-mongo, redis, ou JWT
|
||||||
|
|
||||||
|
### RCON Integration
|
||||||
|
|
||||||
|
```
|
||||||
|
Web UI → Command → Backend → RCON Client → Minecraft Server → Response
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example: /api/rcon/command POST {"command": "list"}**
|
||||||
|
|
||||||
|
1. Backend RCON Client:
|
||||||
|
```
|
||||||
|
- Read: server.properties (rcon.port=25575, rcon.password=Landau8210)
|
||||||
|
- Connect: TCP 192.168.1.252:25575
|
||||||
|
- Authenticate: send password bytes
|
||||||
|
- Send: "list" command
|
||||||
|
- Parse: "There are 1/20 players online: anakine22"
|
||||||
|
- Return: JSON response
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Frontend parses & displays
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Points de Sécurité
|
||||||
|
|
||||||
|
### 🔴 Critiques
|
||||||
|
|
||||||
|
1. **RCON Password en Clair**
|
||||||
|
```properties
|
||||||
|
rcon.password=Landau8210 # Visible dans server.properties
|
||||||
|
```
|
||||||
|
**Risque:** Accès direct au serveur Minecraft si fichier leak
|
||||||
|
**Fix:** Lire depuis env vars, pas fichier
|
||||||
|
|
||||||
|
2. **Session en Mémoire**
|
||||||
|
```javascript
|
||||||
|
// Sessions perdues au redémarrage
|
||||||
|
// Accessible seulement au container courant (pas clustering)
|
||||||
|
```
|
||||||
|
**Risque:** Forcer logout en case de crash/redémarrage
|
||||||
|
**Fix:** Store sessions en Redis/DB
|
||||||
|
|
||||||
|
3. **HTTP seulement**
|
||||||
|
```javascript
|
||||||
|
secure: false // No HTTPS
|
||||||
|
```
|
||||||
|
**Risque:** Credentials en clair sur le réseau
|
||||||
|
**Fix:** Activer HTTPS, self-signed cert minimum
|
||||||
|
|
||||||
|
4. **users.json pas encrypté**
|
||||||
|
```
|
||||||
|
backend/data/users.json
|
||||||
|
```
|
||||||
|
**Contient:** Passwords bcryptés (OK) + usernames (leak de données)
|
||||||
|
**Fix:** Chiffrer fichier ou utiliser database
|
||||||
|
|
||||||
|
### 🟡 Modérés
|
||||||
|
|
||||||
|
5. **Pas de Rate Limiting**
|
||||||
|
```
|
||||||
|
Brute force possible sur endpoint /auth/login
|
||||||
|
```
|
||||||
|
**Fix:** express-rate-limit middleware
|
||||||
|
|
||||||
|
6. **Pas de 2FA**
|
||||||
|
```
|
||||||
|
Seul username/password
|
||||||
|
```
|
||||||
|
**Fix:** Ajouter TOTP si critique
|
||||||
|
|
||||||
|
7. **CORS trop permissif**
|
||||||
|
```javascript
|
||||||
|
CORS({ origin: true, credentials: true })
|
||||||
|
```
|
||||||
|
**Risque:** N'importe quel domaine peut faire requêtes
|
||||||
|
**Fix:** Whitelist domains explicitement
|
||||||
|
|
||||||
|
8. **Pas de CSRF tokens**
|
||||||
|
```
|
||||||
|
State-changing operations (POST/DELETE) sans CSRF
|
||||||
|
```
|
||||||
|
**Fix:** Ajouter csurf middleware
|
||||||
|
|
||||||
|
9. **Pas de input validation**
|
||||||
|
```javascript
|
||||||
|
// POST /api/server/update
|
||||||
|
{ property, value } // Pas de validation property names
|
||||||
|
```
|
||||||
|
**Risque:** Injection server.properties arbitraire
|
||||||
|
**Fix:** Whitelist propriétés modifiables
|
||||||
|
|
||||||
|
10. **Fichiers logs exposés**
|
||||||
|
```javascript
|
||||||
|
GET /api/logs expose tous les logs du serveur
|
||||||
|
```
|
||||||
|
**Risque:** Info sensitive (errors, plugins, config)
|
||||||
|
**Fix:** Limiter logs, filtrer data sensitive
|
||||||
|
|
||||||
|
### 🟢 Acceptables
|
||||||
|
|
||||||
|
11. **online-mode=false**
|
||||||
|
```properties
|
||||||
|
Serveur accepte cracked clients (offline mode)
|
||||||
|
```
|
||||||
|
**Pourquoi:** Peut être intentionnel pour privé réseau
|
||||||
|
|
||||||
|
12. **Debug pas activé**
|
||||||
|
```properties
|
||||||
|
debug=false ✓
|
||||||
|
```
|
||||||
|
|
||||||
|
13. **Entity tracking config non visible** ✓
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Recommandations
|
||||||
|
|
||||||
|
### 🚀 Priorité 1: Critique
|
||||||
|
|
||||||
|
#### 1. Ajouter HTTPS/SSL
|
||||||
|
```dockerfile
|
||||||
|
# docker-compose.yml
|
||||||
|
volumes:
|
||||||
|
- ./certs:/app/certs # Certificates auto-renew via certbot
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
- HTTPS_CERT=/app/certs/cert.pem
|
||||||
|
- HTTPS_KEY=/app/certs/key.pem
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Session Persistence (Redis)
|
||||||
|
```bash
|
||||||
|
# Ajouter redis service
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
# ...
|
||||||
|
depends_on:
|
||||||
|
- redis
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
volumes:
|
||||||
|
- redis-data:/data
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// backend/src/server.js
|
||||||
|
const RedisStore = require('connect-redis').default;
|
||||||
|
const { createClient } = require('redis');
|
||||||
|
|
||||||
|
const redisClient = createClient({ host: 'redis', port: 6379 });
|
||||||
|
const store = new RedisStore({ client: redisClient });
|
||||||
|
|
||||||
|
app.use(session({
|
||||||
|
store,
|
||||||
|
secret: process.env.SESSION_SECRET,
|
||||||
|
// ...
|
||||||
|
}));
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. RCON Password sécurisé
|
||||||
|
```bash
|
||||||
|
# .env
|
||||||
|
RCON_PASSWORD=${RCON_PASSWORD} # Via docker-compose.yml
|
||||||
|
|
||||||
|
# Avoid storing in server.properties
|
||||||
|
# Option: Lire depuis /run/secrets/rcon_password (Docker Secrets)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. Rate Limiting
|
||||||
|
```javascript
|
||||||
|
// backend/src/middleware/rateLimit.js
|
||||||
|
const rateLimit = require('express-rate-limit');
|
||||||
|
|
||||||
|
const loginLimiter = rateLimit({
|
||||||
|
windowMs: 15 * 60 * 1000, // 15 min
|
||||||
|
max: 5, // 5 tentatives
|
||||||
|
message: 'Trop de tentatives login'
|
||||||
|
});
|
||||||
|
|
||||||
|
app.post('/api/auth/login', loginLimiter, handleLogin);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 5. Validation Input Server Properties
|
||||||
|
```javascript
|
||||||
|
// backend/src/routes/server.js
|
||||||
|
const ALLOWED_PROPERTIES = [
|
||||||
|
'max-players',
|
||||||
|
'difficulty',
|
||||||
|
'pvp',
|
||||||
|
'enable-nether',
|
||||||
|
'server-ip',
|
||||||
|
'server-port', // Attention: change port!
|
||||||
|
// NOT: gamemode, level-type, level-name, rcon.password, etc
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!ALLOWED_PROPERTIES.includes(property)) {
|
||||||
|
return res.status(400).json({ error: 'Propriété non modifiable' });
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🎯 Priorité 2: Important
|
||||||
|
|
||||||
|
#### 6. CSRF Tokens
|
||||||
|
```javascript
|
||||||
|
const csrf = require('csurf');
|
||||||
|
const csrfProtection = csrf({ cookie: false, sessionKey: 'session' });
|
||||||
|
|
||||||
|
app.post('/api/server/update', csrfProtection, handleUpdate);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 7. Chiffrer users.json
|
||||||
|
```javascript
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const FILE_KEY = Buffer.from(process.env.FILE_ENCRYPTION_KEY, 'hex');
|
||||||
|
|
||||||
|
function encryptUsers(users) {
|
||||||
|
const iv = crypto.randomBytes(16);
|
||||||
|
const cipher = crypto.createCipheriv('aes-256-gcm', FILE_KEY, iv);
|
||||||
|
const encrypted = cipher.update(JSON.stringify(users));
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 8. Logs Filtering
|
||||||
|
```javascript
|
||||||
|
// backend/src/routes/logs.js
|
||||||
|
// Filtrer:
|
||||||
|
// - Passwords
|
||||||
|
// - Database credentials
|
||||||
|
// - API keys
|
||||||
|
// - Player IPs
|
||||||
|
// - Internal errors
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 9. Database Migration
|
||||||
|
```
|
||||||
|
Remplacer:
|
||||||
|
users.json → PostgreSQL (+ migrations)
|
||||||
|
RCON history JSON → Database table
|
||||||
|
|
||||||
|
Avantages:
|
||||||
|
- Transactions
|
||||||
|
- Backups
|
||||||
|
- Multi-instance
|
||||||
|
- Better performance
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 10. API Documentation
|
||||||
|
```
|
||||||
|
Ajouter Swagger/OpenAPI
|
||||||
|
- /api-docs
|
||||||
|
- Documentation endpoints
|
||||||
|
- Authentification requirements
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🛠️ Priorité 3: Nice to Have
|
||||||
|
|
||||||
|
#### 11. Monitoring & Alerting
|
||||||
|
```javascript
|
||||||
|
// Backend metrics
|
||||||
|
- Uptime server
|
||||||
|
- RCON connection failures
|
||||||
|
- API response times
|
||||||
|
- Error rate
|
||||||
|
|
||||||
|
// Integration: Prometheus + Grafana
|
||||||
|
// Discord webhooks for alerts
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 12. Admin Audit Log
|
||||||
|
```javascript
|
||||||
|
// Log all admin actions
|
||||||
|
- Login/logout timestamps
|
||||||
|
- Command executor + command
|
||||||
|
- Property changes
|
||||||
|
- File modifications
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 13. World Backup Restoration
|
||||||
|
```javascript
|
||||||
|
// Current: Créer backup ✓
|
||||||
|
// TODO: Restore backup avec safety checks
|
||||||
|
// - Stop serveur
|
||||||
|
// - Restore world/
|
||||||
|
// - Restart serveur
|
||||||
|
// - Verify integrité
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 14. Multi-Admin Support
|
||||||
|
```javascript
|
||||||
|
// Current: 1 seul admin (users.json = array mais UI single)
|
||||||
|
// TODO:
|
||||||
|
// - Multiple admins support
|
||||||
|
// - Role-based access (RBAC)
|
||||||
|
// - Permissions per admin
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 15. Players Statistics
|
||||||
|
```javascript
|
||||||
|
// Ajouter analytics:
|
||||||
|
// - Playtime per player
|
||||||
|
// - Last 7 days activity
|
||||||
|
// - Top builders/killers
|
||||||
|
// - Trends
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Métriques de Santé
|
||||||
|
|
||||||
|
### ✅ Points Forts
|
||||||
|
1. **Architecture modulaire** → 7 routes bien séparées
|
||||||
|
2. **Vanilla JS frontend** → Pas de build complexity
|
||||||
|
3. **RCON protocol bien implémenté** → Pas de pertes commands
|
||||||
|
4. **Session management** → Auth basique ok
|
||||||
|
5. **Docker-ready** → Déploiement facile
|
||||||
|
6. **Markdown docs** → QUICKSTART, DEPLOYMENT, MAINTENANCE
|
||||||
|
7. **Dynamic API URL** → Fonctionne IP ou localhost
|
||||||
|
8. **OP status tracking** → Lecture ops.txt correcte
|
||||||
|
|
||||||
|
### ⚠️ Domaines d'Amélioration
|
||||||
|
1. **Sécurité** → HTTPS, rate limiting, validation input
|
||||||
|
2. **Persistence** → Session, database
|
||||||
|
3. **Error handling** → Logs réseau, retry logic
|
||||||
|
4. **Scalability** → Multi-instance support
|
||||||
|
5. **Observability** → Monitoring, alerting
|
||||||
|
6. **Testing** → Tests unitaires + intégration
|
||||||
|
7. **Code quality** → Linting, type checking
|
||||||
|
8. **Features** → 2FA, RBAC, audit log
|
||||||
|
|
||||||
|
### 📈 Performance
|
||||||
|
- **Frontend**: Single file SPA (~61 KB)
|
||||||
|
- **Backend**: 104 lines server.js, routes <250 lines each
|
||||||
|
- **Response time**: <100ms API (RCON varies)
|
||||||
|
- **Memory**: ~50-100 MB Node.js container
|
||||||
|
- **Concurrency**: Sequential RCON (une commande à la fois)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
### Current State
|
||||||
|
L'application est **fonctionnelle** pour un usage **LAN privé** ou **réseau interne**.
|
||||||
|
|
||||||
|
**Prêt pour production?** ❌
|
||||||
|
- Manque HTTPS, rate limiting, CSRF
|
||||||
|
- Sessions perdues au redémarrage
|
||||||
|
- Pas de database
|
||||||
|
- Input validation insuffisante
|
||||||
|
|
||||||
|
**Prêt pour LAN interne?** ✅
|
||||||
|
- Sécurité acceptable pour réseau de confiance
|
||||||
|
- Toutes features essentielles présentes
|
||||||
|
- Déploiement Docker simple
|
||||||
|
|
||||||
|
### Priorités à Court Terme
|
||||||
|
1. ✅ **Dynamic API URL** (FAIT: app.js détecte hostname)
|
||||||
|
2. ✅ **OP status tracking** (FAIT: lit ops.txt, affiche ✅/❌)
|
||||||
|
3. ⏳ **Session persistence** (Redis recommended)
|
||||||
|
4. ⏳ **HTTPS + rate limiting** (Pour production)
|
||||||
|
5. ⏳ **Input validation** (Server properties + RCON)
|
||||||
|
|
||||||
|
### Prochaines Étapes Recommandées
|
||||||
|
```
|
||||||
|
Phase 1 (Cette semaine)
|
||||||
|
[ ] Tester OP display après refresh navigateur
|
||||||
|
[ ] Documenter RCON commands disponibles
|
||||||
|
[ ] Ajouter healthcheck serveur Minecraft
|
||||||
|
|
||||||
|
Phase 2 (Semaine 2)
|
||||||
|
[ ] Implémenter Redis pour sessions
|
||||||
|
[ ] Ajouter HTTPS auto-signed
|
||||||
|
[ ] Rate limiting login
|
||||||
|
|
||||||
|
Phase 3 (Semaine 3)
|
||||||
|
[ ] Migrer users.json → Database
|
||||||
|
[ ] Input validation complete
|
||||||
|
[ ] CSRF tokens
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Document généré:** 5 février 2026
|
||||||
|
**Version:** 1.0
|
||||||
|
**Auteur:** GitHub Copilot
|
||||||
Reference in New Issue
Block a user