lolly/internal/lua/ip_guard_test.go
xfy 179090fa34 fix(security): 修复 2 个 CRITICAL + 6 个 HIGH 安全与代码质量问题
安全修复:
- ConnLimiter Acquire() TOCTOU 竞态: atomic.AddInt64 替代 loadInt64+addInt64
- Cache Purge token 时序侧信道: 改用 subtle.ConstantTimeCompare
- Lua Cosocket SSRF: 新增 ip_guard 两层 IP 检查(字面量+解析后),拒绝私有/回环地址
- X-Accel-Redirect 路径遍历: urlpath.Clean + 前缀拒绝(/internal/ /admin/)
- CRLF 注入: containsCRLF 校验变量展开后的 header 值,logging.Warn 可观测
- Proxy URI 注入: bytes.ContainsAny 检查 path 中的 @\r\n 危险字符

代码质量:
- disk_cache.go Set() 7 处静默 return 改为 logging.Error 日志记录
- config.go 从 2392 行拆分为 9 个按域文件(config/server/proxy/security/ssl/cache/performance/monitoring/variable)

验证: go build + vet + golangci-lint(0 issues) + test(83.2% 无回归) + race detector 全部通过

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-28 10:13:47 +08:00

52 lines
1.5 KiB
Go

package lua
import (
"net"
"testing"
)
func TestIsRestrictedIP(t *testing.T) {
tests := []struct {
name string
ip net.IP
blocked bool
}{
// IPv4 回环
{"IPv4 loopback", net.ParseIP("127.0.0.1"), true},
{"IPv4 loopback alt", net.ParseIP("127.0.1.1"), true},
// IPv4 私有
{"IPv4 private 10.x", net.ParseIP("10.0.0.1"), true},
{"IPv4 private 172.16.x", net.ParseIP("172.16.0.1"), true},
{"IPv4 private 192.168.x", net.ParseIP("192.168.0.1"), true},
// IPv4 链路本地
{"IPv4 link-local", net.ParseIP("169.254.1.1"), true},
// IPv4 未指定
{"IPv4 unspecified", net.ParseIP("0.0.0.0"), true},
// IPv4 公网
{"IPv4 public", net.ParseIP("8.8.8.8"), false},
{"IPv4 public 2", net.ParseIP("1.1.1.1"), false},
// IPv6 回环
{"IPv6 loopback", net.ParseIP("::1"), true},
// IPv6 链路本地
{"IPv6 link-local", net.ParseIP("fe80::1"), true},
// IPv6 链路本地多播(应被拦截)
{"IPv6 link-local multicast", net.ParseIP("ff02::1"), true},
// IPv6 公网
{"IPv6 public", net.ParseIP("2001:4860:4860::8888"), false},
// IPv4-mapped IPv6
{"IPv4-mapped IPv6 loopback", net.ParseIP("::ffff:127.0.0.1"), true},
{"IPv4-mapped IPv6 private", net.ParseIP("::ffff:10.0.0.1"), true},
// nil IP
{"nil IP", net.IP{}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := isRestrictedIP(tt.ip)
if result != tt.blocked {
t.Errorf("isRestrictedIP(%v) = %v, want %v", tt.ip, result, tt.blocked)
}
})
}
}