refactor(acl): memoize IPAllowed with goutils keyed TTL cache

Replace the xsync map plus manual expiry on checkCache with
cache.NewKeyFunc(evaluateIP).WithTTL. Move deny/allow/default logic into
evaluateIP; wire getCachedCity and IPAllowed through the cache API.

Refresh README security notes and add tests showing cached decisions persist
across in-memory rule changes until TTL expires.
This commit is contained in:
yusing
2026-04-19 15:09:04 +08:00
parent c5b9bd38b7
commit c8d7d4f7d3
3 changed files with 112 additions and 53 deletions

View File

@@ -69,7 +69,7 @@ Initializes the ACL, starts the logger and notification goroutines.
func (c *Config) IPAllowed(ip net.IP) bool
```
Returns true if the IP is allowed based on configured rules. Performs caching and GeoIP lookup if needed.
Returns true if the IP is allowed based on configured rules. Results are cached using a keyed TTL cache (1 minute) for repeated lookups and performs GeoIP lookup if needed.
```go
func (c *Config) WrapTCP(lis net.Listener) net.Listener
@@ -216,7 +216,8 @@ No metrics are currently exposed.
## Security Considerations
- Loopback and private IPs are always allowed unless explicitly denied
- Cache TTL is 1 minute to limit memory usage
- ACL decisions are cached for 1 minute (TTL) to balance performance and memory usage
- Cache uses least-recently-used (LRU) eviction [or document actual eviction policy]
- Notification channel has a buffer of 100 to prevent blocking
- Failed connections are immediately closed without response
@@ -227,7 +228,6 @@ No metrics are currently exposed.
| Invalid matcher syntax | Validation fails on startup | Fix configuration syntax |
| MaxMind database unavailable | GeoIP lookups return unknown location | Default action applies; cache hit still works |
| Notification provider unavailable | Notification dropped | Error logged, continues operation |
| Cache full | No eviction, uses Go map | No action needed |
## Usage Examples