The core protocol of WoopChain
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
woop/p2p/security/security.go

192 lines
4.3 KiB

package security
import (
"fmt"
"sync"
"github.com/harmony-one/harmony/internal/utils/blockedpeers"
Release Candidate: dev -> main (#4319) * Rebase dev branch to current main branch (#4318) * add openssl compatibility on m2 chips using darwin (#4302) Adds support for OpenSSL on MacOS Ventura using m2 chips. * [dumpdb] ensure each cross link is dumped (#4311) * bump libp2p to version 0.24.0 and update its dependencies and relevant tests (#4315) * Removed legacy syncing peer provider. (#4260) * Removed legacy syncing peer provider. * Fix localnet. * Fix migrate version. * Rebased on main. * Fix formatting. * Remove blockchain dependency from engine. (#4310) * Consensus doesn't require anymore `Node` as a circular dependency. * Rebased upon main. * Removed engine beacon chain dependency. * Fixed nil error. * Fixed error. * bump libp2p to version 0.24.0 and update its dependencies and relevant tests * fix format, remove wrongly added configs * add back wrongly deleted comment * fix travis go checker Co-authored-by: Konstantin <355847+Frozen@users.noreply.github.com> Co-authored-by: “GheisMohammadi” <“Gheis.Mohammadi@gmail.com”> * bump libp2p to version 0.24.0 and update its dependencies and relevant tests (#4315) * Removed legacy syncing peer provider. (#4260) * Removed legacy syncing peer provider. * Fix localnet. * Fix migrate version. * Rebased on main. * Fix formatting. * Remove blockchain dependency from engine. (#4310) * Consensus doesn't require anymore `Node` as a circular dependency. * Rebased upon main. * Removed engine beacon chain dependency. * Fixed nil error. * Fixed error. * bump libp2p to version 0.24.0 and update its dependencies and relevant tests * fix format, remove wrongly added configs * add back wrongly deleted comment * fix travis go checker Co-authored-by: Konstantin <355847+Frozen@users.noreply.github.com> Co-authored-by: “GheisMohammadi” <“Gheis.Mohammadi@gmail.com”> * Fix for consensus stuck. (#4307) * Added check for block validity. * Starts new view change if block invalid. * Revert "Starts new view change if block invalid." This reverts commit e889fa5da2e0780f087ab7dae5106b96287706db. * staged dns sync v1.0 (#4316) * staged dns sync v1.0 * enabled stream downloader for localnet * fix code review issues * remove extra lock Co-authored-by: “GheisMohammadi” <“Gheis.Mohammadi@gmail.com”> * add description for closing client and change randomize process to ma… (#4276) * add description for closing client and change randomize process to make sure only online nodes are added to sync config * fix sync test * fix legacy limitNumPeers test * add WaitForEachPeerToConnect to node configs to make parallel peer connection optional Co-authored-by: “GheisMohammadi” <“Gheis.Mohammadi@gmail.com”> * Small fixes and code cleanup for network stack. (#4320) * staged dns sync v1.0 * enabled stream downloader for localnet * fix code review issues * remove extra lock * staged dns sync v1.0 * Fixed, code clean up and other. * Fixed, code clean up and other. * Fixed, code clean up and other. * Fix config. Co-authored-by: “GheisMohammadi” <“Gheis.Mohammadi@gmail.com”> * Fix not disable cache in archival mode (#4322) * Feature registry (#4324) * Registry for services. * Test. * Reverted comment. * Fix. * Slash fix (#4284) * Implementation of new slashing rate calculation * Write tests for then new slashing rate calculation * Add engine.applySlashing tests * fix #4059 Co-authored-by: Alex Brezas <abresas@gmail.com> Co-authored-by: Dimitris Lamprinos <pkakelas@gmail.com> * Bump github.com/aws/aws-sdk-go from 1.30.1 to 1.33.0 (#4325) (#4328) Bumps [github.com/aws/aws-sdk-go](https://github.com/aws/aws-sdk-go) from 1.30.1 to 1.33.0. - [Release notes](https://github.com/aws/aws-sdk-go/releases) - [Changelog](https://github.com/aws/aws-sdk-go/blob/v1.33.0/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-go/compare/v1.30.1...v1.33.0) --- updated-dependencies: - dependency-name: github.com/aws/aws-sdk-go dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump github.com/btcsuite/btcd from 0.21.0-beta to 0.23.2 (#4327) (#4329) Bumps [github.com/btcsuite/btcd](https://github.com/btcsuite/btcd) from 0.21.0-beta to 0.23.2. - [Release notes](https://github.com/btcsuite/btcd/releases) - [Changelog](https://github.com/btcsuite/btcd/blob/master/CHANGES) - [Commits](https://github.com/btcsuite/btcd/compare/v0.21.0-beta...v0.23.2) --- updated-dependencies: - dependency-name: github.com/btcsuite/btcd dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Max <82761650+MaxMustermann2@users.noreply.github.com> Co-authored-by: Gheis <36589218+GheisMohammadi@users.noreply.github.com> Co-authored-by: Konstantin <355847+Frozen@users.noreply.github.com> Co-authored-by: “GheisMohammadi” <“Gheis.Mohammadi@gmail.com”> Co-authored-by: Danny Willis <102543677+dannyposi@users.noreply.github.com> Co-authored-by: PeekPI <894646171@QQ.COM> Co-authored-by: Alex Brezas <abresas@gmail.com> Co-authored-by: Dimitris Lamprinos <pkakelas@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2 years ago
libp2p_network "github.com/libp2p/go-libp2p/core/network"
ma "github.com/multiformats/go-multiaddr"
"github.com/pkg/errors"
)
type Security interface {
OnConnectCheck(net libp2p_network.Network, conn libp2p_network.Conn) error
OnDisconnectCheck(conn libp2p_network.Conn) error
}
type peerMap struct {
peers map[string][]string
}
func newPeersMap() *peerMap {
return &peerMap{
peers: make(map[string][]string),
}
}
func (peerMap *peerMap) Len() int {
return len(peerMap.peers)
}
func (peerMap *peerMap) Store(key string, value []string) {
peerMap.peers[key] = value
}
func (peerMap *peerMap) HasKey(key string) bool {
_, ok := peerMap.peers[key]
return ok
}
func (peerMap *peerMap) Delete(key string) {
delete(peerMap.peers, key)
}
func (peerMap *peerMap) Load(key string) (value []string, ok bool) {
value, ok = peerMap.peers[key]
return value, ok
}
func (peerMap *peerMap) Range(f func(key string, value []string) bool) {
for key, value := range peerMap.peers {
if !f(key, value) {
break
}
}
}
type Manager struct {
maxConnPerIP int
maxPeers int64
mutex sync.Mutex
peers peerMap // All the connected nodes, key is the Peer's IP, value is the peer's ID array
banned *blockedpeers.Manager
}
func NewManager(maxConnPerIP int, maxPeers int64, banned *blockedpeers.Manager) *Manager {
if maxConnPerIP < 0 {
panic("maximum connections per IP must not be negative")
}
if maxPeers < 0 {
panic("maximum peers must not be negative")
}
return &Manager{
maxConnPerIP: maxConnPerIP,
maxPeers: maxPeers,
peers: newPeersMap(),
banned: banned,
}
}
func (m *Manager) RangePeers(f func(key string, value []string) bool) {
m.mutex.Lock()
defer m.mutex.Unlock()
m.peers.Range(f)
}
func (m *Manager) OnConnectCheck(net libp2p_network.Network, conn libp2p_network.Conn) error {
m.mutex.Lock()
defer m.mutex.Unlock()
remoteIp, err := getRemoteIP(conn)
if err != nil {
return errors.Wrap(err, "failed on get remote ip")
}
peers, _ := m.peers.Load(remoteIp)
// avoid add repeatedly
peerID := conn.RemotePeer().String()
_, ok := find(peers, peerID)
if !ok {
peers = append(peers, peerID)
}
if m.maxConnPerIP > 0 && len(peers) > m.maxConnPerIP {
utils.Logger().Warn().
Int("len(peers)", len(peers)).
Int("maxConnPerIP", m.maxConnPerIP).
Msgf("too many connections from %s, closing", remoteIp)
return net.ClosePeer(conn.RemotePeer())
}
currentPeerCount := m.peers.Len()
// only limit addition if it's a new peer and not an existing peer with new connection
if m.maxPeers > 0 && currentPeerCount >= m.maxPeers && !m.peers.HasKey(remoteIp) {
utils.Logger().Warn().
Int("connected peers", currentPeerCount).
Str("new peer", remoteIp).
Msg("too many peers, closing")
return net.ClosePeer(conn.RemotePeer())
}
if m.banned.IsBanned(conn.RemotePeer(), time.Now()) {
utils.Logger().Warn().
Str("new peer", remoteIp).
Msg("peer is banned, closing")
return net.ClosePeer(conn.RemotePeer())
}
m.peers.Store(remoteIp, peers)
return nil
}
func (m *Manager) OnDisconnectCheck(conn libp2p_network.Conn) error {
m.mutex.Lock()
defer m.mutex.Unlock()
ip, err := getRemoteIP(conn)
if err != nil {
return errors.Wrap(err, "failed on get ip")
}
peers, ok := m.peers.Load(ip)
if !ok {
return nil
}
peerID := conn.RemotePeer().String()
index, ok := find(peers, peerID)
if ok {
peers = append(peers[:index], peers[index+1:]...)
if len(peers) == 0 {
m.peers.Delete(ip)
} else {
m.peers.Store(ip, peers)
}
}
return nil
}
func find(slice []string, val string) (int, bool) {
for i, item := range slice {
if item == val {
return i, true
}
}
return -1, false
}
func getRemoteIP(conn libp2p_network.Conn) (string, error) {
for _, protocol := range conn.RemoteMultiaddr().Protocols() {
switch protocol.Code {
case ma.P_IP4:
ip, err := conn.RemoteMultiaddr().ValueForProtocol(ma.P_IP4)
if err != nil {
return "", errors.Wrap(err, "failed on get ipv4 addr")
}
return ip, nil
case ma.P_IP6:
ip, err := conn.RemoteMultiaddr().ValueForProtocol(ma.P_IP6)
if err != nil {
return "", errors.Wrap(err, "failed on get ipv6 addr")
}
return ip, nil
}
}
return "", errors.New(fmt.Sprintf("failed on get remote peer ip from addr: %s", conn.RemoteMultiaddr().String()))
}