c75fea9c94
Dynamic ban scores consist of a persistent and a decaying component. The persistent score can be used to create simple additive banning policies simlar to those found in other bitcoin node implementations. The decaying score enables the creation of evasive logic which handles misbehaving peers (especially application layer DoS attacks) gracefully by disconnecting and banning peers attempting various kinds of flooding. Dynamic ban scores allow these two approaches to be used in tandem. This pull request includes the following: - Dynamic ban score type & functions, with tests for core functionality - Ban score of connected peers can be queried via rpc (getpeerinfo) - Example policy with decaying score increments on mempool and getdata - Logging of misbehavior once half of the ban threshold is reached - Banning logic can be disabled via configuration (enabled by default) - User defined ban threshold can be set via configuration
68 lines
1.7 KiB
Go
68 lines
1.7 KiB
Go
// Copyright (c) 2016 The btcsuite developers
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package main
|
|
|
|
import (
|
|
"math"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// TestDynamicBanScoreDecay tests the exponential decay implemented in
|
|
// dynamicBanScore.
|
|
func TestDynamicBanScoreDecay(t *testing.T) {
|
|
var bs dynamicBanScore
|
|
base := time.Now()
|
|
|
|
r := bs.increase(100, 50, base)
|
|
if r != 150 {
|
|
t.Errorf("Unexpected result %d after ban score increase.", r)
|
|
}
|
|
|
|
r = bs.int(base.Add(time.Minute))
|
|
if r != 125 {
|
|
t.Errorf("Halflife check failed - %d instead of 125", r)
|
|
}
|
|
|
|
r = bs.int(base.Add(7 * time.Minute))
|
|
if r != 100 {
|
|
t.Errorf("Decay after 7m - %d instead of 100", r)
|
|
}
|
|
}
|
|
|
|
// TestDynamicBanScoreLifetime tests that dynamicBanScore properly yields zero
|
|
// once the maximum age is reached.
|
|
func TestDynamicBanScoreLifetime(t *testing.T) {
|
|
var bs dynamicBanScore
|
|
base := time.Now()
|
|
|
|
r := bs.increase(0, math.MaxUint32, base)
|
|
r = bs.int(base.Add(Lifetime * time.Second))
|
|
if r != 3 { // 3, not 4 due to precision loss and truncating 3.999...
|
|
t.Errorf("Pre max age check with MaxUint32 failed - %d", r)
|
|
}
|
|
r = bs.int(base.Add((Lifetime + 1) * time.Second))
|
|
if r != 0 {
|
|
t.Errorf("Zero after max age check failed - %d instead of 0", r)
|
|
}
|
|
}
|
|
|
|
// TestDynamicBanScore tests exported functions of dynamicBanScore. Exponential
|
|
// decay or other time based behavior is tested by other functions.
|
|
func TestDynamicBanScoreReset(t *testing.T) {
|
|
var bs dynamicBanScore
|
|
if bs.Int() != 0 {
|
|
t.Errorf("Initial state is not zero.")
|
|
}
|
|
bs.Increase(100, 0)
|
|
r := bs.Int()
|
|
if r != 100 {
|
|
t.Errorf("Unexpected result %d after ban score increase.", r)
|
|
}
|
|
bs.Reset()
|
|
if bs.Int() != 0 {
|
|
t.Errorf("Failed to reset ban score.")
|
|
}
|
|
}
|