mirror of
https://github.com/LBRYFoundation/lbcd.git
synced 2025-08-23 17:47:24 +00:00
Merge pull request #1418 from cfromknecht/useragent-white-blacklist
Configurable UserAgent filtering
This commit is contained in:
commit
150379531e
3 changed files with 75 additions and 3 deletions
4
btcd.go
4
btcd.go
|
@ -145,8 +145,8 @@ func btcdMain(serverChan chan<- *server) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create server and start it.
|
// Create server and start it.
|
||||||
server, err := newServer(cfg.Listeners, db, activeNetParams.Params,
|
server, err := newServer(cfg.Listeners, cfg.AgentBlacklist,
|
||||||
interrupt)
|
cfg.AgentWhitelist, db, activeNetParams.Params, interrupt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: this logging could do with some beautifying.
|
// TODO: this logging could do with some beautifying.
|
||||||
btcdLog.Errorf("Unable to start server on %v: %v",
|
btcdLog.Errorf("Unable to start server on %v: %v",
|
||||||
|
|
|
@ -106,6 +106,8 @@ type config struct {
|
||||||
BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"`
|
BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"`
|
||||||
BanThreshold uint32 `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."`
|
BanThreshold uint32 `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."`
|
||||||
Whitelists []string `long:"whitelist" description:"Add an IP network or IP that will not be banned. (eg. 192.168.1.0/24 or ::1)"`
|
Whitelists []string `long:"whitelist" description:"Add an IP network or IP that will not be banned. (eg. 192.168.1.0/24 or ::1)"`
|
||||||
|
AgentBlacklist []string `long:"agentblacklist" description:"A comma separated list of user-agent substrings which will cause btcd to reject any peers whose user-agent contains any of the blacklisted substrings."`
|
||||||
|
AgentWhitelist []string `long:"agentwhitelist" description:"A comma separated list of user-agent substrings which will cause btcd to require all peers' user-agents to contain one of the whitelisted substrings. The blacklist is applied before the blacklist, and an empty whitelist will allow all agents that do not fail the blacklist."`
|
||||||
RPCUser string `short:"u" long:"rpcuser" description:"Username for RPC connections"`
|
RPCUser string `short:"u" long:"rpcuser" description:"Username for RPC connections"`
|
||||||
RPCPass string `short:"P" long:"rpcpass" default-mask:"-" description:"Password for RPC connections"`
|
RPCPass string `short:"P" long:"rpcpass" default-mask:"-" description:"Password for RPC connections"`
|
||||||
RPCLimitUser string `long:"rpclimituser" description:"Username for limited RPC connections"`
|
RPCLimitUser string `long:"rpclimituser" description:"Username for limited RPC connections"`
|
||||||
|
|
72
server.go
72
server.go
|
@ -246,6 +246,14 @@ type server struct {
|
||||||
// messages for each filter type.
|
// messages for each filter type.
|
||||||
cfCheckptCaches map[wire.FilterType][]cfHeaderKV
|
cfCheckptCaches map[wire.FilterType][]cfHeaderKV
|
||||||
cfCheckptCachesMtx sync.RWMutex
|
cfCheckptCachesMtx sync.RWMutex
|
||||||
|
|
||||||
|
// agentBlacklist is a list of blacklisted substrings by which to filter
|
||||||
|
// user agents.
|
||||||
|
agentBlacklist []string
|
||||||
|
|
||||||
|
// agentWhitelist is a list of whitelisted user agent substrings, no
|
||||||
|
// whitelisting will be applied if the list is empty or nil.
|
||||||
|
agentWhitelist []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// serverPeer extends the peer to maintain state shared by the server and
|
// serverPeer extends the peer to maintain state shared by the server and
|
||||||
|
@ -1586,6 +1594,12 @@ func (s *server) handleAddPeerMsg(state *peerState, sp *serverPeer) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disconnect peers with unwanted user agents.
|
||||||
|
if sp.HasUndesiredUserAgent(s.agentBlacklist, s.agentWhitelist) {
|
||||||
|
sp.Disconnect()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Ignore new peers if we're shutting down.
|
// Ignore new peers if we're shutting down.
|
||||||
if atomic.LoadInt32(&s.shutdown) != 0 {
|
if atomic.LoadInt32(&s.shutdown) != 0 {
|
||||||
srvrLog.Infof("New peer %s ignored - server is shutting down", sp)
|
srvrLog.Infof("New peer %s ignored - server is shutting down", sp)
|
||||||
|
@ -2538,7 +2552,10 @@ func setupRPCListeners() ([]net.Listener, error) {
|
||||||
// newServer returns a new btcd server configured to listen on addr for the
|
// newServer returns a new btcd server configured to listen on addr for the
|
||||||
// bitcoin network type specified by chainParams. Use start to begin accepting
|
// bitcoin network type specified by chainParams. Use start to begin accepting
|
||||||
// connections from peers.
|
// connections from peers.
|
||||||
func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Params, interrupt <-chan struct{}) (*server, error) {
|
func newServer(listenAddrs, agentBlacklist, agentWhitelist []string,
|
||||||
|
db database.DB, chainParams *chaincfg.Params,
|
||||||
|
interrupt <-chan struct{}) (*server, error) {
|
||||||
|
|
||||||
services := defaultServices
|
services := defaultServices
|
||||||
if cfg.NoPeerBloomFilters {
|
if cfg.NoPeerBloomFilters {
|
||||||
services &^= wire.SFNodeBloom
|
services &^= wire.SFNodeBloom
|
||||||
|
@ -2562,6 +2579,13 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(agentBlacklist) > 0 {
|
||||||
|
srvrLog.Infof("User-agent blacklist %s", agentBlacklist)
|
||||||
|
}
|
||||||
|
if len(agentWhitelist) > 0 {
|
||||||
|
srvrLog.Infof("User-agent whitelist %s", agentWhitelist)
|
||||||
|
}
|
||||||
|
|
||||||
s := server{
|
s := server{
|
||||||
chainParams: chainParams,
|
chainParams: chainParams,
|
||||||
addrManager: amgr,
|
addrManager: amgr,
|
||||||
|
@ -2581,6 +2605,8 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
|
||||||
sigCache: txscript.NewSigCache(cfg.SigCacheMaxSize),
|
sigCache: txscript.NewSigCache(cfg.SigCacheMaxSize),
|
||||||
hashCache: txscript.NewHashCache(cfg.SigCacheMaxSize),
|
hashCache: txscript.NewHashCache(cfg.SigCacheMaxSize),
|
||||||
cfCheckptCaches: make(map[wire.FilterType][]cfHeaderKV),
|
cfCheckptCaches: make(map[wire.FilterType][]cfHeaderKV),
|
||||||
|
agentBlacklist: agentBlacklist,
|
||||||
|
agentWhitelist: agentWhitelist,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the transaction and address indexes if needed.
|
// Create the transaction and address indexes if needed.
|
||||||
|
@ -3133,3 +3159,47 @@ func mergeCheckpoints(defaultCheckpoints, additional []chaincfg.Checkpoint) []ch
|
||||||
sort.Sort(checkpointSorter(checkpoints))
|
sort.Sort(checkpointSorter(checkpoints))
|
||||||
return checkpoints
|
return checkpoints
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasUndesiredUserAgent determines whether the server should continue to pursue
|
||||||
|
// a connection with this peer based on its advertised user agent. It performs
|
||||||
|
// the following steps:
|
||||||
|
// 1) Reject the peer if it contains a blacklisted agent.
|
||||||
|
// 2) If no whitelist is provided, accept all user agents.
|
||||||
|
// 3) Accept the peer if it contains a whitelisted agent.
|
||||||
|
// 4) Reject all other peers.
|
||||||
|
func (sp *serverPeer) HasUndesiredUserAgent(blacklistedAgents,
|
||||||
|
whitelistedAgents []string) bool {
|
||||||
|
|
||||||
|
agent := sp.UserAgent()
|
||||||
|
|
||||||
|
// First, if peer's user agent contains any blacklisted substring, we
|
||||||
|
// will ignore the connection request.
|
||||||
|
for _, blacklistedAgent := range blacklistedAgents {
|
||||||
|
if strings.Contains(agent, blacklistedAgent) {
|
||||||
|
srvrLog.Debugf("Ignoring peer %s, user agent "+
|
||||||
|
"contains blacklisted user agent: %s", sp,
|
||||||
|
agent)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no whitelist is provided, we will accept all user agents.
|
||||||
|
if len(whitelistedAgents) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Peer's user agent passed blacklist. Now check to see if it contains
|
||||||
|
// one of our whitelisted user agents, if so accept.
|
||||||
|
for _, whitelistedAgent := range whitelistedAgents {
|
||||||
|
if strings.Contains(agent, whitelistedAgent) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, the peer's user agent was not included in our whitelist.
|
||||||
|
// Ignore just in case it could stall the initial block download.
|
||||||
|
srvrLog.Debugf("Ignoring peer %s, user agent: %s not found in "+
|
||||||
|
"whitelist", sp, agent)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue