package security import ( "encoding/json" "errors" "sync" "time" cfg "github.com/vapor/config" dbm "github.com/vapor/database/leveldb" ) const ( defaultBanDuration = time.Hour * 1 blacklistKey = "BlacklistPeers" ) var ( ErrConnectBannedPeer = errors.New("connect banned peer") ) type Blacklist struct { peers map[string]time.Time db dbm.DB mtx sync.Mutex } func NewBlacklist(config *cfg.Config) *Blacklist { return &Blacklist{ peers: make(map[string]time.Time), db: dbm.NewDB("blacklist", config.DBBackend, config.DBDir()), } } //AddPeer add peer to blacklist func (bl *Blacklist) AddPeer(ip string) error { bl.mtx.Lock() defer bl.mtx.Unlock() bl.peers[ip] = time.Now().Add(defaultBanDuration) dataJSON, err := json.Marshal(bl.peers) if err != nil { return err } bl.db.Set([]byte(blacklistKey), dataJSON) return nil } func (bl *Blacklist) delPeer(ip string) error { delete(bl.peers, ip) dataJson, err := json.Marshal(bl.peers) if err != nil { return err } bl.db.Set([]byte(blacklistKey), dataJson) return nil } func (bl *Blacklist) DoFilter(ip string, pubKey string) error { bl.mtx.Lock() defer bl.mtx.Unlock() if banEnd, ok := bl.peers[ip]; ok { if time.Now().Before(banEnd) { return ErrConnectBannedPeer } if err := bl.delPeer(ip); err != nil { return err } } return nil } // LoadPeers load banned peers from db func (bl *Blacklist) LoadPeers() error { bl.mtx.Lock() defer bl.mtx.Unlock() if dataJSON := bl.db.Get([]byte(blacklistKey)); dataJSON != nil { if err := json.Unmarshal(dataJSON, &bl.peers); err != nil { return err } } return nil }