mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-06-13 01:26:43 +00:00
Ban by IP (#1471)
* Ban by IP * Fix panic * Fix error format * Remove failed addresses Co-authored-by: stasatdaglabs <39559713+stasatdaglabs@users.noreply.github.com>
This commit is contained in:
parent
65e149b2bb
commit
669a9ab4c3
@ -22,7 +22,7 @@ func (*FlowContext) HandleError(err error, flowName string, isStopping *uint32,
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Errorf("error from %s: %+v", flowName, err)
|
log.Errorf("error from %s: %s", flowName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if atomic.AddUint32(isStopping, 1) == 1 {
|
if atomic.AddUint32(isStopping, 1) == 1 {
|
||||||
|
@ -60,7 +60,7 @@ func (flow *receiveVersionFlow) start() (*appmessage.NetAddress, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !allowSelfConnections && flow.NetAdapter().ID().IsEqual(msgVersion.ID) {
|
if !allowSelfConnections && flow.NetAdapter().ID().IsEqual(msgVersion.ID) {
|
||||||
return nil, protocolerrors.New(true, "connected to self")
|
return nil, protocolerrors.New(false, "connected to self")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disconnect and ban peers from a different network
|
// Disconnect and ban peers from a different network
|
||||||
|
@ -1421,7 +1421,7 @@ func TestHandleRelayInvs(t *testing.T) {
|
|||||||
if !test.expectsIBDToFinish {
|
if !test.expectsIBDToFinish {
|
||||||
t.Fatalf("IBD unexpecetedly finished")
|
t.Fatalf("IBD unexpecetedly finished")
|
||||||
}
|
}
|
||||||
case <-time.After(time.Second):
|
case <-time.After(10 * time.Second):
|
||||||
if test.expectsIBDToFinish {
|
if test.expectsIBDToFinish {
|
||||||
t.Fatalf("IBD didn't finished after %d", time.Second)
|
t.Fatalf("IBD didn't finished after %d", time.Second)
|
||||||
}
|
}
|
||||||
@ -1436,7 +1436,7 @@ func TestHandleRelayInvs(t *testing.T) {
|
|||||||
if !errors.Is(err, router.ErrRouteClosed) {
|
if !errors.Is(err, router.ErrRouteClosed) {
|
||||||
t.Fatalf("unexpected error %+v", err)
|
t.Fatalf("unexpected error %+v", err)
|
||||||
}
|
}
|
||||||
case <-time.After(time.Second):
|
case <-time.After(10 * time.Second):
|
||||||
t.Fatalf("waiting for flow to finish timed out after %s", time.Second)
|
t.Fatalf("waiting for flow to finish timed out after %s", time.Second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,11 +78,7 @@ func (m *Manager) handleError(err error, netConnection *netadapter.NetConnection
|
|||||||
if !m.context.Config().DisableBanning && protocolErr.ShouldBan {
|
if !m.context.Config().DisableBanning && protocolErr.ShouldBan {
|
||||||
log.Warnf("Banning %s (reason: %s)", netConnection, protocolErr.Cause)
|
log.Warnf("Banning %s (reason: %s)", netConnection, protocolErr.Cause)
|
||||||
|
|
||||||
err := m.context.ConnectionManager().Ban(netConnection)
|
m.context.ConnectionManager().Ban(netConnection)
|
||||||
if err != nil && !errors.Is(err, addressmanager.ErrAddressNotFound) {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = outgoingRoute.Enqueue(appmessage.NewMsgReject(protocolErr.Error()))
|
err = outgoingRoute.Enqueue(appmessage.NewMsgReject(protocolErr.Error()))
|
||||||
if err != nil && !errors.Is(err, routerpkg.ErrRouteClosed) {
|
if err != nil && !errors.Is(err, routerpkg.ErrRouteClosed) {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -232,12 +232,12 @@ func TestBoundedMergeDepth(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
factory := NewFactory()
|
factory := NewFactory()
|
||||||
consensusBuild, teardownFunc1, err := factory.NewTestConsensus(params, false, "BoundedMergeTestBuild")
|
consensusBuild, teardownFunc1, err := factory.NewTestConsensus(params, false, "TestBoundedMergeTestBuild")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("TestBoundedMergeDepth: Error setting up consensus: %+v", err)
|
t.Fatalf("TestBoundedMergeDepth: Error setting up consensus: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
consensusReal, teardownFunc2, err := factory.NewTestConsensus(params, false, "BoundedMergeTestReal")
|
consensusReal, teardownFunc2, err := factory.NewTestConsensus(params, false, "TestBoundedMergeTestReal")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("TestBoundedMergeDepth: Error setting up consensus: %+v", err)
|
t.Fatalf("TestBoundedMergeDepth: Error setting up consensus: %+v", err)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package blockvalidator
|
package blockvalidator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
|
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||||
@ -29,6 +31,21 @@ func (v *blockValidator) ValidateHeaderInContext(blockHash *externalapi.DomainHa
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var logErr error
|
||||||
|
log.Debug(logger.NewLogClosure(func() string {
|
||||||
|
var ghostdagData *model.BlockGHOSTDAGData
|
||||||
|
ghostdagData, logErr = v.ghostdagDataStore.Get(v.databaseContext, blockHash)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("block %s blue score is %d", blockHash, ghostdagData.BlueScore())
|
||||||
|
}))
|
||||||
|
|
||||||
|
if logErr != nil {
|
||||||
|
return logErr
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = v.validateMedianTime(header)
|
err = v.validateMedianTime(header)
|
||||||
|
@ -12,16 +12,22 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddressRandomizer is the interface for the randomizer needed for the AddressManager.
|
// addressRandomizer is the interface for the randomizer needed for the AddressManager.
|
||||||
type AddressRandomizer interface {
|
type addressRandomizer interface {
|
||||||
RandomAddress(addresses []*appmessage.NetAddress) *appmessage.NetAddress
|
RandomAddress(addresses []*appmessage.NetAddress) *appmessage.NetAddress
|
||||||
RandomAddresses(addresses []*appmessage.NetAddress, count int) []*appmessage.NetAddress
|
RandomAddresses(addresses []*appmessage.NetAddress, count int) []*appmessage.NetAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddressKey represents a pair of IP and port, the IP is always in V6 representation
|
// addressKey represents a pair of IP and port, the IP is always in V6 representation
|
||||||
type AddressKey struct {
|
type addressKey struct {
|
||||||
port uint16
|
port uint16
|
||||||
address [net.IPv6len]byte
|
address ipv6
|
||||||
|
}
|
||||||
|
|
||||||
|
type ipv6 [net.IPv6len]byte
|
||||||
|
|
||||||
|
func (i ipv6) equal(other ipv6) bool {
|
||||||
|
return i == other
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrAddressNotFound is an error returned from some functions when a
|
// ErrAddressNotFound is an error returned from some functions when a
|
||||||
@ -29,16 +35,16 @@ type AddressKey struct {
|
|||||||
var ErrAddressNotFound = errors.New("address not found")
|
var ErrAddressNotFound = errors.New("address not found")
|
||||||
|
|
||||||
// NetAddressKey returns a key of the ip address to use it in maps.
|
// NetAddressKey returns a key of the ip address to use it in maps.
|
||||||
func netAddressKey(netAddress *appmessage.NetAddress) AddressKey {
|
func netAddressKey(netAddress *appmessage.NetAddress) addressKey {
|
||||||
key := AddressKey{port: netAddress.Port}
|
key := addressKey{port: netAddress.Port}
|
||||||
// all IPv4 can be represented as IPv6.
|
// all IPv4 can be represented as IPv6.
|
||||||
copy(key.address[:], netAddress.IP.To16())
|
copy(key.address[:], netAddress.IP.To16())
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
|
|
||||||
// netAddressKeys returns a key of the ip address to use it in maps.
|
// netAddressKeys returns a key of the ip address to use it in maps.
|
||||||
func netAddressesKeys(netAddresses []*appmessage.NetAddress) map[AddressKey]bool {
|
func netAddressesKeys(netAddresses []*appmessage.NetAddress) map[addressKey]bool {
|
||||||
result := make(map[AddressKey]bool, len(netAddresses))
|
result := make(map[addressKey]bool, len(netAddresses))
|
||||||
for _, netAddress := range netAddresses {
|
for _, netAddress := range netAddresses {
|
||||||
key := netAddressKey(netAddress)
|
key := netAddressKey(netAddress)
|
||||||
result[key] = true
|
result[key] = true
|
||||||
@ -50,12 +56,12 @@ func netAddressesKeys(netAddresses []*appmessage.NetAddress) map[AddressKey]bool
|
|||||||
// AddressManager provides a concurrency safe address manager for caching potential
|
// AddressManager provides a concurrency safe address manager for caching potential
|
||||||
// peers on the Kaspa network.
|
// peers on the Kaspa network.
|
||||||
type AddressManager struct {
|
type AddressManager struct {
|
||||||
addresses map[AddressKey]*appmessage.NetAddress
|
addresses map[addressKey]*appmessage.NetAddress
|
||||||
bannedAddresses map[AddressKey]*appmessage.NetAddress
|
bannedAddresses map[ipv6]*appmessage.NetAddress
|
||||||
localAddresses *localAddressManager
|
localAddresses *localAddressManager
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
cfg *Config
|
cfg *Config
|
||||||
random AddressRandomizer
|
random addressRandomizer
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new Kaspa address manager.
|
// New returns a new Kaspa address manager.
|
||||||
@ -66,8 +72,8 @@ func New(cfg *Config) (*AddressManager, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &AddressManager{
|
return &AddressManager{
|
||||||
addresses: map[AddressKey]*appmessage.NetAddress{},
|
addresses: map[addressKey]*appmessage.NetAddress{},
|
||||||
bannedAddresses: map[AddressKey]*appmessage.NetAddress{},
|
bannedAddresses: map[ipv6]*appmessage.NetAddress{},
|
||||||
localAddresses: localAddresses,
|
localAddresses: localAddresses,
|
||||||
random: NewAddressRandomize(),
|
random: NewAddressRandomize(),
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
@ -111,7 +117,6 @@ func (am *AddressManager) RemoveAddress(address *appmessage.NetAddress) {
|
|||||||
|
|
||||||
key := netAddressKey(address)
|
key := netAddressKey(address)
|
||||||
delete(am.addresses, key)
|
delete(am.addresses, key)
|
||||||
delete(am.bannedAddresses, key)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Addresses returns all addresses
|
// Addresses returns all addresses
|
||||||
@ -175,21 +180,23 @@ func (am *AddressManager) BestLocalAddress(remoteAddress *appmessage.NetAddress)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ban marks the given address as banned
|
// Ban marks the given address as banned
|
||||||
func (am *AddressManager) Ban(address *appmessage.NetAddress) error {
|
func (am *AddressManager) Ban(addressToBan *appmessage.NetAddress) {
|
||||||
am.mutex.Lock()
|
am.mutex.Lock()
|
||||||
defer am.mutex.Unlock()
|
defer am.mutex.Unlock()
|
||||||
|
|
||||||
|
keyToBan := netAddressKey(addressToBan)
|
||||||
|
keysToDelete := make([]addressKey, 0)
|
||||||
|
for _, address := range am.addresses {
|
||||||
key := netAddressKey(address)
|
key := netAddressKey(address)
|
||||||
addressToBan, ok := am.addresses[key]
|
if key.address.equal(keyToBan.address) {
|
||||||
if !ok {
|
keysToDelete = append(keysToDelete, key)
|
||||||
return errors.Wrapf(ErrAddressNotFound, "address %s "+
|
}
|
||||||
"is not registered with the address manager", address.TCPAddress())
|
}
|
||||||
|
for _, key := range keysToDelete {
|
||||||
|
delete(am.addresses, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(am.addresses, key)
|
am.bannedAddresses[keyToBan.address] = addressToBan
|
||||||
am.bannedAddresses[key] = addressToBan
|
|
||||||
return nil
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unban unmarks the given address as banned
|
// Unban unmarks the given address as banned
|
||||||
@ -198,13 +205,13 @@ func (am *AddressManager) Unban(address *appmessage.NetAddress) error {
|
|||||||
defer am.mutex.Unlock()
|
defer am.mutex.Unlock()
|
||||||
|
|
||||||
key := netAddressKey(address)
|
key := netAddressKey(address)
|
||||||
bannedAddress, ok := am.bannedAddresses[key]
|
bannedAddress, ok := am.bannedAddresses[key.address]
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.Wrapf(ErrAddressNotFound, "address %s "+
|
return errors.Wrapf(ErrAddressNotFound, "address %s "+
|
||||||
"is not registered with the address manager as banned", address.TCPAddress())
|
"is not registered with the address manager as banned", address.TCPAddress())
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(am.bannedAddresses, key)
|
delete(am.bannedAddresses, key.address)
|
||||||
am.addresses[key] = bannedAddress
|
am.addresses[key] = bannedAddress
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -215,7 +222,7 @@ func (am *AddressManager) IsBanned(address *appmessage.NetAddress) (bool, error)
|
|||||||
defer am.mutex.Unlock()
|
defer am.mutex.Unlock()
|
||||||
|
|
||||||
key := netAddressKey(address)
|
key := netAddressKey(address)
|
||||||
if _, ok := am.bannedAddresses[key]; !ok {
|
if _, ok := am.bannedAddresses[key.address]; !ok {
|
||||||
if _, ok = am.addresses[key]; !ok {
|
if _, ok = am.addresses[key]; !ok {
|
||||||
return false, errors.Wrapf(ErrAddressNotFound, "address %s "+
|
return false, errors.Wrapf(ErrAddressNotFound, "address %s "+
|
||||||
"is not registered with the address manager", address.TCPAddress())
|
"is not registered with the address manager", address.TCPAddress())
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
"github.com/kaspanet/kaspad/app/appmessage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddressRandomize implement AddressRandomizer interface
|
// AddressRandomize implement addressRandomizer interface
|
||||||
type AddressRandomize struct {
|
type AddressRandomize struct {
|
||||||
random *rand.Rand
|
random *rand.Rand
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ type localAddress struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type localAddressManager struct {
|
type localAddressManager struct {
|
||||||
localAddresses map[AddressKey]*localAddress
|
localAddresses map[addressKey]*localAddress
|
||||||
lookupFunc func(string) ([]net.IP, error)
|
lookupFunc func(string) ([]net.IP, error)
|
||||||
cfg *Config
|
cfg *Config
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
@ -46,7 +46,7 @@ type localAddressManager struct {
|
|||||||
|
|
||||||
func newLocalAddressManager(cfg *Config) (*localAddressManager, error) {
|
func newLocalAddressManager(cfg *Config) (*localAddressManager, error) {
|
||||||
localAddressManager := localAddressManager{
|
localAddressManager := localAddressManager{
|
||||||
localAddresses: map[AddressKey]*localAddress{},
|
localAddresses: map[addressKey]*localAddress{},
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
lookupFunc: cfg.Lookup,
|
lookupFunc: cfg.Lookup,
|
||||||
}
|
}
|
||||||
|
@ -126,12 +126,21 @@ func (c *ConnectionManager) ConnectionCount() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ban marks the given netConnection as banned
|
// Ban marks the given netConnection as banned
|
||||||
func (c *ConnectionManager) Ban(netConnection *netadapter.NetConnection) error {
|
func (c *ConnectionManager) Ban(netConnection *netadapter.NetConnection) {
|
||||||
return c.addressManager.Ban(netConnection.NetAddress())
|
if c.isPermanent(netConnection.Address()) {
|
||||||
|
log.Infof("Cannot ban %s because it's a permanent connection", netConnection.Address())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.addressManager.Ban(netConnection.NetAddress())
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsBanned returns whether the given netConnection is banned
|
// IsBanned returns whether the given netConnection is banned
|
||||||
func (c *ConnectionManager) IsBanned(netConnection *netadapter.NetConnection) (bool, error) {
|
func (c *ConnectionManager) IsBanned(netConnection *netadapter.NetConnection) (bool, error) {
|
||||||
|
if c.isPermanent(netConnection.Address()) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
return c.addressManager.IsBanned(netConnection.NetAddress())
|
return c.addressManager.IsBanned(netConnection.NetAddress())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,3 +168,15 @@ func (c *ConnectionManager) connectionExists(addressString string) bool {
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ConnectionManager) isPermanent(addressString string) bool {
|
||||||
|
if conn, ok := c.activeRequested[addressString]; ok {
|
||||||
|
return conn.isPermanent
|
||||||
|
}
|
||||||
|
|
||||||
|
if conn, ok := c.pendingRequested[addressString]; ok {
|
||||||
|
return conn.isPermanent
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user