mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-03-30 15:08:33 +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)
|
||||
}
|
||||
|
||||
log.Errorf("error from %s: %+v", flowName, err)
|
||||
log.Errorf("error from %s: %s", flowName, err)
|
||||
}
|
||||
|
||||
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) {
|
||||
return nil, protocolerrors.New(true, "connected to self")
|
||||
return nil, protocolerrors.New(false, "connected to self")
|
||||
}
|
||||
|
||||
// Disconnect and ban peers from a different network
|
||||
|
@ -1421,7 +1421,7 @@ func TestHandleRelayInvs(t *testing.T) {
|
||||
if !test.expectsIBDToFinish {
|
||||
t.Fatalf("IBD unexpecetedly finished")
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
case <-time.After(10 * time.Second):
|
||||
if test.expectsIBDToFinish {
|
||||
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) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -78,11 +78,7 @@ func (m *Manager) handleError(err error, netConnection *netadapter.NetConnection
|
||||
if !m.context.Config().DisableBanning && protocolErr.ShouldBan {
|
||||
log.Warnf("Banning %s (reason: %s)", netConnection, protocolErr.Cause)
|
||||
|
||||
err := m.context.ConnectionManager().Ban(netConnection)
|
||||
if err != nil && !errors.Is(err, addressmanager.ErrAddressNotFound) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
m.context.ConnectionManager().Ban(netConnection)
|
||||
err = outgoingRoute.Enqueue(appmessage.NewMsgReject(protocolErr.Error()))
|
||||
if err != nil && !errors.Is(err, routerpkg.ErrRouteClosed) {
|
||||
panic(err)
|
||||
|
@ -232,12 +232,12 @@ func TestBoundedMergeDepth(t *testing.T) {
|
||||
}
|
||||
|
||||
factory := NewFactory()
|
||||
consensusBuild, teardownFunc1, err := factory.NewTestConsensus(params, false, "BoundedMergeTestBuild")
|
||||
consensusBuild, teardownFunc1, err := factory.NewTestConsensus(params, false, "TestBoundedMergeTestBuild")
|
||||
if err != nil {
|
||||
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 {
|
||||
t.Fatalf("TestBoundedMergeDepth: Error setting up consensus: %+v", err)
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package blockvalidator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
@ -29,6 +31,21 @@ func (v *blockValidator) ValidateHeaderInContext(blockHash *externalapi.DomainHa
|
||||
if err != nil {
|
||||
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)
|
||||
|
@ -12,16 +12,22 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// AddressRandomizer is the interface for the randomizer needed for the AddressManager.
|
||||
type AddressRandomizer interface {
|
||||
// addressRandomizer is the interface for the randomizer needed for the AddressManager.
|
||||
type addressRandomizer interface {
|
||||
RandomAddress(addresses []*appmessage.NetAddress) *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
|
||||
type AddressKey struct {
|
||||
// addressKey represents a pair of IP and port, the IP is always in V6 representation
|
||||
type addressKey struct {
|
||||
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
|
||||
@ -29,16 +35,16 @@ type AddressKey struct {
|
||||
var ErrAddressNotFound = errors.New("address not found")
|
||||
|
||||
// NetAddressKey returns a key of the ip address to use it in maps.
|
||||
func netAddressKey(netAddress *appmessage.NetAddress) AddressKey {
|
||||
key := AddressKey{port: netAddress.Port}
|
||||
func netAddressKey(netAddress *appmessage.NetAddress) addressKey {
|
||||
key := addressKey{port: netAddress.Port}
|
||||
// all IPv4 can be represented as IPv6.
|
||||
copy(key.address[:], netAddress.IP.To16())
|
||||
return key
|
||||
}
|
||||
|
||||
// netAddressKeys returns a key of the ip address to use it in maps.
|
||||
func netAddressesKeys(netAddresses []*appmessage.NetAddress) map[AddressKey]bool {
|
||||
result := make(map[AddressKey]bool, len(netAddresses))
|
||||
func netAddressesKeys(netAddresses []*appmessage.NetAddress) map[addressKey]bool {
|
||||
result := make(map[addressKey]bool, len(netAddresses))
|
||||
for _, netAddress := range netAddresses {
|
||||
key := netAddressKey(netAddress)
|
||||
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
|
||||
// peers on the Kaspa network.
|
||||
type AddressManager struct {
|
||||
addresses map[AddressKey]*appmessage.NetAddress
|
||||
bannedAddresses map[AddressKey]*appmessage.NetAddress
|
||||
addresses map[addressKey]*appmessage.NetAddress
|
||||
bannedAddresses map[ipv6]*appmessage.NetAddress
|
||||
localAddresses *localAddressManager
|
||||
mutex sync.Mutex
|
||||
cfg *Config
|
||||
random AddressRandomizer
|
||||
random addressRandomizer
|
||||
}
|
||||
|
||||
// New returns a new Kaspa address manager.
|
||||
@ -66,8 +72,8 @@ func New(cfg *Config) (*AddressManager, error) {
|
||||
}
|
||||
|
||||
return &AddressManager{
|
||||
addresses: map[AddressKey]*appmessage.NetAddress{},
|
||||
bannedAddresses: map[AddressKey]*appmessage.NetAddress{},
|
||||
addresses: map[addressKey]*appmessage.NetAddress{},
|
||||
bannedAddresses: map[ipv6]*appmessage.NetAddress{},
|
||||
localAddresses: localAddresses,
|
||||
random: NewAddressRandomize(),
|
||||
cfg: cfg,
|
||||
@ -111,7 +117,6 @@ func (am *AddressManager) RemoveAddress(address *appmessage.NetAddress) {
|
||||
|
||||
key := netAddressKey(address)
|
||||
delete(am.addresses, key)
|
||||
delete(am.bannedAddresses, key)
|
||||
}
|
||||
|
||||
// Addresses returns all addresses
|
||||
@ -175,21 +180,23 @@ func (am *AddressManager) BestLocalAddress(remoteAddress *appmessage.NetAddress)
|
||||
}
|
||||
|
||||
// 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()
|
||||
defer am.mutex.Unlock()
|
||||
|
||||
key := netAddressKey(address)
|
||||
addressToBan, ok := am.addresses[key]
|
||||
if !ok {
|
||||
return errors.Wrapf(ErrAddressNotFound, "address %s "+
|
||||
"is not registered with the address manager", address.TCPAddress())
|
||||
keyToBan := netAddressKey(addressToBan)
|
||||
keysToDelete := make([]addressKey, 0)
|
||||
for _, address := range am.addresses {
|
||||
key := netAddressKey(address)
|
||||
if key.address.equal(keyToBan.address) {
|
||||
keysToDelete = append(keysToDelete, key)
|
||||
}
|
||||
}
|
||||
for _, key := range keysToDelete {
|
||||
delete(am.addresses, key)
|
||||
}
|
||||
|
||||
delete(am.addresses, key)
|
||||
am.bannedAddresses[key] = addressToBan
|
||||
return nil
|
||||
|
||||
am.bannedAddresses[keyToBan.address] = addressToBan
|
||||
}
|
||||
|
||||
// Unban unmarks the given address as banned
|
||||
@ -198,13 +205,13 @@ func (am *AddressManager) Unban(address *appmessage.NetAddress) error {
|
||||
defer am.mutex.Unlock()
|
||||
|
||||
key := netAddressKey(address)
|
||||
bannedAddress, ok := am.bannedAddresses[key]
|
||||
bannedAddress, ok := am.bannedAddresses[key.address]
|
||||
if !ok {
|
||||
return errors.Wrapf(ErrAddressNotFound, "address %s "+
|
||||
"is not registered with the address manager as banned", address.TCPAddress())
|
||||
}
|
||||
|
||||
delete(am.bannedAddresses, key)
|
||||
delete(am.bannedAddresses, key.address)
|
||||
am.addresses[key] = bannedAddress
|
||||
return nil
|
||||
}
|
||||
@ -215,7 +222,7 @@ func (am *AddressManager) IsBanned(address *appmessage.NetAddress) (bool, error)
|
||||
defer am.mutex.Unlock()
|
||||
|
||||
key := netAddressKey(address)
|
||||
if _, ok := am.bannedAddresses[key]; !ok {
|
||||
if _, ok := am.bannedAddresses[key.address]; !ok {
|
||||
if _, ok = am.addresses[key]; !ok {
|
||||
return false, errors.Wrapf(ErrAddressNotFound, "address %s "+
|
||||
"is not registered with the address manager", address.TCPAddress())
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
)
|
||||
|
||||
// AddressRandomize implement AddressRandomizer interface
|
||||
// AddressRandomize implement addressRandomizer interface
|
||||
type AddressRandomize struct {
|
||||
random *rand.Rand
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ type localAddress struct {
|
||||
}
|
||||
|
||||
type localAddressManager struct {
|
||||
localAddresses map[AddressKey]*localAddress
|
||||
localAddresses map[addressKey]*localAddress
|
||||
lookupFunc func(string) ([]net.IP, error)
|
||||
cfg *Config
|
||||
mutex sync.Mutex
|
||||
@ -46,7 +46,7 @@ type localAddressManager struct {
|
||||
|
||||
func newLocalAddressManager(cfg *Config) (*localAddressManager, error) {
|
||||
localAddressManager := localAddressManager{
|
||||
localAddresses: map[AddressKey]*localAddress{},
|
||||
localAddresses: map[addressKey]*localAddress{},
|
||||
cfg: cfg,
|
||||
lookupFunc: cfg.Lookup,
|
||||
}
|
||||
|
@ -126,12 +126,21 @@ func (c *ConnectionManager) ConnectionCount() int {
|
||||
}
|
||||
|
||||
// Ban marks the given netConnection as banned
|
||||
func (c *ConnectionManager) Ban(netConnection *netadapter.NetConnection) error {
|
||||
return c.addressManager.Ban(netConnection.NetAddress())
|
||||
func (c *ConnectionManager) Ban(netConnection *netadapter.NetConnection) {
|
||||
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
|
||||
func (c *ConnectionManager) IsBanned(netConnection *netadapter.NetConnection) (bool, error) {
|
||||
if c.isPermanent(netConnection.Address()) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return c.addressManager.IsBanned(netConnection.NetAddress())
|
||||
}
|
||||
|
||||
@ -159,3 +168,15 @@ func (c *ConnectionManager) connectionExists(addressString string) bool {
|
||||
|
||||
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