143438a30e
Introduces WhitelistedAuthenticator that wraps an auth.Authenticator to skip authentication when the client IP matches configured CIDR ranges or exact IPs. The wrapping happens at service-parse time, transparently covering all handler types (HTTP, SOCKS4/5, relay, http2, SSH). Usage: gost -L 'user:pass@:5999?skipauth=192.168.0.0/24,172.22.22.22/32'
62 lines
1.7 KiB
Go
62 lines
1.7 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"strings"
|
|
|
|
"github.com/go-gost/core/auth"
|
|
xctx "github.com/go-gost/x/ctx"
|
|
"github.com/go-gost/x/internal/matcher"
|
|
)
|
|
|
|
// whitelistedAuthenticator wraps an Authenticator to skip authentication
|
|
// for client IPs matching the configured whitelist patterns.
|
|
type whitelistedAuthenticator struct {
|
|
auther auth.Authenticator
|
|
ipMatcher matcher.Matcher
|
|
cidrMatcher matcher.Matcher
|
|
}
|
|
|
|
// WhitelistedAuthenticator returns an Authenticator that skips the underlying
|
|
// auther when the client's IP address matches one of the given patterns.
|
|
// Patterns may be IP addresses (e.g. "192.168.1.1") or CIDR ranges
|
|
// (e.g. "10.0.0.0/8"). Invalid patterns are silently ignored.
|
|
func WhitelistedAuthenticator(auther auth.Authenticator, patterns []string) auth.Authenticator {
|
|
var ips []net.IP
|
|
var inets []*net.IPNet
|
|
for _, pattern := range patterns {
|
|
pattern = strings.TrimSpace(pattern)
|
|
if pattern == "" {
|
|
continue
|
|
}
|
|
if ip := net.ParseIP(pattern); ip != nil {
|
|
ips = append(ips, ip)
|
|
continue
|
|
}
|
|
if _, inet, err := net.ParseCIDR(pattern); err == nil {
|
|
inets = append(inets, inet)
|
|
}
|
|
}
|
|
return &whitelistedAuthenticator{
|
|
auther: auther,
|
|
ipMatcher: matcher.IPMatcher(ips),
|
|
cidrMatcher: matcher.CIDRMatcher(inets),
|
|
}
|
|
}
|
|
|
|
func (w *whitelistedAuthenticator) Authenticate(ctx context.Context, user, password string, opts ...auth.Option) (string, bool) {
|
|
if srcAddr := xctx.SrcAddrFromContext(ctx); srcAddr != nil {
|
|
host, _, err := net.SplitHostPort(srcAddr.String())
|
|
if err == nil && host != "" {
|
|
if w.ipMatcher.Match(host) || w.cidrMatcher.Match(host) {
|
|
return "", true
|
|
}
|
|
}
|
|
}
|
|
if w.auther != nil {
|
|
return w.auther.Authenticate(ctx, user, password, opts...)
|
|
}
|
|
return "", false
|
|
}
|