Skip to content

Commit

Permalink
server: adds hybrid black/whitelist filtering to user agents
Browse files Browse the repository at this point in the history
  • Loading branch information
cfromknecht committed Mar 23, 2018
1 parent 80c6d56 commit 8ae4322
Showing 1 changed file with 67 additions and 1 deletion.
68 changes: 67 additions & 1 deletion server.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,14 @@ type server struct {
// The fee estimator keeps track of how long transactions are left in
// the mempool before they are mined into blocks.
feeEstimator *mempool.FeeEstimator

// 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
Expand Down Expand Up @@ -1368,6 +1376,12 @@ func (s *server) handleAddPeerMsg(state *peerState, sp *serverPeer) bool {
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.
if atomic.LoadInt32(&s.shutdown) != 0 {
srvrLog.Infof("New peer %s ignored - server is shutting down", sp)
Expand Down Expand Up @@ -2319,7 +2333,10 @@ func setupRPCListeners() ([]net.Listener, error) {
// newServer returns a new btcd server configured to listen on addr for the
// bitcoin network type specified by chainParams. Use start to begin accepting
// 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
if cfg.NoPeerBloomFilters {
services &^= wire.SFNodeBloom
Expand All @@ -2343,6 +2360,9 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
}
}

srvrLog.Infof("Using agent blacklist: %s and whitelist: %s",
agentBlacklist, agentWhitelist)

s := server{
chainParams: chainParams,
addrManager: amgr,
Expand All @@ -2361,6 +2381,8 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
services: services,
sigCache: txscript.NewSigCache(cfg.SigCacheMaxSize),
hashCache: txscript.NewHashCache(cfg.SigCacheMaxSize),
agentBlacklist: agentBlacklist,
agentWhitelist: agentWhitelist,
}

// Create the transaction and address indexes if needed.
Expand Down Expand Up @@ -2913,3 +2935,47 @@ func mergeCheckpoints(defaultCheckpoints, additional []chaincfg.Checkpoint) []ch
sort.Sort(checkpointSorter(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
}

0 comments on commit 8ae4322

Please sign in to comment.