2019-11-18 07:42:48 +01:00
|
|
|
// Copyright (c) 2018 Shivaram Lingamneni
|
|
|
|
// released under the MIT license
|
|
|
|
|
|
|
|
package connection_limits
|
|
|
|
|
|
|
|
import (
|
2020-12-08 03:21:10 +01:00
|
|
|
"crypto/md5"
|
2019-11-18 07:42:48 +01:00
|
|
|
"net"
|
|
|
|
"testing"
|
|
|
|
"time"
|
2020-12-08 03:21:10 +01:00
|
|
|
|
|
|
|
"github.com/oragono/oragono/irc/flatip"
|
2019-11-18 07:42:48 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
func easyParseIP(ipstr string) (result net.IP) {
|
|
|
|
result = net.ParseIP(ipstr)
|
|
|
|
if result == nil {
|
|
|
|
panic(ipstr)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-12-08 03:21:10 +01:00
|
|
|
func easyParseFlat(ipstr string) (result flatip.IP) {
|
|
|
|
r1 := easyParseIP(ipstr)
|
|
|
|
return flatip.FromNetIP(r1)
|
|
|
|
}
|
|
|
|
|
2019-11-18 07:42:48 +01:00
|
|
|
var baseConfig = LimiterConfig{
|
2019-11-18 23:30:54 +01:00
|
|
|
rawLimiterConfig: rawLimiterConfig{
|
2019-11-24 03:09:31 +01:00
|
|
|
Count: true,
|
2019-11-18 07:42:48 +01:00
|
|
|
MaxConcurrent: 4,
|
|
|
|
|
|
|
|
Throttle: true,
|
|
|
|
Window: time.Second * 600,
|
|
|
|
MaxPerWindow: 8,
|
|
|
|
|
|
|
|
CidrLenIPv4: 32,
|
|
|
|
CidrLenIPv6: 64,
|
|
|
|
|
|
|
|
Exempted: []string{"localhost"},
|
|
|
|
|
|
|
|
CustomLimits: map[string]CustomLimitConfig{
|
2020-12-04 09:51:54 +01:00
|
|
|
"google": {
|
|
|
|
Nets: []string{"8.8.0.0/16"},
|
2019-11-18 07:42:48 +01:00
|
|
|
MaxConcurrent: 128,
|
|
|
|
MaxPerWindow: 256,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestKeying(t *testing.T) {
|
|
|
|
config := baseConfig
|
|
|
|
config.postprocess()
|
|
|
|
var limiter Limiter
|
|
|
|
limiter.ApplyConfig(&config)
|
|
|
|
|
2020-12-08 03:21:10 +01:00
|
|
|
// an ipv4 /32 looks like a /128 to us after applying the 4-in-6 mapping
|
|
|
|
key, maxConc, maxWin := limiter.addrToKey(easyParseFlat("1.1.1.1"))
|
|
|
|
assertEqual(key.prefixLen, uint8(128), t)
|
|
|
|
assertEqual(key.maskedIP[12:], []byte{1, 1, 1, 1}, t)
|
2019-11-18 07:42:48 +01:00
|
|
|
assertEqual(maxConc, 4, t)
|
|
|
|
assertEqual(maxWin, 8, t)
|
|
|
|
|
2020-12-08 03:21:10 +01:00
|
|
|
testIPv6 := easyParseFlat("2607:5301:201:3100::7426")
|
|
|
|
key, maxConc, maxWin = limiter.addrToKey(testIPv6)
|
|
|
|
assertEqual(key.prefixLen, uint8(64), t)
|
|
|
|
assertEqual(key.maskedIP[:], []byte(easyParseIP("2607:5301:201:3100::")), t)
|
2019-11-18 07:42:48 +01:00
|
|
|
assertEqual(maxConc, 4, t)
|
|
|
|
assertEqual(maxWin, 8, t)
|
|
|
|
|
2020-12-08 03:21:10 +01:00
|
|
|
key, maxConc, maxWin = limiter.addrToKey(easyParseFlat("8.8.4.4"))
|
|
|
|
assertEqual(key.prefixLen, uint8(0), t)
|
|
|
|
assertEqual([16]byte(key.maskedIP), md5.Sum([]byte("google")), t)
|
2019-11-18 07:42:48 +01:00
|
|
|
assertEqual(maxConc, 128, t)
|
|
|
|
assertEqual(maxWin, 256, t)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestLimits(t *testing.T) {
|
|
|
|
regularIP := easyParseIP("2607:5301:201:3100::7426")
|
|
|
|
config := baseConfig
|
|
|
|
config.postprocess()
|
|
|
|
var limiter Limiter
|
|
|
|
limiter.ApplyConfig(&config)
|
|
|
|
|
|
|
|
for i := 0; i < 4; i++ {
|
|
|
|
err := limiter.AddClient(regularIP)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("ip should not be blocked, but %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
err := limiter.AddClient(regularIP)
|
|
|
|
if err != ErrLimitExceeded {
|
|
|
|
t.Errorf("ip should be blocked, but %v", err)
|
|
|
|
}
|
|
|
|
limiter.RemoveClient(regularIP)
|
|
|
|
err = limiter.AddClient(regularIP)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("ip should not be blocked, but %v", err)
|
|
|
|
}
|
|
|
|
}
|