diff --git a/src/network/connectionthreads.cpp b/src/network/connectionthreads.cpp index d99169160ead..03771b33f158 100644 --- a/src/network/connectionthreads.cpp +++ b/src/network/connectionthreads.cpp @@ -44,6 +44,8 @@ namespace con // TODO: Clean this up. #define LOG(a) a +#define MAX_NEW_PEERS_PER_SEC 30 + static inline session_t readPeerId(const u8 *packetdata) { return readU16(&packetdata[4]); @@ -971,7 +973,19 @@ void ConnectionReceiveThread::receive(SharedBuffer &packetdata, // Someone new is trying to talk to us. Add them. if (peer_id == PEER_ID_INEXISTENT) { - peer_id = m_connection->createPeer(sender, MTP_MINETEST_RELIABLE_UDP, 0); + auto &l = m_new_peer_ratelimit; + l.tick(); + if (++l.counter > MAX_NEW_PEERS_PER_SEC) { + if (!l.logged) { + warningstream << m_connection->getDesc() + << "Receive(): More than " << MAX_NEW_PEERS_PER_SEC + << " new clients within 1s. Throttling." << std::endl; + } + l.logged = true; + // We simply drop the packet, the client can try again. + } else { + peer_id = m_connection->createPeer(sender, MTP_MINETEST_RELIABLE_UDP, 0); + } } } diff --git a/src/network/connectionthreads.h b/src/network/connectionthreads.h index 3ba45b3b8e4c..7e0d44373fa9 100644 --- a/src/network/connectionthreads.h +++ b/src/network/connectionthreads.h @@ -162,8 +162,25 @@ class ConnectionReceiveThread : public Thread bool reliable); }; + struct RateLimitHelper { + u64 time = 0; + int counter = 0; + bool logged = false; + + void tick() { + u64 now = porting::getTimeS(); + if (time != now) { + time = now; + counter = 0; + logged = false; + } + } + }; + static const PacketTypeHandler packetTypeRouter[PACKET_TYPE_MAX]; Connection *m_connection = nullptr; + + RateLimitHelper m_new_peer_ratelimit; }; }