3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-23 12:29:25 +01:00

Merge pull request #1425 from slingamn/issue1421_customlimits.2

fix #1421
This commit is contained in:
Shivaram Lingamneni 2020-12-05 16:03:51 -08:00 committed by GitHub
commit 23a7221137
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 65 additions and 24 deletions

View File

@ -263,13 +263,23 @@ server:
# - "192.168.1.1" # - "192.168.1.1"
# - "2001:0db8::/32" # - "2001:0db8::/32"
# custom connection limits for certain IPs/networks. note that CIDR # custom connection limits for certain IPs/networks.
# 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-limits: custom-limits:
# "8.8.0.0/16": #"irccloud":
# max-concurrent-connections: 128 # nets:
# max-connections-per-window: 1024 # - "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 # pluggable IP ban mechanism, via subprocess invocation
# this can be used to check new connections against a DNSBL, for example # this can be used to check new connections against a DNSBL, for example

View File

@ -19,14 +19,17 @@ var (
) )
type CustomLimitConfig struct { type CustomLimitConfig struct {
Nets []string
MaxConcurrent int `yaml:"max-concurrent-connections"` MaxConcurrent int `yaml:"max-concurrent-connections"`
MaxPerWindow int `yaml:"max-connections-per-window"` MaxPerWindow int `yaml:"max-connections-per-window"`
} }
// tuples the key-value pair of a CIDR and its custom limit/throttle values // tuples the key-value pair of a CIDR and its custom limit/throttle values
type customLimit struct { type customLimit struct {
CustomLimitConfig name string
ipNet net.IPNet maxConcurrent int
maxPerWindow int
nets []net.IPNet
} }
// LimiterConfig controls the automated connection limits. // 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()) return fmt.Errorf("Could not parse limiter exemption list: %v", err.Error())
} }
for netStr, customLimitConf := range config.CustomLimits { for identifier, customLimitConf := range config.CustomLimits {
normalizedNet, err := utils.NormalizedNetFromString(netStr) nets := make([]net.IPNet, len(customLimitConf.Nets))
if err != nil { for i, netStr := range customLimitConf.Nets {
return fmt.Errorf("Could not parse custom limit specification: %v", err.Error()) 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{ config.customLimits = append(config.customLimits, customLimit{
CustomLimitConfig: customLimitConf, maxConcurrent: customLimitConf.MaxConcurrent,
ipNet: normalizedNet, 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) { 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" // `key` will be a CIDR string like "8.8.8.8/32" or "2001:0db8::/32"
for _, custom := range cl.config.customLimits { for _, custom := range cl.config.customLimits {
if custom.ipNet.Contains(addr) { for _, net := range custom.nets {
return custom.ipNet.String(), custom.MaxConcurrent, custom.MaxPerWindow if net.Contains(addr) {
return custom.name, custom.maxConcurrent, custom.maxPerWindow
}
} }
} }

View File

@ -32,7 +32,8 @@ var baseConfig = LimiterConfig{
Exempted: []string{"localhost"}, Exempted: []string{"localhost"},
CustomLimits: map[string]CustomLimitConfig{ CustomLimits: map[string]CustomLimitConfig{
"8.8.0.0/16": { "google": {
Nets: []string{"8.8.0.0/16"},
MaxConcurrent: 128, MaxConcurrent: 128,
MaxPerWindow: 256, MaxPerWindow: 256,
}, },
@ -57,7 +58,7 @@ func TestKeying(t *testing.T) {
assertEqual(maxWin, 8, t) assertEqual(maxWin, 8, t)
key, maxConc, maxWin = limiter.addrToKey(easyParseIP("8.8.4.4")) 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(maxConc, 128, t)
assertEqual(maxWin, 256, t) assertEqual(maxWin, 256, t)
} }

View File

@ -236,13 +236,23 @@ server:
# - "192.168.1.1" # - "192.168.1.1"
# - "2001:0db8::/32" # - "2001:0db8::/32"
# custom connection limits for certain IPs/networks. note that CIDR # custom connection limits for certain IPs/networks.
# 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-limits: custom-limits:
# "8.8.0.0/16": #"irccloud":
# max-concurrent-connections: 128 # nets:
# max-connections-per-window: 1024 # - "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 # pluggable IP ban mechanism, via subprocess invocation
# this can be used to check new connections against a DNSBL, for example # this can be used to check new connections against a DNSBL, for example