mirror of
https://github.com/ergochat/ergo.git
synced 2024-12-22 10:42:52 +01:00
fix #1421
Allow custom limit definitions that encompass multiple subnets
This commit is contained in:
parent
7e56f62aed
commit
f9b842c88b
22
default.yaml
22
default.yaml
@ -263,13 +263,23 @@ server:
|
||||
# - "192.168.1.1"
|
||||
# - "2001:0db8::/32"
|
||||
|
||||
# custom connection limits for certain IPs/networks. note that CIDR
|
||||
# widths defined here override the default CIDR width --- the limit
|
||||
# will apply to the entire CIDR no matter how large or small it is
|
||||
# custom connection limits for certain IPs/networks.
|
||||
custom-limits:
|
||||
# "8.8.0.0/16":
|
||||
# max-concurrent-connections: 128
|
||||
# max-connections-per-window: 1024
|
||||
#"irccloud":
|
||||
# nets:
|
||||
# - "192.184.9.108" # highgate.irccloud.com
|
||||
# - "192.184.9.110" # ealing.irccloud.com
|
||||
# - "192.184.9.112" # charlton.irccloud.com
|
||||
# - "192.184.10.118" # brockwell.irccloud.com
|
||||
# - "192.184.10.9" # tooting.irccloud.com
|
||||
# - "192.184.8.73" # hathersage.irccloud.com
|
||||
# - "192.184.8.103" # stonehaven.irccloud.com
|
||||
# - "5.254.36.57" # tinside.irccloud.com
|
||||
# - "5.254.36.56/29" # additional ipv4 net
|
||||
# - "2001:67c:2f08::/48"
|
||||
# - "2a03:5180:f::/64"
|
||||
# max-concurrent-connections: 2048
|
||||
# max-connections-per-window: 2048
|
||||
|
||||
# pluggable IP ban mechanism, via subprocess invocation
|
||||
# this can be used to check new connections against a DNSBL, for example
|
||||
|
@ -19,14 +19,17 @@ var (
|
||||
)
|
||||
|
||||
type CustomLimitConfig struct {
|
||||
Nets []string
|
||||
MaxConcurrent int `yaml:"max-concurrent-connections"`
|
||||
MaxPerWindow int `yaml:"max-connections-per-window"`
|
||||
}
|
||||
|
||||
// tuples the key-value pair of a CIDR and its custom limit/throttle values
|
||||
type customLimit struct {
|
||||
CustomLimitConfig
|
||||
ipNet net.IPNet
|
||||
name string
|
||||
maxConcurrent int
|
||||
maxPerWindow int
|
||||
nets []net.IPNet
|
||||
}
|
||||
|
||||
// LimiterConfig controls the automated connection limits.
|
||||
@ -71,14 +74,29 @@ func (config *LimiterConfig) postprocess() (err error) {
|
||||
return fmt.Errorf("Could not parse limiter exemption list: %v", err.Error())
|
||||
}
|
||||
|
||||
for netStr, customLimitConf := range config.CustomLimits {
|
||||
normalizedNet, err := utils.NormalizedNetFromString(netStr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not parse custom limit specification: %v", err.Error())
|
||||
for identifier, customLimitConf := range config.CustomLimits {
|
||||
nets := make([]net.IPNet, len(customLimitConf.Nets))
|
||||
for i, netStr := range customLimitConf.Nets {
|
||||
normalizedNet, err := utils.NormalizedNetFromString(netStr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Bad net %s in custom-limits block %s: %w", netStr, identifier, err)
|
||||
}
|
||||
nets[i] = normalizedNet
|
||||
}
|
||||
if len(customLimitConf.Nets) == 0 {
|
||||
// see #1421: this is the legacy config format where the
|
||||
// dictionary key of the block is a CIDR string
|
||||
normalizedNet, err := utils.NormalizedNetFromString(identifier)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Custom limit block %s has no defined nets", identifier)
|
||||
}
|
||||
nets = []net.IPNet{normalizedNet}
|
||||
}
|
||||
config.customLimits = append(config.customLimits, customLimit{
|
||||
CustomLimitConfig: customLimitConf,
|
||||
ipNet: normalizedNet,
|
||||
maxConcurrent: customLimitConf.MaxConcurrent,
|
||||
maxPerWindow: customLimitConf.MaxPerWindow,
|
||||
name: "*" + identifier,
|
||||
nets: nets,
|
||||
})
|
||||
}
|
||||
|
||||
@ -105,8 +123,10 @@ type Limiter struct {
|
||||
func (cl *Limiter) addrToKey(addr net.IP) (key string, limit int, throttle int) {
|
||||
// `key` will be a CIDR string like "8.8.8.8/32" or "2001:0db8::/32"
|
||||
for _, custom := range cl.config.customLimits {
|
||||
if custom.ipNet.Contains(addr) {
|
||||
return custom.ipNet.String(), custom.MaxConcurrent, custom.MaxPerWindow
|
||||
for _, net := range custom.nets {
|
||||
if net.Contains(addr) {
|
||||
return custom.name, custom.maxConcurrent, custom.maxPerWindow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,8 @@ var baseConfig = LimiterConfig{
|
||||
Exempted: []string{"localhost"},
|
||||
|
||||
CustomLimits: map[string]CustomLimitConfig{
|
||||
"8.8.0.0/16": {
|
||||
"google": {
|
||||
Nets: []string{"8.8.0.0/16"},
|
||||
MaxConcurrent: 128,
|
||||
MaxPerWindow: 256,
|
||||
},
|
||||
@ -57,7 +58,7 @@ func TestKeying(t *testing.T) {
|
||||
assertEqual(maxWin, 8, t)
|
||||
|
||||
key, maxConc, maxWin = limiter.addrToKey(easyParseIP("8.8.4.4"))
|
||||
assertEqual(key, "8.8.0.0/16", t)
|
||||
assertEqual(key, "*google", t)
|
||||
assertEqual(maxConc, 128, t)
|
||||
assertEqual(maxWin, 256, t)
|
||||
}
|
||||
|
@ -236,13 +236,23 @@ server:
|
||||
# - "192.168.1.1"
|
||||
# - "2001:0db8::/32"
|
||||
|
||||
# custom connection limits for certain IPs/networks. note that CIDR
|
||||
# widths defined here override the default CIDR width --- the limit
|
||||
# will apply to the entire CIDR no matter how large or small it is
|
||||
# custom connection limits for certain IPs/networks.
|
||||
custom-limits:
|
||||
# "8.8.0.0/16":
|
||||
# max-concurrent-connections: 128
|
||||
# max-connections-per-window: 1024
|
||||
#"irccloud":
|
||||
# nets:
|
||||
# - "192.184.9.108" # highgate.irccloud.com
|
||||
# - "192.184.9.110" # ealing.irccloud.com
|
||||
# - "192.184.9.112" # charlton.irccloud.com
|
||||
# - "192.184.10.118" # brockwell.irccloud.com
|
||||
# - "192.184.10.9" # tooting.irccloud.com
|
||||
# - "192.184.8.73" # hathersage.irccloud.com
|
||||
# - "192.184.8.103" # stonehaven.irccloud.com
|
||||
# - "5.254.36.57" # tinside.irccloud.com
|
||||
# - "5.254.36.56/29" # additional ipv4 net
|
||||
# - "2001:67c:2f08::/48"
|
||||
# - "2a03:5180:f::/64"
|
||||
# max-concurrent-connections: 2048
|
||||
# max-connections-per-window: 2048
|
||||
|
||||
# pluggable IP ban mechanism, via subprocess invocation
|
||||
# this can be used to check new connections against a DNSBL, for example
|
||||
|
Loading…
Reference in New Issue
Block a user