2022-09-27 15:06:18 +00:00
|
|
|
package ban
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2022-10-26 10:02:53 +00:00
|
|
|
"net"
|
2022-09-27 15:06:18 +00:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"google.golang.org/grpc/codes"
|
|
|
|
"google.golang.org/grpc/peer"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
Unauthorized = "Unauthorized"
|
|
|
|
Unauthenticated = "Unauthenticated"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
defaultOptions = options{
|
2022-12-07 13:09:36 +00:00
|
|
|
cap: 1024,
|
|
|
|
reaperInterval: 10 * time.Minute,
|
|
|
|
rules: defaultRules,
|
|
|
|
actorFunc: DefaultActorFunc,
|
|
|
|
defaultCallback: nil,
|
|
|
|
defaultJailDuration: 10 * time.Second,
|
2022-09-27 15:06:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
defaultRules = []Rule{
|
|
|
|
{
|
|
|
|
Name: Unauthorized,
|
|
|
|
Message: "Too many unauthorized requests",
|
|
|
|
Code: codes.PermissionDenied,
|
|
|
|
StrikeLimit: 3,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: Unauthenticated,
|
|
|
|
Message: "Too many unauthenticated requests",
|
|
|
|
Code: codes.Unauthenticated,
|
|
|
|
StrikeLimit: 3,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
func DefaultActorFunc(ctx context.Context) (string, bool, error) {
|
|
|
|
p, ok := peer.FromContext(ctx)
|
|
|
|
if !ok {
|
|
|
|
return "", false, nil
|
|
|
|
}
|
2022-10-26 10:02:53 +00:00
|
|
|
if host, _, err := net.SplitHostPort(p.Addr.String()); err == nil {
|
|
|
|
return host, true, nil
|
|
|
|
}
|
2022-09-27 15:06:18 +00:00
|
|
|
return p.Addr.String(), true, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type Option func(*options)
|
|
|
|
|
|
|
|
func WithCapacity(cap int32) Option {
|
|
|
|
return func(o *options) {
|
|
|
|
o.cap = cap
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func WithRules(rules ...Rule) Option {
|
|
|
|
return func(o *options) {
|
|
|
|
o.rules = rules
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func WithReaperInterval(interval time.Duration) Option {
|
|
|
|
return func(o *options) {
|
|
|
|
o.reaperInterval = interval
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func WithActorFunc(f func(context.Context) (name string, found bool, err error)) Option {
|
|
|
|
return func(o *options) {
|
|
|
|
o.actorFunc = f
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-07 13:09:36 +00:00
|
|
|
func WithDefaultCallback(f ActionCallback) Option {
|
|
|
|
return func(o *options) {
|
|
|
|
o.defaultCallback = f
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func WithDefaultJailDuration(expire time.Duration) Option {
|
|
|
|
return func(o *options) {
|
|
|
|
o.defaultJailDuration = expire
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-27 15:06:18 +00:00
|
|
|
type options struct {
|
2022-12-07 13:09:36 +00:00
|
|
|
cap int32
|
|
|
|
rules []Rule
|
|
|
|
reaperInterval time.Duration
|
|
|
|
actorFunc func(ctx context.Context) (name string, found bool, err error)
|
|
|
|
defaultCallback ActionCallback
|
|
|
|
defaultJailDuration time.Duration
|
2022-09-27 15:06:18 +00:00
|
|
|
}
|