Browse Source

fix #1421

Allow custom limit definitions that encompass multiple subnets
tags/v2.5.0-rc1
Shivaram Lingamneni 3 years ago
parent
commit
f9b842c88b
4 changed files with 65 additions and 24 deletions
  1. 16
    6
      default.yaml
  2. 30
    10
      irc/connection_limits/limiter.go
  3. 3
    2
      irc/connection_limits/limiter_test.go
  4. 16
    6
      traditional.yaml

+ 16
- 6
default.yaml View File

263
             # - "192.168.1.1"
263
             # - "192.168.1.1"
264
             # - "2001:0db8::/32"
264
             # - "2001:0db8::/32"
265
 
265
 
266
-        # custom connection limits for certain IPs/networks. note that CIDR
267
-        # widths defined here override the default CIDR width --- the limit
268
-        # will apply to the entire CIDR no matter how large or small it is
266
+        # custom connection limits for certain IPs/networks.
269
         custom-limits:
267
         custom-limits:
270
-            # "8.8.0.0/16":
271
-            #     max-concurrent-connections: 128
272
-            #     max-connections-per-window: 1024
268
+            #"irccloud":
269
+            #    nets:
270
+            #        - "192.184.9.108"  # highgate.irccloud.com
271
+            #        - "192.184.9.110"  # ealing.irccloud.com
272
+            #        - "192.184.9.112"  # charlton.irccloud.com
273
+            #        - "192.184.10.118" # brockwell.irccloud.com
274
+            #        - "192.184.10.9"   # tooting.irccloud.com
275
+            #        - "192.184.8.73"   # hathersage.irccloud.com
276
+            #        - "192.184.8.103"  # stonehaven.irccloud.com
277
+            #        - "5.254.36.57"    # tinside.irccloud.com
278
+            #        - "5.254.36.56/29" # additional ipv4 net
279
+            #        - "2001:67c:2f08::/48"
280
+            #        - "2a03:5180:f::/64"
281
+            #    max-concurrent-connections: 2048
282
+            #    max-connections-per-window: 2048
273
 
283
 
274
     # pluggable IP ban mechanism, via subprocess invocation
284
     # pluggable IP ban mechanism, via subprocess invocation
275
     # this can be used to check new connections against a DNSBL, for example
285
     # this can be used to check new connections against a DNSBL, for example

+ 30
- 10
irc/connection_limits/limiter.go View File

19
 )
19
 )
20
 
20
 
21
 type CustomLimitConfig struct {
21
 type CustomLimitConfig struct {
22
+	Nets          []string
22
 	MaxConcurrent int `yaml:"max-concurrent-connections"`
23
 	MaxConcurrent int `yaml:"max-concurrent-connections"`
23
 	MaxPerWindow  int `yaml:"max-connections-per-window"`
24
 	MaxPerWindow  int `yaml:"max-connections-per-window"`
24
 }
25
 }
25
 
26
 
26
 // tuples the key-value pair of a CIDR and its custom limit/throttle values
27
 // tuples the key-value pair of a CIDR and its custom limit/throttle values
27
 type customLimit struct {
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
 // LimiterConfig controls the automated connection limits.
35
 // LimiterConfig controls the automated connection limits.
71
 		return fmt.Errorf("Could not parse limiter exemption list: %v", err.Error())
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
 		config.customLimits = append(config.customLimits, customLimit{
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
 func (cl *Limiter) addrToKey(addr net.IP) (key string, limit int, throttle int) {
123
 func (cl *Limiter) addrToKey(addr net.IP) (key string, limit int, throttle int) {
106
 	// `key` will be a CIDR string like "8.8.8.8/32" or "2001:0db8::/32"
124
 	// `key` will be a CIDR string like "8.8.8.8/32" or "2001:0db8::/32"
107
 	for _, custom := range cl.config.customLimits {
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
 

+ 3
- 2
irc/connection_limits/limiter_test.go View File

32
 		Exempted: []string{"localhost"},
32
 		Exempted: []string{"localhost"},
33
 
33
 
34
 		CustomLimits: map[string]CustomLimitConfig{
34
 		CustomLimits: map[string]CustomLimitConfig{
35
-			"8.8.0.0/16": {
35
+			"google": {
36
+				Nets:          []string{"8.8.0.0/16"},
36
 				MaxConcurrent: 128,
37
 				MaxConcurrent: 128,
37
 				MaxPerWindow:  256,
38
 				MaxPerWindow:  256,
38
 			},
39
 			},
57
 	assertEqual(maxWin, 8, t)
58
 	assertEqual(maxWin, 8, t)
58
 
59
 
59
 	key, maxConc, maxWin = limiter.addrToKey(easyParseIP("8.8.4.4"))
60
 	key, maxConc, maxWin = limiter.addrToKey(easyParseIP("8.8.4.4"))
60
-	assertEqual(key, "8.8.0.0/16", t)
61
+	assertEqual(key, "*google", t)
61
 	assertEqual(maxConc, 128, t)
62
 	assertEqual(maxConc, 128, t)
62
 	assertEqual(maxWin, 256, t)
63
 	assertEqual(maxWin, 256, t)
63
 }
64
 }

+ 16
- 6
traditional.yaml View File

236
             # - "192.168.1.1"
236
             # - "192.168.1.1"
237
             # - "2001:0db8::/32"
237
             # - "2001:0db8::/32"
238
 
238
 
239
-        # custom connection limits for certain IPs/networks. note that CIDR
240
-        # widths defined here override the default CIDR width --- the limit
241
-        # will apply to the entire CIDR no matter how large or small it is
239
+        # custom connection limits for certain IPs/networks.
242
         custom-limits:
240
         custom-limits:
243
-            # "8.8.0.0/16":
244
-            #     max-concurrent-connections: 128
245
-            #     max-connections-per-window: 1024
241
+            #"irccloud":
242
+            #    nets:
243
+            #        - "192.184.9.108"  # highgate.irccloud.com
244
+            #        - "192.184.9.110"  # ealing.irccloud.com
245
+            #        - "192.184.9.112"  # charlton.irccloud.com
246
+            #        - "192.184.10.118" # brockwell.irccloud.com
247
+            #        - "192.184.10.9"   # tooting.irccloud.com
248
+            #        - "192.184.8.73"   # hathersage.irccloud.com
249
+            #        - "192.184.8.103"  # stonehaven.irccloud.com
250
+            #        - "5.254.36.57"    # tinside.irccloud.com
251
+            #        - "5.254.36.56/29" # additional ipv4 net
252
+            #        - "2001:67c:2f08::/48"
253
+            #        - "2a03:5180:f::/64"
254
+            #    max-concurrent-connections: 2048
255
+            #    max-connections-per-window: 2048
246
 
256
 
247
     # pluggable IP ban mechanism, via subprocess invocation
257
     # pluggable IP ban mechanism, via subprocess invocation
248
     # this can be used to check new connections against a DNSBL, for example
258
     # this can be used to check new connections against a DNSBL, for example

Loading…
Cancel
Save