منصة مفتوحة المصدر لمراقبة اللوقات وكشف الهجمات بشكل مباشر.
Quick Start · Screenshots · Architecture · عربي
I'm a Mechanical Engineering student from AlKhobar, but cybersecurity is what I do in my free time — CTFs, write-ups, breaking stuff in labs. After a while of just consuming content I wanted to actually build something instead.
Most open-source security tools I came across were either super basic (a script that greps logs) or way too heavy to actually set up on your own. I wanted something in between — something that looks like a real product, detects real attack patterns, and you can deploy with one command.
LogHunter is what came out of that. It's not perfect, there's stuff I'd still change, but it works and I learned a lot building it.
The platform has three main parts:
A Go collector that runs on your servers and watches log files (SSH auth, Nginx access). It tails them in real time, parses the lines, and ships events to the engine in batches. I picked Go because I wanted it lightweight — the binary ends up around 15MB.
A Python engine (FastAPI) that runs every incoming event through three detectors:
- Brute Force — counts failed logins per IP using a Redis sliding window. 5 failures in 5 minutes triggers an alert. (MITRE T1110)
- Web Attacks — regex patterns for SQL injection, XSS, and path traversal in URLs. Won't catch everything but it catches the obvious stuff. (MITRE T1190)
- Impossible Travel — flags when the same user logs in from two different countries within an hour. Last-seen location is stored in Redis. (MITRE T1078)
When a detector triggers, it creates an alert and pushes notifications to the channels you set up (Slack, Discord, Telegram, or any webhook).
A React dashboard with a dark theme, live updates over WebSocket, a world map with animated dots for threat origins, host monitoring, and a notifications page where you add channels from the UI instead of editing YAML files.
Login and first-time setup
Default login is admin/admin. The setup wizard forces you to change the password before you can use anything.
Threat map
SVG world map using d3-geo. The dots pulse and size scales with alert count. I originally used react-simple-maps but it doesn't support React 19 at all, so I rewrote it from scratch with raw d3 and topojson.
┌──────────────┐
│ Dashboard │ :3000
│ React + WS │
└──────┬───────┘
│
┌───────────┐ ┌───────▼───────┐ ┌───────────────────┐
│ Collector │─────▶│ Engine │─────▶│ Notifications │
│ (Go) │ HTTP │ (FastAPI) │ │ Slack / Discord / │
│ Agent │ │ + Detectors │ │ Telegram / Webhook│
└───────────┘ └──┬────────┬──┘ └───────────────────┘
│ │
┌────▼──┐ ┌───▼───┐
│Postgres│ │ Redis │
│ :5432 │ │ :6379 │
└────────┘ └───────┘
| Service | Port | Stack |
|---|---|---|
| Dashboard | 3000 | React 19, Vite, Tailwind, Recharts, d3-geo |
| Engine | 8000 | Python 3.12, FastAPI, SQLAlchemy async, Redis |
| Collector | 9000 | Go 1.24, goroutines, Viper, Zap |
| Database | 5432 | PostgreSQL 16 (internal only) |
| Cache | 6379 | Redis 7 (internal only) |
You need Docker and Docker Compose.
git clone https://github.com/2lba/loghunter.git
cd loghunter
cp .env.example .env
nano .envGenerate two secrets and paste them into .env:
openssl rand -hex 32 # for ENGINE_SECRET_KEY
openssl rand -hex 32 # for COLLECTOR_API_KEYThen bring everything up:
docker-compose up --build -dFirst build takes a few minutes. After that open http://localhost:3000 and log in with admin / admin. The setup wizard will make you change the password.
To populate the dashboard with attack data for testing:
chmod +x demo-data.sh
./demo-data.shIt runs 6 attack scenarios + background traffic. Takes around 30 seconds.
Since it's a security tool I tried to do this part right:
- Collector events require an API key header (
X-API-Key). No key, no ingestion. - JWT auth with bcrypt (12 rounds) for passwords.
- Login rate limit of 5 attempts per minute per IP.
- WebSocket needs a valid token in the query string.
- CORS only allows configured dashboard origins.
- Engine refuses to start in production mode if the secret key is still the default.
- Postgres and Redis aren't exposed outside the Docker network.
- Webhook URLs are masked in API responses.
- All containers run as non-root users.
- No raw SQL — everything goes through SQLAlchemy ORM.
loghunter/
├── engine/ # Detection engine (Python/FastAPI)
│ ├── app/
│ │ ├── api/ # REST + WebSocket endpoints
│ │ ├── core/ # Auth, rate limiting
│ │ ├── detectors/ # The three detection algorithms
│ │ ├── models/ # ORM models
│ │ ├── schemas/ # Pydantic schemas
│ │ └── services/ # Business logic
│ └── Dockerfile
├── collector/ # Log collector (Go)
│ ├── cmd/
│ ├── internal/ # Parsers (SSH, Nginx), shipper
│ └── Dockerfile
├── dashboard/ # Frontend (React)
│ ├── src/
│ │ ├── pages/
│ │ ├── components/
│ │ └── hooks/
│ └── Dockerfile
├── deployment/docker/ # DB schema
├── docker-compose.yml
├── demo-data.sh
└── .env.example
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /auth/login |
— | Get a JWT |
| GET | /auth/me |
Bearer | Current user |
| POST | /events/ingest |
API Key | Single event |
| POST | /events/ingest/batch |
API Key | Batch events |
| GET | /events |
Bearer | Query events |
| GET | /alerts |
Bearer | List alerts |
| GET | /alerts/stats |
Bearer | Stats |
| GET | /threats/geo |
Bearer | Geo data |
| GET/POST | /hosts |
Bearer | Host management |
| GET/POST | /notifications/channels |
Bearer | Channels |
| WS | /ws/alerts?token= |
JWT | Live stream |
| GET | /health |
— | Health check |
Interactive API docs at http://localhost:8000/docs in dev mode.
- passlib doesn't work with bcrypt 5.x. Switched to using bcrypt directly.
- react-simple-maps doesn't support React 19. Had to rewrite the threat map with d3-geo from scratch.
- FastAPI CORS middleware doesn't add headers to error responses. Wrote a custom middleware to fix it.
- Postgres INET columns return Python
IPv4Addressobjects. Pydantic doesn't know what to do with them. Added validators. - Special characters in
.envpasswords break shell scripts. Stick with alphanumeric. - React StrictMode renders twice in dev mode and broke my login flow. Removed it and added a manual guard.
- ML-based anomaly detection
- eBPF collector for kernel visibility
- Kubernetes operator
- Mobile app for on-call alerts
- LLM-powered alert investigation
- Multi-tenant with RBAC
- Splunk/Elastic forwarding
أداة مفتوحة المصدر لمراقبة سيرفراتك بشكل مباشر، تكشف الهجمات تلقائياً، وتنبهك على Slack أو Discord أو Telegram.
أنا طالب هندسة ميكانيكيه من الخبر، بس وقت فراغي كله بسيبرسيكيورتي وبرمجه. أغلب الأدوات المفتوحة إما بسيطة جداً (سكربت يقرأ ملف لوق) أو ثقيلة لدرجة ما تقدر تشغّلها بدون فريق كامل. حبيت أسوي شي بينهم — أداة شغّاله، شكلها احترافي، وتنزّلها بأمر واحد.
يجمع — Agent مكتوب بـ Go يراقب اللوقات (SSH, Nginx) ويرسلها للمحرّك بشكل مباشر.
يكشف — فيه ثلاث خوارزميات:
- Brute Force — يحسب محاولات الدخول الفاشلة لكل IP. لو 5 محاولات بـ 5 دقايق يطلّع تنبيه. (MITRE T1110)
- Web Attacks — يطابق patterns لهجمات SQL Injection و XSS و Path Traversal في الـ URLs. (MITRE T1190)
- Impossible Travel — يطلّع تنبيه لو نفس اليوزر دخل من بلدين مختلفه خلال ساعه. (MITRE T1078)
ينبّه — لما يكتشف شي، يرسل تنبيه على القنوات اللي ضبطتها ويحدّث الداشبورد لحظياً عن طريق WebSocket.
| الطبقة | التقنيه |
|---|---|
| محرّك الكشف | Python, FastAPI, SQLAlchemy |
| جامع اللوقات | Go, goroutines |
| الداشبورد | React 19, Tailwind, d3-geo |
| قاعدة البيانات | PostgreSQL 16 |
| الكاش | Redis 7 |
| البنيه التحتيه | Docker Compose |
تحتاج Docker و Docker Compose.
git clone https://github.com/2lba/loghunter.git
cd loghunter
cp .env.example .env
nano .envولّد اثنين secrets وحطّهم في .env:
openssl rand -hex 32 # حطّه في ENGINE_SECRET_KEY
openssl rand -hex 32 # حطّه في COLLECTOR_API_KEYوبعدين شغّل كل شي:
docker-compose up --build -dأول build ياخذ كم دقيقة. بعدها افتح http://localhost:3000 وادخل بـ admin / admin. أول تسجيل دخول راح يطلب منك تغيّر الباسوورد.
لو تبي تعبّي الداشبورد ببيانات اختبار:
chmod +x demo-data.sh
./demo-data.shالسكربت يشغّل 6 سيناريوهات هجمات + ترافيك عادي. ياخذ تقريباً 30 ثانية.
- أحداث الـ Collector تطلب API key في الـ header، ما فيه أحد يقدر يبعث events بدون مفتاح.
- JWT للداشبورد، و bcrypt مع 12 rounds للباسووردات.
- Rate limit على تسجيل الدخول: 5 محاولات بالدقيقه لكل IP.
- الـ WebSocket يبي توكن صالح في query string.
- CORS مقفول إلا على origins محدّده.
- المحرّك يرفض يشتغل بـ production لو الـ secret key لسّا اللي افتراضي.
- Postgres و Redis ما هم مكشوفين برّا Docker network.
- روابط الـ Webhook متخفّيه في الـ API responses.
- كل الـ containers تشتغل بـ users عاديين مو root.
- كل الـ queries عبر SQLAlchemy ORM، ما فيه أي SQL خام.
إذا المشروع فادك أو حسّيت إنك تعلّمت شي من الكود، star على الريبو يفرق معاي مرّه.
ولو حابب تدعمني ماديّا:
أي دعم يعني لي كثير، صراحه. بس بدون ضغط — استخدامك للأداة وملاحظاتك تكفي.
MIT — تفاصيل في LICENSE.
Abdulaziz AlQahtani · @2lba






