--- /dev/null
+package security
+
+import (
+ "sync"
+
+ log "github.com/sirupsen/logrus"
+)
+
+const (
+ defaultBanThreshold = uint32(100)
+ defaultWarnThreshold = uint32(50)
+
+ LevelMsgIllegal = 0x01
+ levelMsgIllegalPersistent = uint32(20)
+ levelMsgIllegalTransient = uint32(0)
+ LevelConnException = 0x02
+ levelConnExceptionPersistent = uint32(0)
+ levelConnExceptionTransient = uint32(20)
+)
+
+type PeersBanScore struct {
+ peers map[string]*DynamicBanScore
+ mtx sync.Mutex
+}
+
+func NewPeersScore() *PeersBanScore {
+ return &PeersBanScore{
+ peers: make(map[string]*DynamicBanScore),
+ }
+}
+
+func (ps *PeersBanScore) DelPeer(ip string) {
+ ps.mtx.Lock()
+ defer ps.mtx.Unlock()
+
+ delete(ps.peers, ip)
+}
+
+func (ps *PeersBanScore) Increase(ip string, level byte, reason string) bool {
+ ps.mtx.Lock()
+ defer ps.mtx.Unlock()
+
+ var persistent, transient uint32
+ switch level {
+ case LevelMsgIllegal:
+ persistent = levelMsgIllegalPersistent
+ transient = levelMsgIllegalTransient
+ case LevelConnException:
+ persistent = levelConnExceptionPersistent
+ transient = levelConnExceptionTransient
+ default:
+ return false
+ }
+ banScore, ok := ps.peers[ip]
+ if !ok {
+ banScore = &DynamicBanScore{}
+ ps.peers[ip] = banScore
+ }
+ score := banScore.Increase(persistent, transient)
+ if score > defaultBanThreshold {
+ log.WithFields(log.Fields{"module": logModule, "address": ip, "score": score, "reason": reason}).Errorf("banning and disconnecting")
+ return true
+ }
+
+ if score > defaultWarnThreshold {
+ log.WithFields(log.Fields{"module": logModule, "address": ip, "score": score, "reason": reason}).Warning("ban score increasing")
+ }
+ return false
+}