|
@@ -19,14 +19,17 @@ var (
|
19
|
19
|
)
|
20
|
20
|
|
21
|
21
|
type CustomLimitConfig struct {
|
|
22
|
+ Nets []string
|
22
|
23
|
MaxConcurrent int `yaml:"max-concurrent-connections"`
|
23
|
24
|
MaxPerWindow int `yaml:"max-connections-per-window"`
|
24
|
25
|
}
|
25
|
26
|
|
26
|
27
|
// tuples the key-value pair of a CIDR and its custom limit/throttle values
|
27
|
28
|
type customLimit struct {
|
28
|
|
- CustomLimitConfig
|
29
|
|
- ipNet net.IPNet
|
|
29
|
+ name string
|
|
30
|
+ maxConcurrent int
|
|
31
|
+ maxPerWindow int
|
|
32
|
+ nets []net.IPNet
|
30
|
33
|
}
|
31
|
34
|
|
32
|
35
|
// LimiterConfig controls the automated connection limits.
|
|
@@ -71,14 +74,29 @@ func (config *LimiterConfig) postprocess() (err error) {
|
71
|
74
|
return fmt.Errorf("Could not parse limiter exemption list: %v", err.Error())
|
72
|
75
|
}
|
73
|
76
|
|
74
|
|
- for netStr, customLimitConf := range config.CustomLimits {
|
75
|
|
- normalizedNet, err := utils.NormalizedNetFromString(netStr)
|
76
|
|
- if err != nil {
|
77
|
|
- return fmt.Errorf("Could not parse custom limit specification: %v", err.Error())
|
|
77
|
+ for identifier, customLimitConf := range config.CustomLimits {
|
|
78
|
+ nets := make([]net.IPNet, len(customLimitConf.Nets))
|
|
79
|
+ for i, netStr := range customLimitConf.Nets {
|
|
80
|
+ normalizedNet, err := utils.NormalizedNetFromString(netStr)
|
|
81
|
+ if err != nil {
|
|
82
|
+ return fmt.Errorf("Bad net %s in custom-limits block %s: %w", netStr, identifier, err)
|
|
83
|
+ }
|
|
84
|
+ nets[i] = normalizedNet
|
|
85
|
+ }
|
|
86
|
+ if len(customLimitConf.Nets) == 0 {
|
|
87
|
+ // see #1421: this is the legacy config format where the
|
|
88
|
+ // dictionary key of the block is a CIDR string
|
|
89
|
+ normalizedNet, err := utils.NormalizedNetFromString(identifier)
|
|
90
|
+ if err != nil {
|
|
91
|
+ return fmt.Errorf("Custom limit block %s has no defined nets", identifier)
|
|
92
|
+ }
|
|
93
|
+ nets = []net.IPNet{normalizedNet}
|
78
|
94
|
}
|
79
|
95
|
config.customLimits = append(config.customLimits, customLimit{
|
80
|
|
- CustomLimitConfig: customLimitConf,
|
81
|
|
- ipNet: normalizedNet,
|
|
96
|
+ maxConcurrent: customLimitConf.MaxConcurrent,
|
|
97
|
+ maxPerWindow: customLimitConf.MaxPerWindow,
|
|
98
|
+ name: "*" + identifier,
|
|
99
|
+ nets: nets,
|
82
|
100
|
})
|
83
|
101
|
}
|
84
|
102
|
|
|
@@ -105,8 +123,10 @@ type Limiter struct {
|
105
|
123
|
func (cl *Limiter) addrToKey(addr net.IP) (key string, limit int, throttle int) {
|
106
|
124
|
// `key` will be a CIDR string like "8.8.8.8/32" or "2001:0db8::/32"
|
107
|
125
|
for _, custom := range cl.config.customLimits {
|
108
|
|
- if custom.ipNet.Contains(addr) {
|
109
|
|
- return custom.ipNet.String(), custom.MaxConcurrent, custom.MaxPerWindow
|
|
126
|
+ for _, net := range custom.nets {
|
|
127
|
+ if net.Contains(addr) {
|
|
128
|
+ return custom.name, custom.maxConcurrent, custom.maxPerWindow
|
|
129
|
+ }
|
110
|
130
|
}
|
111
|
131
|
}
|
112
|
132
|
|