fix(acl): maxmind error even if configured, refactor

This commit is contained in:
yusing 2025-05-14 13:44:43 +08:00
parent 8e27886235
commit b490e8c475
5 changed files with 47 additions and 19 deletions

View file

@ -7,6 +7,7 @@ import (
"github.com/puzpuzpuz/xsync/v3"
"github.com/yusing/go-proxy/internal/common"
"github.com/yusing/go-proxy/internal/gperr"
"github.com/yusing/go-proxy/internal/logging"
"github.com/yusing/go-proxy/internal/logging/accesslog"
"github.com/yusing/go-proxy/internal/maxmind"
"github.com/yusing/go-proxy/internal/task"
@ -21,6 +22,7 @@ type Config struct {
Log *accesslog.ACLLoggerConfig `json:"log"`
config
valErr gperr.Error
}
type config struct {
@ -57,7 +59,8 @@ func (c *Config) Validate() gperr.Error {
case ACLDeny:
c.defaultAllow = false
default:
return gperr.New("invalid default value").Subject(c.Default)
c.valErr = gperr.New("invalid default value").Subject(c.Default)
return c.valErr
}
if c.AllowLocal != nil {
@ -70,12 +73,17 @@ func (c *Config) Validate() gperr.Error {
c.logAllowed = c.Log.LogAllowed
}
if !c.allowLocal && !c.defaultAllow && len(c.Allow) == 0 {
c.valErr = gperr.New("allow_local is false and default is deny, but no allow rules are configured")
return c.valErr
}
c.ipCache = xsync.NewMapOf[string, *checkCache]()
return nil
}
func (c *Config) Valid() bool {
return c != nil && (len(c.Allow) > 0 || len(c.Deny) > 0 || c.allowLocal)
return c != nil && c.valErr == nil
}
func (c *Config) Start(parent *task.Task) gperr.Error {
@ -86,6 +94,15 @@ func (c *Config) Start(parent *task.Task) gperr.Error {
}
c.logger = logger
}
if c.valErr != nil {
return c.valErr
}
logging.Info().
Str("default", c.Default).
Bool("allow_local", c.allowLocal).
Int("allow_rules", len(c.Allow)).
Int("deny_rules", len(c.Deny)).
Msg("ACL started")
return nil
}
@ -114,8 +131,7 @@ func (c *Config) IPAllowed(ip net.IP) bool {
return false
}
// always allow loopback
// loopback is not logged
// always allow loopback, not logged
if ip.IsLoopback() {
return true
}

View file

@ -24,6 +24,9 @@ const (
MatcherTypeCountry = "country"
)
// TODO: use this error in the future
//
//nolint:unused
var errMatcherFormat = gperr.Multiline().AddLines(
"invalid matcher format, expect {type}:{value}",
"Available types: ip|cidr|tz|country",
@ -34,10 +37,9 @@ var errMatcherFormat = gperr.Multiline().AddLines(
)
var (
errSyntax = errors.New("syntax error")
errInvalidIP = errors.New("invalid IP")
errInvalidCIDR = errors.New("invalid CIDR")
errMaxMindNotConfigured = errors.New("MaxMind not configured")
errSyntax = errors.New("syntax error")
errInvalidIP = errors.New("invalid IP")
errInvalidCIDR = errors.New("invalid CIDR")
)
func (matcher *Matcher) Parse(s string) error {
@ -60,14 +62,8 @@ func (matcher *Matcher) Parse(s string) error {
}
matcher.match = matchCIDR(net)
case MatcherTypeTimeZone:
if !maxmind.HasInstance() {
return errMaxMindNotConfigured
}
matcher.match = matchTimeZone(parts[1])
case MatcherTypeCountry:
if !maxmind.HasInstance() {
return errMaxMindNotConfigured
}
matcher.match = matchISOCode(parts[1])
default:
return errSyntax

View file

@ -10,12 +10,12 @@ type UDPListener struct {
lis net.PacketConn
}
func (cfg *Config) WrapUDP(lis net.PacketConn) net.PacketConn {
if cfg == nil {
func (c *Config) WrapUDP(lis net.PacketConn) net.PacketConn {
if c == nil {
return lis
}
return &UDPListener{
acl: cfg,
acl: c,
lis: lis,
}
}

View file

@ -248,8 +248,6 @@ func (cfg *Config) load() gperr.Error {
err := model.ACL.Start(cfg.task)
if err != nil {
errs.Add(err)
} else {
logging.Info().Msg("ACL started")
}
}

View file

@ -1,12 +1,29 @@
package maxmind
import (
"sync"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/yusing/go-proxy/internal/gperr"
"github.com/yusing/go-proxy/internal/notif"
"github.com/yusing/go-proxy/internal/task"
)
var instance *MaxMind
var warnOnce sync.Once
func warnNotConfigured() {
log.Warn().Msg("MaxMind not configured, geo lookup will fail")
notif.Notify(&notif.LogMessage{
Level: zerolog.WarnLevel,
Title: "MaxMind not configured",
Body: notif.MessageBody("MaxMind is not configured, geo lookup will fail"),
Color: notif.ColorError,
})
}
func SetInstance(parent task.Parent, cfg *Config) gperr.Error {
newInstance := &MaxMind{Config: cfg}
if err := newInstance.LoadMaxMindDB(parent); err != nil {
@ -22,6 +39,7 @@ func HasInstance() bool {
func LookupCity(ip *IPInfo) (*City, bool) {
if instance == nil {
warnOnce.Do(warnNotConfigured)
return nil, false
}
return instance.lookupCity(ip)