A standalone PHP honeypot server that emulates CMS installations (WordPress, Drupal, Joomla) to detect and report malicious traffic to the reportedip.de API.
Zero external Composer dependencies. Runs on vanilla PHP 8.2+. Uses SQLite for persistence.
We're looking for testers and community members!
We are actively searching for test users and contributors who want to help improve the data quality and detection coverage of reportedip.de. Every honeypot instance you run contributes attack data that helps protect the entire community.
To get started, you need a Community Access Key (API key). Please contact us at 1@reportedip.de to request your key. It's free.
Whether you're running a small VPS, a shared hosting account, or a dedicated server — every installation helps.
- CMS Emulation — Realistic WordPress, Drupal, and Joomla front-ends with login pages, admin panels, REST APIs, RSS feeds, sitemaps, and vulnerability paths
- 36 Threat Analyzers — SQL injection, XSS, path traversal, brute force, credential stuffing, SSRF, XML-RPC abuse, plugin exploits, config file access, and more
- Automatic Reporting — Detected threats are queued and batch-reported to the reportedip.de API with rate limiting and exponential backoff
- Webhooks — Forward detections in real time to your own logging/SIEM systems or third-party abuse databases (AbuseIPDB, Slack, Discord, custom APIs) with configurable methods, headers, body templates, and optional HMAC-SHA256 signatures
- Admin Dashboard — Web-based panel for monitoring attacks, viewing statistics, managing whitelists, and generating AI content
- AI Content Generation — Optional OpenAI integration to generate realistic blog posts for the fake CMS (AJAX-based, one post at a time to avoid timeouts)
- Bot Detection — Classifies visitors as good bots, bad bots, AI agents, hackers, or humans
- Cloudflare Support — Real IP resolution behind Cloudflare and custom reverse proxies via trusted_proxies config
- Security Hardened — CSRF protection, bcrypt auth, brute-force lockout, security headers (CSP, X-Frame-Options, HSTS), session IP binding
- Docker Ready — Ships with Dockerfile and docker-compose for instant deployment
- Zero Dependencies — No external Composer packages; built-in PSR-4 autoloader fallback
- PHP 8.2+
- Extensions:
pdo_sqlite,curl,json - Web server (nginx or Apache) with all requests routed to
public/index.php
git clone https://github.com/reportedip/honeypot-server.git
cd honeypot-server
docker compose -f docker/docker-compose.yml up -dOpen the container URL in your browser — the web installer starts automatically on first visit.
git clone https://github.com/reportedip/honeypot-server.git
cd honeypot-serverConfigure your web server:
- nginx — Copy
config/nginx.conf.exampleand adjust paths - Apache — Copy
config/apache.htaccess.exampleto your document root
Then open the website URL in your browser. The web installer starts automatically when no config/config.php exists and guides you through:
- System requirements check (PHP 8.2+, required extensions)
- Community Access Key — contact 1@reportedip.de to get yours (free)
- CMS profile selection (WordPress / Drupal / Joomla)
- Admin panel path and password
- Optional AI content settings (OpenAI API key, model, language)
- Automatic initialization (database, directories, IP whitelist)
By default, the honeypot uses web cron mode: the report queue is automatically processed in small batches (2 reports) after every page visit. No external cron job is needed. This is ideal for shared hosting.
For high-traffic installations, switch to cron mode in config/config.php:
'queue_mode' => 'cron',Then set up a cron job:
# Process the report queue every 5 minutes
*/5 * * * * php /path/to/honeypot-server/cli.php process-queueCleanup of old entries runs automatically in both modes.
All settings are in config/config.php (generated by the installer). See config/config.example.php for defaults and documentation.
| Option | Default | Description |
|---|---|---|
api_key |
'' |
Community Access Key — request at 1@reportedip.de |
api_url |
'https://reportedip.de/...' |
API endpoint URL |
cms_profile |
'wordpress' |
CMS to emulate: wordpress, drupal, joomla |
admin_path |
'/_hp_admin' |
Path to the honeypot admin panel |
admin_password_hash |
'' |
Bcrypt hash (set by installer) |
db_path |
'data/honeypot.sqlite' |
SQLite database path |
trusted_proxies |
Cloudflare CIDRs | Trusted proxy IP ranges for real IP resolution |
debug |
false |
Enable verbose error output |
| Option | Default | Description |
|---|---|---|
rate_limit_per_ip |
10 |
Max log entries per IP per minute |
report_rate_limit |
60 |
Max API reports per minute |
report_batch_size |
10 |
Reports per cron batch |
queue_mode |
'web' |
'web' (automatic) or 'cron' (manual via cli.php) |
log_retention_days |
90 |
Days to keep log entries |
session_lifetime |
3600 |
Admin session lifetime (seconds) |
| Option | Default | Description |
|---|---|---|
openai_api_key |
'' |
OpenAI API key (enables content generation) |
openai_base_url |
'https://api.openai.com/v1' |
API base URL (change for compatible providers) |
openai_model |
'gpt-4o-mini' |
Model to use for generation |
content_language |
'en' |
Default language (en or de) |
content_niche |
'' |
Default topic niche for posts |
Each profile emulates a specific CMS with realistic URL patterns, HTTP headers, and response templates:
| Profile | Emulated Paths | Fake Headers |
|---|---|---|
| WordPress | wp-login.php, wp-admin/, wp-json/, xmlrpc.php, /feed/, plugin paths |
X-Pingback, Link: wp-json, Server: Apache |
| Drupal | user/login, admin/, jsonapi/, update.php, module paths |
X-Generator: Drupal 10, X-Drupal-Cache |
| Joomla | administrator/, api/, component/ paths |
X-Content-Encoded-By: Joomla! 4.4 |
The DetectionPipeline runs 36 analyzers on every request:
| Analyzer | Detects |
|---|---|
SqlInjectionAnalyzer |
SQL injection in query params, POST data, headers |
XssAnalyzer |
Cross-site scripting via script tags, event handlers |
PathTraversalAnalyzer |
Directory traversal (../, encoded variants) |
BruteForceAnalyzer |
Repeated login attempts |
CredentialStuffingAnalyzer |
Common username/password combinations |
PathScanningAnalyzer |
Probing for admin panels, backup files |
PluginExploitAnalyzer |
Known CMS plugin vulnerability paths |
ConfigAccessAnalyzer |
Attempts to access .env, wp-config.php, etc. |
VulnerabilityProbeAnalyzer |
Shellshock, Log4Shell, PHPUnit exploits |
XmlRpcAnalyzer |
XML-RPC pingback abuse, method enumeration |
UserAgentAnalyzer |
Malicious tools (sqlmap, nikto, dirbuster) |
HeaderAnomalyAnalyzer |
Missing/suspicious HTTP headers |
HttpVerbAnalyzer |
Unusual HTTP methods (TRACE, DELETE, etc.) |
SsrfAnalyzer |
Server-side request forgery attempts |
FormSpamAnalyzer |
Spam submissions via comment/contact forms |
ThemeExploitAnalyzer |
Theme vulnerability exploitation, TimThumb access, theme editor abuse |
UserEnumerationAnalyzer |
User enumeration via author params, REST API, sitemaps |
FileUploadMalwareAnalyzer |
Malicious file uploads, double extensions, PHP code signatures |
AdminDirectoryScanningAnalyzer |
CMS admin directory scanning and probing |
ResourceExhaustionAnalyzer |
DoS attacks, oversized requests, regex DoS, XML entity expansion |
WpCronAbuseAnalyzer |
WP-Cron abuse, heartbeat abuse, REST API bulk operations |
VersionFingerprintingAnalyzer |
CMS version fingerprinting via readme/license files, version params |
DatabaseBackupAccessAnalyzer |
Database dump and backup file access attempts |
RegistrationHoneypotAnalyzer |
Automated registration spam, disposable emails, bot patterns |
SearchSpamAnalyzer |
Search functionality abuse, injection via search params |
TrackbackPingbackSpamAnalyzer |
Trackback/pingback spam, DDoS amplification |
MediaLibraryAbuseAnalyzer |
Media library abuse, upload directory scanning |
WpCliAbuseAnalyzer |
WP-CLI abuse, dangerous AJAX actions, object injection |
CoreFileModificationAnalyzer |
Core file modification via plugin/theme editors |
AjaxEndpointAbuseAnalyzer |
AJAX and admin-post endpoint abuse |
OpenRedirectAnalyzer |
Open redirect attacks, JavaScript protocol handlers |
PasswordResetAbuseAnalyzer |
Password reset abuse, Host header injection |
SessionHijackingAnalyzer |
Session hijacking, cookie manipulation, session fixation |
UnicodeEncodingAttackAnalyzer |
Unicode/encoding bypass attacks, overlong UTF-8, null bytes |
RateLimitBypassAnalyzer |
Rate limit bypass via header spoofing, proxy chain manipulation |
JavaScriptInjectionAnalyzer |
JS injection, DOM-based XSS, prototype pollution |
Each detection produces a DetectionResult with category IDs (mapped to reportedip.de categories), severity score (1-100), and a human-readable comment.
Access the admin panel at your configured path (default: /_hp_admin).
- Dashboard — Attack statistics, activity chart, top IPs, top categories, cron status, system info
- Logs — Filterable attack log with search, IP filter, category filter, status filter
- Whitelist — Add/remove IPs and CIDR ranges from the whitelist
- Content — Manage AI-generated blog posts for the fake CMS
- Visitors — Bot/visitor classification log with type breakdown
- Webhooks — Manage external report targets (see Webhooks)
- Updates — Self-update via GitHub Releases with backups and rollback
- Bcrypt password authentication with brute-force lockout (5 attempts, 15-minute window)
- CSRF protection on all state-changing actions (including logout)
- Session IP binding to prevent session hijacking
- Security headers:
X-Frame-Options: DENY,Content-Security-Policy,X-Content-Type-Options: nosniff,Referrer-Policy,Permissions-Policy,Cache-Control: no-store SameSite=StrictandHttpOnlysession cookies
Besides the automatic reporting to reportedip.de, the honeypot can forward every detection to your own systems (SIEM, log management, chat alerts, custom dashboards) or third-party abuse databases like AbuseIPDB in real time. Webhooks are managed in the admin panel under Webhooks.
- Each webhook is an HTTP(S) endpoint that receives a request for every matching detection
- HTTP method (
POST/PUT/PATCH/GET), custom headers (e.g. API keys), and body format are configurable per endpoint - Delivery happens after the trap response has been sent to the attacker, so webhooks never slow down the honeypot
- Filters: restrict a webhook to specific category IDs and/or analyzer names. Empty filters = all detections. When both filters are set, the webhook triggers when either one matches
- Test button: every webhook can be verified from the admin panel with a test delivery (
X-ReportedIP-Event: test). Test deliveries use the loopback IP127.0.0.1, so abuse databases reject them instead of storing a real report - Delivery status, timestamp, and consecutive failure count are shown per webhook
- Quick presets in the admin form fill in URL, method, headers, and body template for AbuseIPDB, Slack, Discord, and generic JSON — just add your API key afterwards
| Format | Description |
|---|---|
json |
Full structured detection payload (see below) — default |
form |
Flat key/value fields as application/x-www-form-urlencoded |
custom |
Free-form body template with placeholders — adapts to any third-party API |
Available in custom body templates and in the endpoint URL (for GET-style APIs):
{{ip}}, {{categories}}, {{abuseipdb_categories}}, {{comment}}, {{severity}}, {{analyzers}}, {{uri}}, {{method}}, {{user_agent}}, {{host}}, {{timestamp}}, {{version}}, {{event}}
Each placeholder also exists as {{name_url}} (URL-encoded) and {{name_json}} (JSON-escaped). Multiple detections in one request are aggregated: categories are merged, severity is the maximum, comments are joined.
{{abuseipdb_categories}} automatically translates reportedip.de category IDs to AbuseIPDB category IDs (IDs 1–23 are identical on both platforms; the CMS-specific IDs 24–58 map to their closest equivalent, e.g. WP Login Brute Force → Brute-Force + Web App Attack).
Use the AbuseIPDB preset in the admin form, or configure manually:
| Field | Value |
|---|---|
| URL | https://api.abuseipdb.com/api/v2/report |
| Method | POST |
| Body format | custom |
| Headers | Key: YOUR_ABUSEIPDB_API_KEYAccept: application/json |
| Body template | ip={{ip_url}}&categories={{abuseipdb_categories}}&comment={{comment_url}} |
Note: AbuseIPDB accepts a report for the same IP only once every 15 minutes per reporter. The honeypot's built-in category cooldown (15 minutes by default) keeps duplicate submissions to a minimum; rejected duplicates show up as a delivery failure (HTTP 429) in the webhook status.
| Header | Value |
|---|---|
Content-Type |
application/json (format json), application/x-www-form-urlencoded (format form); for custom it is derived from the rendered body and can be overridden via custom headers |
User-Agent |
reportedip-honeypot-server/<version> |
X-ReportedIP-Event |
detection or test |
X-ReportedIP-Signature |
sha256=<HMAC> — only when a secret is configured |
Custom headers configured on the webhook override the defaults (e.g. a custom Content-Type).
{
"event": "detection",
"generated_at": "2026-06-12T14:00:00+00:00",
"honeypot": {
"name": "reportedip-honeypot-server",
"version": "1.3.1",
"host": "your-honeypot.example.com",
"profile": "wordpress"
},
"request": {
"ip": "203.0.113.50",
"method": "POST",
"uri": "/wp-login.php",
"user_agent": "sqlmap/1.7"
},
"detections": [
{
"analyzer": "SqlInjection",
"categories": [16, 45],
"category_names": ["SQL Injection", "Code Injection"],
"comment": "SQL injection attempt detected: ...",
"severity": 85
}
]
}When a secret is configured, verify the integrity of each delivery by computing the HMAC over the raw request body:
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret);
$valid = hash_equals($expected, $_SERVER['HTTP_X_REPORTEDIP_SIGNATURE'] ?? '');php cli.php stats # Show attack statistics
php cli.php process-queue # Send pending reports to API
php cli.php cleanup [--days=90] # Remove old log entries
php cli.php whitelist-add <ip> [desc] # Add IP/CIDR to whitelist
php cli.php whitelist-remove <ip> # Remove IP from whitelist
php cli.php whitelist-list # Show all whitelist entries
php cli.php test-api # Test API connectivityreportedip-honeypot-server/
├── public/index.php # Single entry point (document root)
├── cli.php # CLI tool for cron and management
├── config/
│ ├── config.example.php # Configuration template
│ ├── nginx.conf.example # Nginx config template
│ └── apache.htaccess.example # Apache config template
├── src/
│ ├── Core/ # App, Request, Response, Router, Config, Cache
│ ├── Detection/ # DetectionPipeline + 36 Analyzers
│ ├── Network/ # IpResolver, CidrMatcher
│ ├── Persistence/ # Database, Logger, VisitorLogger, Whitelist
│ ├── Api/ # ReportClient, ReportQueue
│ ├── Profile/ # CmsProfile, WordPress/Drupal/Joomla profiles
│ ├── Content/ # ContentGenerator, ContentRepository
│ ├── Admin/ # AdminController, AdminAuth, Dashboard, LogViewer
│ └── Trap/ # 13 trap handlers (Login, Admin, Home, Content, ...)
├── templates/
│ ├── admin/ # Admin panel templates (layout, dashboard, logs, ...)
│ ├── wordpress/ # WordPress trap templates
│ ├── drupal/ # Drupal trap templates
│ └── joomla/ # Joomla trap templates
├── tests/ # 311+ tests (unit + analyzer + integration)
├── docker/ # Dockerfile, docker-compose.yml, nginx/php-fpm configs
└── data/ # SQLite DB, cache, logs (gitignored)
The project uses a custom lightweight test framework (no PHPUnit dependency):
php tests/run-tests.php # Run all tests
php tests/run-tests.php --integration # Include integration tests
php tests/run-tests.php --filter Config # Filter by class name
php tests/run-tests.php --verbose # Show timing per test- All HTTP requests hit
public/index.php IpResolverdetermines the real client IP (Cloudflare/proxy-aware)Routerchecks if the request targets the admin panel- For honeypot requests:
Whitelistcheck, thenDetectionPipelineruns all 36 analyzers - Detections are logged to SQLite with
sent=0(queued for reporting) Routermatches the path against the active CMS profile to select a trap- The trap renders a convincing CMS-like response (login page, blog post, RSS feed, etc.)
- After the response is sent, web cron processes a micro-batch of queued reports to the reportedip.de API (or a cron job does it in cron mode)
Contributions are welcome! Please read CONTRIBUTING.md for guidelines.
Patrick Schlesinger
- Website: reportedip.de
- Email: 1@reportedip.de
This project is licensed under the Business Source License 1.1 (BSL 1.1).
- Production use is permitted (including by companies), EXCEPT offering this software as a hosted/managed service to third parties or selling it as a commercial product.
- On 2030-03-01, the license automatically converts to Apache License 2.0.
See LICENSE for the full text.
By using this software, you agree to the terms in DISCLAIMER.md.
- No Warranty: This software is provided "AS IS" without warranty of any kind.
- Legal Compliance: You are solely responsible for compliance with all applicable laws in your jurisdiction regarding honeypot operation and data collection.
- Data Privacy: You are the data controller for any personal data (IP addresses) collected by this software.
- Risk: Running a honeypot involves inherent security risks. The authors are not liable for any damages.
Bitte beachten Sie den ausführlichen Haftungsausschluss in DISCLAIMER.md.