Skip to main content

Overview

The honeypot middleware monitors requests to commonly attacked paths (like /admin, /.env, /wp-admin) and blocks IPs that access them. It acts as a trap for attackers and bots scanning for vulnerabilities. Use it when you need:
  • Detect automated vulnerability scanners
  • Block malicious IPs proactively
  • Reduce attack surface
  • Log attack attempts

Installation

import "github.com/go-mizu/mizu/middlewares/honeypot"

Quick Start

app := mizu.New()

// Use default honeypot paths
app.Use(honeypot.New())

Configuration

Options

OptionTypeDefaultDescription
Paths[]stringCommon attack pathsPaths to monitor
BlockDurationtime.Duration1hHow long to block detected IPs
Responsefunc(*mizu.Ctx) error404 Not FoundResponse for honeypot requests
OnTrapfunc(ip, path string)-Callback when trap triggered

Default Paths

var defaultPaths = []string{
    "/admin", "/administrator", "/wp-admin", "/wp-login.php",
    "/phpmyadmin", "/pma", "/mysql", "/sql",
    "/.env", "/.git", "/.svn", "/config.php",
    "/backup", "/backup.sql", "/dump.sql",
    "/shell", "/cmd", "/exec", "/eval",
    "/xmlrpc.php", "/wp-config.php",
    "/server-status", "/server-info",
}

Examples

Default Configuration

// Monitor default attack paths
app.Use(honeypot.New())

Custom Paths

app.Use(honeypot.Paths(
    "/secret",
    "/internal",
    "/debug",
    "/test.php",
))

Admin Path Honeypot

// Specifically target admin path attackers
app.Use(honeypot.AdminPaths())

Config File Honeypot

// Target config file scanners
app.Use(honeypot.ConfigPaths())

Database Path Honeypot

// Target database scanners
app.Use(honeypot.DatabasePaths())

With Logging

app.Use(honeypot.WithOptions(honeypot.Options{
    OnTrap: func(ip, path string) {
        log.Printf("HONEYPOT: IP %s triggered trap at %s", ip, path)

        // Send to security monitoring
        alertSecurity(ip, path)
    },
}))

Custom Block Duration

app.Use(honeypot.WithOptions(honeypot.Options{
    BlockDuration: 24 * time.Hour, // Block for 24 hours
}))

Custom Response

app.Use(honeypot.WithOptions(honeypot.Options{
    Response: func(c *mizu.Ctx) error {
        // Slow down attackers with a delay
        time.Sleep(5 * time.Second)
        return c.Text(404, "Not Found")
    },
}))

Form Field Honeypot

Detect bots that fill hidden form fields:
// Add to forms that might be targeted by bots
app.Post("/contact", contactHandler, honeypot.Form("website"))
<!-- Hidden field that humans won't fill -->
<form method="POST" action="/contact">
    <input type="text" name="website" style="display:none">
    <input type="text" name="email">
    <textarea name="message"></textarea>
    <button type="submit">Send</button>
</form>

Comprehensive Protection

app.Use(honeypot.WithOptions(honeypot.Options{
    Paths: append(
        honeypot.DefaultPaths,
        "/api/internal",
        "/debug/vars",
        "/metrics", // If not used
    ),
    BlockDuration: 12 * time.Hour,
    OnTrap: func(ip, path string) {
        // Log to file
        securityLog.Printf("Blocked %s accessing %s", ip, path)

        // Store in database for analysis
        db.RecordAttackAttempt(ip, path, time.Now())

        // Alert if too many attempts
        if count := getAttemptCount(ip); count > 10 {
            alertSecurityTeam(ip)
        }
    },
}))

Combined with IP Filter

// First, check honeypot
app.Use(honeypot.New())

// Then, additional IP filtering
app.Use(ipfilter.Deny(loadBlockedIPs()...))

API Reference

Functions

// New creates honeypot with default options
func New() mizu.Middleware

// WithOptions creates honeypot with custom options
func WithOptions(opts Options) mizu.Middleware

// Paths creates honeypot for specific paths
func Paths(paths ...string) mizu.Middleware

// AdminPaths creates honeypot for admin paths
func AdminPaths() mizu.Middleware

// ConfigPaths creates honeypot for config file paths
func ConfigPaths() mizu.Middleware

// DatabasePaths creates honeypot for database paths
func DatabasePaths() mizu.Middleware

// Form creates honeypot for form field detection
func Form(field string) mizu.Middleware

How It Works

  1. Request arrives at a honeypot path
  2. IP recorded in block list with expiration
  3. Callback triggered (if configured) for logging/alerting
  4. Fake response returned to attacker
  5. Future requests from that IP are blocked
Attacker → /wp-admin → IP Blocked → 403 Forbidden
                     ↓
                     OnTrap callback
                     ↓
                     Log/Alert

Technical Details

Architecture

The honeypot middleware uses an in-memory block list with automatic cleanup to track and block malicious IPs:
type blockList struct {
    mu       sync.RWMutex
    ips      map[string]time.Time
    duration time.Duration
}

Request Flow

  1. IP Extraction - Client IP is extracted with proxy support (X-Forwarded-For, X-Real-IP)
  2. Block Check - If IP is in block list and not expired, return 403 Forbidden
  3. Path Matching - Current path is checked against honeypot path map (O(1) lookup)
  4. Trap Trigger - If path matches:
    • IP is added to block list with expiration time
    • OnTrap callback is invoked (if configured)
    • Custom/default response is returned
  5. Pass Through - If no match, request continues to next handler

Implementation Details

  • Concurrent Access - Block list uses sync.RWMutex for thread-safe operations
  • Automatic Cleanup - Background goroutine runs every 10 minutes to remove expired entries
  • Path Lookup - Paths stored in map[string]bool for O(1) lookup performance
  • IP Detection Priority:
    1. X-Forwarded-For header
    2. X-Real-IP header
    3. Request.RemoteAddr

Memory Management

  • Block list grows with unique trapped IPs
  • Automatic cleanup prevents unbounded growth
  • Each entry: IP string + time.Time (approximately 24-32 bytes)
  • Recommended for moderate traffic; for high-traffic consider external storage

Form Honeypot Implementation

Form honeypots use a simpler stateless approach:
  • Check if hidden field contains any value
  • No IP blocking or state management
  • Returns 400 Bad Request immediately if filled

Security Considerations

  1. False Positives - Legitimate users might accidentally hit honeypot paths
  2. IP Rotation - Attackers may rotate IPs
  3. Proxy Detection - Consider X-Forwarded-For for accurate blocking
  4. Log Analysis - Monitor trapped IPs for patterns

Best Practices

  • Choose honeypot paths that legitimate users won’t access
  • Set appropriate block duration based on attack patterns
  • Log all triggered traps for security analysis
  • Combine with other security measures
  • Don’t use paths that might be legitimately requested

Testing

The honeypot middleware includes comprehensive test coverage for all functionality:
Test CaseDescriptionExpected Behavior
TestNew - normal pathRequest to non-honeypot pathReturns 200 OK, request passes through
TestNew - honeypot pathRequest to default honeypot path (/admin)Returns 404 Not Found, IP blocked
TestWithOptions_CustomPaths - custom trap pathRequest to custom honeypot pathReturns 404 Not Found for custom paths
TestWithOptions_CustomPaths - default path not trappedRequest to default path when custom paths setPasses through (default paths not active)
TestWithOptions_OnTrapHoneypot triggered with OnTrap callbackCallback invoked with IP and path
TestWithOptions_CustomResponseHoneypot with custom response functionReturns custom status (418 Teapot) and JSON
TestBlockedIP - first requestInitial request to honeypot pathReturns 404, IP added to block list
TestBlockedIP - subsequent requestNormal request from blocked IPReturns 403 Forbidden
TestPathsCustom paths using Paths() functionCustom paths trigger honeypot
TestAdminPathsAdminPaths() preset pathsAdmin-related paths trigger honeypot
TestConfigPathsConfigPaths() preset pathsConfig file paths (/.env) trigger honeypot
TestDatabasePathsDatabasePaths() preset pathsDatabase paths (/phpmyadmin) trigger honeypot
TestForm - empty honeypot fieldForm submission with empty hidden fieldReturns 200 OK, request passes
TestForm - filled honeypot fieldForm submission with filled hidden fieldReturns 400 Bad Request, blocks bot

Running Tests

# Run all honeypot tests
go test -v ./middlewares/honeypot

# Run with coverage
go test -cover ./middlewares/honeypot

# Run specific test
go test -v -run TestBlockedIP ./middlewares/honeypot