Les reverse proxies disponibles aujourd'hui imposent un compromis : soit un framework performant sans interface opérationnelle (Pingora, Envoy), soit un binaire configurable mais sans observabilité intégrée (Nginx, Caddy), soit une solution full-featured sous licence AGPL (Sōzu). Lorica 1.0.0 sort en Apache 2.0 avec un positionnement différent : un seul binaire, zéro dépendance runtime, dashboard web embarqué, WAF et monitoring SLA inclus.
Contexte et positionnement
Lorica est construit sur Pingora, le moteur de proxy de Cloudflare (Apache 2.0), celui qui traite une part significative du trafic CDN de Cloudflare. L'idée de départ : prendre ce moteur éprouvé à l'échelle et l'habiller d'un plan de contrôle complet, là où Pingora reste volontairement un framework sans couche opérationnelle.
Le résultat : un binaire Linux x86_64 qui se configure entièrement depuis un navigateur, expose une API REST documentée OpenAPI 3.0.3, et intègre nativement le WAF, le monitoring SLA, le load testing et les notifications. Le mental model visé est celui d'une appliance réseau (Ubiquiti, pfSense) plutôt que d'un daemon Unix.
Architecture
L'architecture sépare strictement plan de données et plan de contrôle. Le plan de données s'appuie sur Pingora pour le proxy HTTP/HTTPS ; le plan de contrôle tourne sur axum, expose une API sur le port 9443, et sert le dashboard Svelte 5 (~59 KB gzippé) directement depuis le binaire via rust-embed.
La configuration est persistée dans SQLite (mode WAL, 13 migrations de schéma). Les mutations API propagent les changements au proxy via arc-swap, sans redémarrage. Côté TLS, rustls remplace OpenSSL entièrement ; la rotation de certificats s'effectue de manière atomique, également par arc-swap.
Le workspace Rust contient 25 crates : 15 issues du fork Pingora, 10 crates produit. Les crates de logique pure (WAF, config, notify, bench, API) ont #![deny(unsafe_code)] activé. La supply chain est auditée via cargo-deny.
Proxy et routage
Le moteur supporte HTTP/1.1, HTTP/2 (y compris upstream h2c pour le proxying gRPC), WebSocket passthrough et la terminaison TLS avec SNI. Le routage fonctionne par hostname exact, wildcard (*.example.com) ou catch-all (_), avec préfixe de chemin et règle « longest-prefix-first ».
Les « path rules » permettent des surcharges par sous-chemin : backend différent, cache, headers, rate limiting ou réponse directe (status 200/403/404). L'éditeur de route dans le dashboard couvre 25+ paramètres répartis sur 7 onglets (General, Timeouts, Security, Headers, CORS, Caching, Protection).


Load balancing : Round Robin pondéré (algorithme Nginx), Peak EWMA (sélection latency-aware), Consistent Hash, Random. Les backends en état dégradé (>2s de latence) ou down sont retirés de la rotation automatiquement. Le rechargement de configuration via l'API se fait sans interruption de trafic (arc-swap).
WAF et sécurité
Le moteur WAF embarque 49 règles inspirées de l'OWASP CRS : SQLi, XSS, path traversal, command injection, SSRF (cloud metadata, localhost, réseaux internes, URI schemes dangereux), Log4Shell/JNDI, XXE, CRLF. Le scanning couvre le corps des requêtes POST (texte jusqu'à 1 Mo) et applique un décodage URL récursif (3 passes maximum) pour résister aux techniques de double-encodage. Latence d'évaluation annoncée : <0,5 ms par requête, avec les patterns regex précompilés.

Les règles sont activables/désactivables individuellement depuis le dashboard ou l'API, avec persistance en SQLite. Des règles personnalisées peuvent être ajoutées.
La blocklist IP est auto-fetchée depuis le Data-Shield IPv4 Blocklist (~80 000 entrées, lookup O(1), rafraîchissement toutes les 6h). Le rate limiting est par route et par IP client ; les IPs dépassant les seuils sont bannies automatiquement. En mode multi-worker, les compteurs de bans sont agrégés globalement par le superviseur. Les protections DDoS couvrent le flood global, le slowloris et les connexions maximales par route.
Côté stockage, les clés privées des certificats et les configurations de notification sont chiffrées at-rest en AES-256-GCM. Les permissions du fichier SQLite sont forcées à 0600. Le hachage du mot de passe admin utilise Argon2id avec les paramètres OWASP (longueur maximale 128 caractères pour prévenir le DoS via Argon2). L'invalidation de session est déclenchée automatiquement sur changement de mot de passe, toutes sessions confondues sauf la session courante.
Dashboard et observabilité

La page Overview sert de cockpit : état des routes, backends, certificats, événements WAF récents, métriques ressources système. Un guide de démarrage interactif avec checklist s'affiche sur les nouvelles installations.

Le monitoring SLA fonctionne en deux modes. Le mode passif agrège le trafic réel avec des compteurs atomiques lock-free en fenêtres glissantes (1h/24h/7d/30d). Le mode actif envoie des sondes HTTP synthétiques configurables (méthode, chemin, statut attendu, intervalle, timeout). Les percentiles de latence (p50/p95/p99) sont exportables en CSV ou JSON. Des alertes sont déclenchées automatiquement quand le SLA passif passe sous le seuil configuré.
Les access logs arrivent en temps réel via WebSocket dans le dashboard, avec filtrage par IP client et export CSV/JSON. Les métriques Prometheus sont disponibles sur /metrics sans authentification : compteurs de requêtes, histogrammes de latence, état des backends, événements WAF, expiration des certificats.
Un moteur de load testing est intégré directement dans le dashboard : configuration du scénario (concurrence, RPS, durée), exécution en un clic, streaming des résultats en temps réel via SSE, comparaison des runs historiques. Un circuit breaker CPU (90%) arrête le test si la charge dépasse le seuil. Le target URL est restreint à localhost pour éviter des attaques externes.
Isolation des workers et haute disponibilité

En mode multi-process (--workers N), le superviseur fork+exec les workers et leur passe les sockets d'écoute via SCM_RIGHTS. La communication superviseur-worker passe par un canal protobuf sur Unix socketpair. Le heartbeat est vérifié toutes les 5 secondes ; les métriques (PID, état, latence) sont visibles dans la page System du dashboard.
Le graceful shutdown attend 30 secondes le drain des connexions actives avant d'envoyer SIGKILL. Le backoff de redémarrage des workers est exponentiel (1s-30s). Toutes les fonctionnalités (TLS, SLA, load testing, dispatch de notifications) sont opérationnelles en mode worker.
Performances mesurées sur une VM 4 vCPU / 8 Go RAM :
| Scénario | Débit |
|---|---|
| Single-process | ~6 500 req/s |
| 4 workers | ~25 000 req/s |
| Overhead WAF activé | ~6% |
| Bundle dashboard (gzip) | ~59 KB |
TLS et certificats
L'ACME est supporté en HTTP-01 (challenges servis sur le port 80 du proxy) et DNS-01 avec trois providers natifs : Cloudflare, Route53 (AWS SDK) et OVH. Les certificats multi-domaines SAN et wildcard (*.example.com) sont supportés en DNS-01. Un mode manuel DNS-01 en deux étapes permet d'utiliser n'importe quel provider DNS.
Les credentials DNS sont configurés une seule fois dans la page Settings et référencés par ID lors du provisionnement. Le renouvellement automatique vérifie toutes les 12h et renouvelle 30 jours avant expiration. Les certificats provisionnés manuellement (DNS-01 manuel) sont exclus du renouvellement automatique. Une rotation de clé de chiffrement est disponible via lorica rotate-key.
Installation
wget https://github.com/Rwx-G/Lorica/releases/latest/download/lorica.deb
sudo dpkg -i lorica.debLe paquet crée un utilisateur lorica, installe un service systemd avec durcissement (ProtectSystem=strict, NoNewPrivileges=yes, MemoryDenyWriteExecute=yes, SystemCallFilter=@system-service, CAP_NET_BIND_SERVICE) et démarre Lorica sur les ports 8080 (HTTP), 8443 (HTTPS) et 9443 (dashboard). Le mot de passe admin initial est affiché sur stdout au premier démarrage.
Pour passer en production sur les ports standards avec workers :
sudo systemctl edit lorica
[Service]
ExecStart=
ExecStart=/usr/bin/lorica --data-dir /var/lib/lorica \
--http-port 80 --https-port 443 --management-port 9443 \
--workers 4 --log-level infoLes packages .deb et .rpm sont signés GPG. Un guide de tuning (sysctl, limites de file descriptors, sizing des workers) est disponible dans le repo.
Couverture de tests
892 tests Rust répartis sur 25 crates (463 crates produit, 429 fork Pingora), 119 tests frontend Vitest, 350+ assertions E2E via Docker Compose (modes standalone et worker). Des cibles de fuzz testing couvrent le moteur WAF et les inputs API. Un benchmark reproductible en Docker est fourni pour mesurer le débit en conditions contrôlées.
Roadmap
HTTP/3 / QUIC est prévu, conditionné par l'intégration de tokio-quiche dans Pingora (PR #524 upstream). Le support Windows et macOS n'est pas prévu : le modèle fork+exec worker est spécifique à Linux. OpenSSL et BoringSSL ont été explicitement retirés ; rustls est le seul provider TLS.