* 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:
Ori Newman 2021-02-01 10:51:18 +02:00 committed by GitHub
parent 65e149b2bb
commit 669a9ab4c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 85 additions and 44 deletions

View File

@ -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 {

View File

@ -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

View File

@ -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)
}
}

View File

@ -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)

View File

@ -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)
}

View File

@ -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)

View File

@ -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())

View File

@ -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
}

View File

@ -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,
}

View File

@ -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
}