SimpleHTTPServer: A Rule-Based Mock Server for Security Testing
Hook
While Python's SimpleHTTPServer has served files for decades, it can't fake an SMTP server, intercept authentication attempts, or simulate vulnerable endpoints—which is exactly what security researchers need.
Context
Anyone who's done web development has typed python -m http.server to quickly serve files from a directory. It's the Swiss Army knife of local development—simple, reliable, and ubiquitous. But security researchers and penetration testers face a different challenge: they need to simulate servers, not just serve files. During a security assessment, you might need to host a malicious payload, capture authentication credentials, simulate a vulnerable service, or test how an application behaves against different server responses. Python's SimpleHTTPServer can't help you fake an SMTP server that logs credentials, create a mock OAuth endpoint that returns specific tokens, or serve files over HTTPS with basic auth enabled.
ProjectDiscovery—the team behind Nuclei and other offensive security tools—built SimpleHTTPServer to bridge this gap. Written in Go, it's designed for security testing workflows where you need more than static file serving. Beyond the standard HTTP file server features, it introduces a rule-based TCP server that uses YAML templates to match incoming requests and return custom responses. This architecture lets you simulate almost any text-based protocol: HTTP endpoints with specific responses, SMTP servers that log authentication attempts, or custom TCP services that respond to particular patterns. Combined with zero-config TLS, basic authentication, file uploads, and CORS support, it's optimized for the messy realities of penetration testing where you need to spin up mock services quickly.
Technical Insight
SimpleHTTPServer's architecture separates into two distinct modes: HTTP file serving and rule-based TCP serving. The HTTP mode wraps Go's net/http with security-focused middleware, while the TCP mode implements a pattern-matching engine that evaluates YAML rules against incoming data.
The HTTP server is straightforward but feature-rich. Launch it with simplehttpserver -path ./files -port 8080, and it serves files with directory listing, range request support, and request logging. Add -https and it generates a self-signed certificate on the fly using Go's crypto/tls. The -upload flag transforms it into a file receiver with configurable size limits via -max-size. Basic authentication (-basic-auth user:pass) and CORS headers (-cors) round out the security testing features. For sandboxed file serving that prevents directory traversal, -sandbox mode restricts access to the specified path.
The TCP rule engine is where things get interesting. Create a YAML file defining matchers and responses:
rules:
- match:
type: literal
value: "EHLO"
response: |
250-smtp.example.com
250-STARTTLS
250 AUTH PLAIN LOGIN
- match:
type: regex
value: "AUTH PLAIN (.+)"
response: |
235 Authentication successful
log: true
- match:
type: regex
value: "GET /api/v1/users/(\\d+)"
response: |
HTTP/1.1 200 OK
Content-Type: application/json
{"id": "{{.matches.1}}", "status": "active"}
Launch this with simplehttpserver -tcp -port 2525 -rules smtp.yaml -https and you've got a mock SMTP server over TLS that logs authentication attempts. The rule engine processes incoming data line-by-line, evaluating each matcher in order. Literal matches use string comparison for performance, while regex matches use Go's regexp package. When a match succeeds, the engine returns the templated response, with captured groups accessible via {{.matches.N}}.
Under the hood, the TCP server uses net.Listen and spawns a goroutine for each connection. Each handler reads from the connection using bufio.Scanner, tests incoming lines against compiled matchers, and writes responses back through the connection. This design is simple but effective for text-based protocols where requests and responses are line-delimited.
The TLS implementation deserves attention. When you enable -https without providing certificates, the tool generates a self-signed certificate valid for localhost and common internal hostnames. This happens via Go's crypto/x509 and crypto/rsa packages, creating a 2048-bit RSA key and a certificate valid for one year. For custom certificates, -cert and -key flags accept PEM-encoded files. The TLS configuration defaults to TLS 1.2+ with secure cipher suites, adequate for testing scenarios though not hardened for production.
Authentication integrates at the middleware level for HTTP mode and at the connection level for TCP mode. The -basic-auth flag accepts colon-separated credentials that get validated against the Authorization header. For TCP, authentication can be simulated through rules—perfect for testing credential stuffing or authentication bypass scenarios. The -log-file flag captures all requests to disk, invaluable when testing how applications behave or debugging integration issues.
One particularly clever feature is the -ipv6 flag, which binds to [::]:port instead of 0.0.0.0:port. Combined with the rule engine, this makes it easy to test IPv6-specific behavior or simulate dual-stack environments. The -interface flag lets you bind to specific network interfaces, useful in multi-homed hosts or Docker containers where you need precise control over which interface serves traffic.
Gotcha
SimpleHTTPServer isn't designed for production use, and that shows in several areas. The TCP rule engine evaluates patterns sequentially—if you have dozens of rules, performance degrades as each incoming line tests against all matchers until one succeeds. There's no rule optimization, caching, or compilation beyond Go's regex cache. For complex protocols with hundreds of possible commands, you'll hit performance walls. The tool also lacks stateful protocol support: each line is evaluated independently, so simulating protocols that require multi-step handshakes (like a full TLS negotiation or stateful FTP) becomes awkward. You can fake it with carefully ordered rules, but the abstraction leaks quickly.
The documentation is minimal beyond the README's basic examples. Advanced rule templating features, like accessing connection metadata or maintaining per-connection state, aren't documented—you'll need to read the source code. Error handling is basic: malformed YAML causes startup failures without helpful validation messages, and regex compilation errors don't indicate which rule failed. The auto-generated TLS certificates work for most scenarios but can trigger warnings in some tools that perform strict certificate validation. For security testing that requires trusted certificates, you'll need to use the -cert and -key flags with properly signed certificates.
File upload security is another consideration. While -max-size limits individual file uploads, there's no rate limiting, quota management, or protection against directory traversal attacks in the upload path. The -sandbox flag helps for serving files, but upload handling is more permissive. This is fine for controlled testing environments but don't expose it to untrusted networks. The tool also doesn't handle binary protocols well—the line-based scanner in TCP mode works for text protocols like HTTP, SMTP, or IMAP, but binary protocols require different parsing strategies that aren't supported.
Verdict
Use if: You're conducting security assessments and need to quickly mock services, serve payloads over HTTPS, capture authentication attempts, or test how applications respond to specific server behaviors. It's particularly valuable when you need zero-config TLS, want to simulate multiple protocols without writing code, or require a file server with authentication and upload capabilities. The rule engine shines for testing text-based protocols and creating honeypot services that log interesting traffic. Skip if: You need a production-ready web server (use Caddy or nginx), require complex stateful protocol simulation (build a custom service or use specialized tools like mitmproxy), or want to serve files long-term with proper security hardening. Also skip it for binary protocol simulation or scenarios requiring high performance under load—the sequential rule matching and per-connection goroutines work for testing but won't scale. Think of SimpleHTTPServer as a security tester's Swiss Army knife: powerful and versatile for short-lived mock services, but not a replacement for purpose-built infrastructure.