Files
golib/static/doc.go
nabbar 43241f78ba [ file/progress ]
- ADD flag to register temp file creation
    - ADD function to check flag is temp

[ static ]
    - FIX bugs & race detection
    - UPDATE code: refactor & optimize code, improve security &
      preformances
    - ADD Path Security: add options & code to improve security
    - ADD Rate Limiting: add option to limit capabilities of burst request
    - ADD HTTP Security Headers: add option to customize header, improve
      security & allow cache crontol
    - ADD Suspicious Access Detection: add option to identify & log
      suspicious request
    - ADD Security Backend Integration: add option to plug WAF/IDF/EDR
      backend (with CEF Format or not)
    - ADD documentation: add enhanced README and TESTING guidelines
    - ADD tests: complete test suites with benchmarks, concurrency, and edge cases
2025-11-23 19:30:27 +01:00

372 lines
13 KiB
Go

/*
* MIT License
*
* Copyright (c) 2022 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
/*
Package static provides a secure, high-performance static file server for Gin framework
with embedded filesystem support, comprehensive security features, and WAF/IDS/EDR integration.
# Overview
The static package is designed to serve files from Go's embed.FS with enterprise-grade
security features including:
- Path traversal protection with configurable rules
- IP-based rate limiting (DoS/scraping prevention)
- Suspicious access pattern detection
- MIME type validation and filtering
- HTTP caching (ETag, Cache-Control)
- Integration with external security systems (WAF/IDS/EDR)
All operations are thread-safe using atomic operations without mutexes for maximum
performance and scalability.
# Architecture
The package follows a layered architecture with clear separation of concerns:
┌─────────────────────────────────────────────────────────────┐
│ Gin HTTP Request │
└────────────────────────┬────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Static Handler (Get) │
│ ┌────────────┬───────────────┬─────────────┬─────────────┐ │
│ │Rate Limit │Path Security │Headers │Suspicious │ │
│ │Check │Validation │Control │Detection │ │
│ └────────────┴───────────────┴─────────────┴─────────────┘ │
└────────────────────────┬────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ File Operations (embed.FS) │
│ ┌────────────┬───────────────┬─────────────┬─────────────┐ │
│ │Has() │Find() │Info() │Temp() │ │
│ └────────────┴───────────────┴─────────────┴─────────────┘ │
└────────────────────────┬────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ HTTP Response (SendFile) │
│ ┌────────────┬───────────────┬─────────────┬─────────────┐ │
│ │ETag │Cache-Control │Content-Type │Disposition │ │
│ └────────────┴───────────────┴─────────────┴─────────────┘ │
└─────────────────────────────────────────────────────────────┘
# Request Flow
A typical request flows through multiple security layers:
HTTP Request
[Rate Limit Check]
├─── Rate exceeded? ──► 429 Too Many Requests
[Path Security Validation]
├─── Path traversal? ──► 403 Forbidden
├─── Dot file? ────────► 403 Forbidden
├─── Blocked pattern? ─► 403 Forbidden
[Suspicious Access Detection]
├─── Log suspicious patterns
[File Exists Check]
├─── Not found? ───────► 404 Not Found
[ETag Validation]
├─── Cached? ──────────► 304 Not Modified
[MIME Type Validation]
├─── Denied type? ─────► 403 Forbidden
[Send File with Headers]
200 OK with caching headers
# Security Features
The package implements defense-in-depth with multiple security layers:
## 1. Path Traversal Protection
Protects against directory traversal attacks:
- Detects ".." sequences before path normalization
- Validates against null byte injection
- Enforces maximum path depth
- Blocks access to dot files (.env, .git, etc.)
- Pattern-based blocking (configurable)
Example:
handler.SetPathSecurity(static.PathSecurityConfig{
Enabled: true,
AllowDotFiles: false,
MaxPathDepth: 10,
BlockedPatterns: []string{".git", ".svn", "node_modules"},
})
## 2. Rate Limiting
IP-based rate limiting tracks unique file paths per IP:
- Configurable request limits and time windows
- IP whitelisting support
- Trusted proxy detection
- Automatic cache cleanup
- Thread-safe atomic operations
Example:
handler.SetRateLimit(static.RateLimitConfig{
Enabled: true,
MaxRequests: 100,
Window: time.Minute,
CleanupInterval: 5 * time.Minute,
WhitelistIPs: []string{"127.0.0.1"},
})
## 3. Suspicious Access Detection
Monitors and logs suspicious file access patterns:
- Configuration file access (.env, config.php)
- Backup file enumeration (.bak, .old)
- Admin panel scanning (wp-admin, phpmyadmin)
- Database file requests (.sql, .db)
- Logs both successful and failed attempts
## 4. MIME Type Validation
Controls which file types can be served:
- MIME type detection by file extension
- Whitelist/blacklist configuration
- Custom MIME type mapping
- Blocks dangerous file types (.exe, .sh)
## 5. HTTP Caching
Optimizes bandwidth and performance:
- ETag generation and validation
- Cache-Control headers (public/private)
- 304 Not Modified responses
- Configurable cache duration
- Last-Modified support
# Security Backend Integration
The package can report security events to external systems:
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Static │ │ Security │ │ External │
│ Handler │────────►│ Event │────────►│ System │
│ │ │ Processor │ │ (WAF/IDS) │
└──────────────┘ └──────────────┘ └──────────────┘
├─────► Webhook (JSON/CEF)
└─────► Go Callbacks
Supported integrations:
- Webhooks with custom headers (Authorization, etc.)
- Common Event Format (CEF) for SIEM systems
- Go callbacks for custom processing
- Batch processing for efficiency
- Configurable severity filtering
# Thread Safety
All data structures use atomic operations without mutexes:
Configuration: libatm.Value[*Config] (atomic.Value wrapper)
IP Tracking: libatm.MapTyped[string, *T] (atomic map)
Counters: atomic.Int64, atomic.Uint64 (standard atomic)
Event Batch: atomic operations only (no mutex)
This design ensures:
- Zero contention under high load
- Predictable performance
- No deadlock risk
- Lock-free scalability
# Performance Considerations
The package is optimized for high-performance scenarios:
1. Atomic Operations: All state managed without mutexes
2. Lazy Initialization: Security features activated only when configured
3. Batch Processing: Multiple events sent together to reduce overhead
4. HTTP Caching: ETag reduces bandwidth and CPU usage
5. Embedded FS: No disk I/O for file access
Typical performance characteristics:
- Request handling: <1ms per request (cached)
- Rate limit check: ~100ns (atomic read)
- Path validation: <10μs (string operations)
- ETag generation: <1μs (hash calculation)
# Dependencies
This package requires:
- github.com/gin-gonic/gin - HTTP framework
- github.com/nabbar/golib/atomic - Thread-safe atomic wrappers
- github.com/nabbar/golib/context - Context-aware configuration
- github.com/nabbar/golib/logger - Logging interface
- github.com/nabbar/golib/errors - Error management
- github.com/nabbar/golib/router - Router helpers
- github.com/nabbar/golib/monitor - Health monitoring
# Example Usage
Basic static file server:
package main
import (
"context"
"embed"
"github.com/gin-gonic/gin"
"github.com/nabbar/golib/static"
)
//go:embed assets/*
var content embed.FS
func main() {
handler := static.New(context.Background(), content, "assets")
router := gin.Default()
handler.RegisterRouter("/static", router.GET)
router.Run(":8080")
}
With security features:
handler := static.New(context.Background(), content, "assets")
// Path security
handler.SetPathSecurity(static.DefaultPathSecurityConfig())
// Rate limiting
handler.SetRateLimit(static.RateLimitConfig{
Enabled: true,
MaxRequests: 100,
Window: time.Minute,
})
// HTTP caching
handler.SetHeaders(static.DefaultHeadersConfig())
// Security backend
handler.SetSecurityBackend(static.SecurityConfig{
Enabled: true,
WebhookURL: "https://waf.example.com/events",
})
See example_test.go for more comprehensive examples.
# Best Practices
1. Always enable path security in production:
handler.SetPathSecurity(static.DefaultPathSecurityConfig())
2. Configure rate limiting appropriate to your traffic:
- API serving: 100-1000 requests/minute
- Public websites: 1000-10000 requests/minute
3. Use HTTP caching to reduce server load:
handler.SetHeaders(static.DefaultHeadersConfig())
4. Monitor security events in production:
handler.SetSecurityBackend() with appropriate webhooks
5. Whitelist known IPs (monitoring, health checks):
config.WhitelistIPs = []string{"monitoring-ip"}
6. Use custom MIME types for modern formats:
config.CustomMimeTypes = map[string]string{".wasm": "application/wasm"}
7. Enable suspicious access logging:
handler.SetSuspicious(static.DefaultSuspiciousConfig())
# Troubleshooting
Common issues and solutions:
403 Forbidden:
- Check path security configuration
- Verify file is not a dot file (if AllowDotFiles = false)
- Check blocked patterns
429 Too Many Requests:
- Increase rate limit (MaxRequests)
- Add IP to whitelist
- Increase time window
404 Not Found:
- Verify file exists in embed.FS
- Check embedRootDir parameter in New()
- Use handler.Has() to verify file presence
# Testing
The package includes comprehensive tests:
- 229+ test cases
- Thread safety verified with race detector
- Concurrency stress tests
- Benchmark tests
- Security scenario tests
Run tests:
go test -v
go test -race (with race detector)
go test -bench . (benchmarks)
# License
MIT License - Copyright (c) 2022 Nicolas JUHEL
*/
package static