diff --git a/libtransmission/handshake.cc b/libtransmission/handshake.cc index 6be04586c..8cbaf6edf 100644 --- a/libtransmission/handshake.cc +++ b/libtransmission/handshake.cc @@ -20,6 +20,7 @@ #include "handshake.h" #include "log.h" #include "peer-io.h" +#include "peer-mgr.h" #include "timer.h" #include "tr-assert.h" #include "tr-buffer.h" @@ -110,6 +111,9 @@ tr_handshake::ParseResult tr_handshake::parse_handshake(tr_peerIo* peer_io) return ParseResult::PeerIsSelf; } + /* bans leetch-only clients */ + if (tr_peerMgrClientIsBanned(peer_id)) return ParseResult::PeerIsLeetcher; + return ParseResult::Ok; } diff --git a/libtransmission/handshake.h b/libtransmission/handshake.h index c9b6582c4..2d0769b1e 100644 --- a/libtransmission/handshake.h +++ b/libtransmission/handshake.h @@ -80,6 +80,7 @@ private: EncryptionWrong, BadTorrent, PeerIsSelf, + PeerIsLeetcher, }; enum class State diff --git a/libtransmission/peer-mgr.cc b/libtransmission/peer-mgr.cc index f17577647..aa8df86a9 100644 --- a/libtransmission/peer-mgr.cc +++ b/libtransmission/peer-mgr.cc @@ -968,6 +968,22 @@ void tr_peerMgrPieceCompleted(tr_torrent* tor, tr_piece_index_t p) tor->set_needs_completeness_check(); } +bool tr_peerMgrClientIsBanned(const tr_peer_id_t& peer_id_arr) +{ + const char* peer_id = peer_id_arr.data(); + bool banned = peer_id_arr.empty(); + // Names like '-XL0012-','-DL3760-', '-FD51YC-', etc. + banned |= !memcmp(peer_id+1, "SD", 2); + banned |= !memcmp(peer_id+1, "XL", 2); + banned |= !memcmp(peer_id+1, "QD", 2); + banned |= !memcmp(peer_id+1, "XF", 2); + banned |= !memcmp(peer_id+1, "BN", 2); + banned |= !memcmp(peer_id, "Xunlei", 6); + banned |= !memcmp(peer_id, "Thunder", 7); + banned |= !memcmp(peer_id, "QQDownload", 10); + return banned; +} + namespace { namespace handshake_helpers @@ -1069,6 +1085,10 @@ void create_bit_torrent_peer(tr_torrent* tor, std::shared_ptr io, str { tr_logAddTraceSwarm(s, fmt::format("banned peer {} tried to reconnect", atom->display_name())); } + else if (!result.peer_id.has_value() || tr_peerMgrClientIsBanned(result.peer_id.value())) + { + tr_logAddDebugSwarm(s, fmt::format("banned leetch-only peer {} tried to reconnect", atom->display_name())); + } else if (result.io->is_incoming() && s->peerCount() >= s->tor->peerLimit()) { /* too many peers already */ diff --git a/libtransmission/peer-mgr.h b/libtransmission/peer-mgr.h index 4566e685b..25d106b33 100644 --- a/libtransmission/peer-mgr.h +++ b/libtransmission/peer-mgr.h @@ -222,4 +222,7 @@ void tr_peerMgrGotBadPiece(tr_torrent* tor, tr_piece_index_t piece_index); void tr_peerMgrPieceCompleted(tr_torrent* tor, tr_piece_index_t pieceIndex); +/* Check if the client is banned. XunLei is banned because it is leetch-only (never uploads). */ +bool tr_peerMgrClientIsBanned(const tr_peer_id_t& peer_id); + /* @} */