client.go | 2 +- dht/announce.go | 14 ++++++++++++++ dht/dht.go | 14 ++++++++++++++ diff --git a/client.go b/client.go index 465f10629d82698a3a9e7d2679266537ddd20c2e..dc5b66fd921b1ad7340a08e8a0fe7c995b9312f0 100644 --- a/client.go +++ b/client.go @@ -226,7 +226,7 @@ } fmt.Fprintf(w, "Peer ID: %+q\n", cl.peerID) if cl.dHT != nil { dhtStats := cl.dHT.Stats() - fmt.Fprintf(w, "DHT nodes: %d (%d good)\n", dhtStats.Nodes, dhtStats.GoodNodes) + fmt.Fprintf(w, "DHT nodes: %d (%d good, %d banned)\n", dhtStats.Nodes, dhtStats.GoodNodes, dhtStats.BadNodes) fmt.Fprintf(w, "DHT Server ID: %x\n", cl.dHT.ID()) fmt.Fprintf(w, "DHT port: %d\n", addrPort(cl.dHT.Addr())) fmt.Fprintf(w, "DHT announces: %d\n", dhtStats.ConfirmedAnnounces) diff --git a/dht/announce.go b/dht/announce.go index 75a9558e643779cafc4986faa547de335ba02c7e..3b9dc32f3e0fad94eaedf3d5900f5acf4d6b16d1 100644 --- a/dht/announce.go +++ b/dht/announce.go @@ -108,6 +108,12 @@ } if me.server.ipBlocked(addr.UDPAddr().IP) { return } + me.server.mu.Lock() + if me.server.badNodes.Test([]byte(addr.String())) { + me.server.mu.Unlock() + return + } + me.server.mu.Unlock() me.contact(addr) } @@ -162,6 +168,14 @@ } me.mu.Unlock() if vs := m.Values(); vs != nil { + for _, cp := range vs { + if cp.Port == 0 { + me.server.mu.Lock() + me.server.badNode(addr) + me.server.mu.Unlock() + return + } + } nodeInfo := NodeInfo{ Addr: t.remoteAddr, } diff --git a/dht/dht.go b/dht/dht.go index ed544f6066163216b9bca3497cf78682f76c96e7..5db6adb4c236d3e44811d2d29b46b6ef29fecd0e 100644 --- a/dht/dht.go +++ b/dht/dht.go @@ -22,6 +22,7 @@ "time" "github.com/anacrolix/missinggo" "github.com/anacrolix/sync" + "github.com/tylertreat/BoomFilters" "github.com/anacrolix/torrent/bencode" "github.com/anacrolix/torrent/iplist" @@ -50,6 +51,7 @@ mu sync.Mutex closed chan struct{} passive bool // Don't respond to queries. ipBlockList *iplist.IPList + badNodes *boom.BloomFilter numConfirmedAnnounces int bootstrapNodes []string @@ -81,6 +83,8 @@ // Transactions awaiting a response. OutstandingTransactions int // Individual announce_peer requests that got a success response. ConfirmedAnnounces int + // Nodes that have been blocked. + BadNodes uint } // Returns statistics for the server. @@ -95,6 +99,7 @@ } ss.Nodes = len(s.nodes) ss.OutstandingTransactions = len(s.transactions) ss.ConfirmedAnnounces = s.numConfirmedAnnounces + ss.BadNodes = s.badNodes.Count() return } @@ -121,6 +126,7 @@ } s = &Server{ config: *c, ipBlockList: c.IPBlocklist, + badNodes: boom.NewBloomFilter(1000, 0.1), } if c.Conn != nil { s.socket = c.Conn @@ -790,6 +796,9 @@ } if !s.config.NoSecurity && !n.IsSecure() { return } + if s.badNodes.Test([]byte(addrStr)) { + return + } s.nodes[addrStr] = n return } @@ -1214,3 +1223,8 @@ ret = append(ret, idNodes[id.ByteString()]) } return ret } + +func (me *Server) badNode(addr dHTAddr) { + me.badNodes.Add([]byte(addr.String())) + delete(me.nodes, addr.String()) +}