Rate limit incoming addr p2p messages
This commit is contained in:
34
src/main.cpp
34
src/main.cpp
@@ -6997,6 +6997,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||
{
|
||||
pfrom->PushMessage(NetMsgType::GETADDR);
|
||||
pfrom->fGetAddr = true;
|
||||
// pfrom->m_getaddr_sent = true;
|
||||
// When requesting a getaddr, accept an additional MAX_ADDR_TO_SEND addresses in response
|
||||
// (bypassing the MAX_ADDR_PROCESSING_TOKEN_BUCKET limit).
|
||||
pfrom->m_addr_token_bucket += MAX_ADDR_TO_SEND;
|
||||
}
|
||||
addrman.Good(pfrom->addr);
|
||||
} else {
|
||||
@@ -7100,15 +7104,36 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||
vector<CAddress> vAddrOk;
|
||||
int64_t nNow = GetTime();
|
||||
int64_t nSince = nNow - 10 * 60;
|
||||
|
||||
// Update/increment addr rate limiting bucket.
|
||||
const int64_t current_time = GetTimeMicros();
|
||||
if (pfrom->m_addr_token_bucket < MAX_ADDR_PROCESSING_TOKEN_BUCKET) {
|
||||
// Don't increment bucket if it's already full
|
||||
const auto time_diff = std::max(current_time - pfrom->m_addr_token_timestamp, (int64_t) 0);
|
||||
const double increment = (time_diff / 1000000) * MAX_ADDR_RATE_PER_SECOND;
|
||||
pfrom->m_addr_token_bucket = std::min<double>(pfrom->m_addr_token_bucket + increment, MAX_ADDR_PROCESSING_TOKEN_BUCKET);
|
||||
}
|
||||
pfrom->m_addr_token_timestamp = current_time;
|
||||
|
||||
uint64_t num_proc = 0;
|
||||
uint64_t num_rate_limit = 0;
|
||||
|
||||
BOOST_FOREACH(CAddress& addr, vAddr)
|
||||
{
|
||||
boost::this_thread::interruption_point();
|
||||
// Apply rate limiting if the address is not allowlisted
|
||||
if (!pfrom->IsAllowlistedRange(addr)) {
|
||||
if (pfrom->m_addr_token_bucket < 1.0) break;
|
||||
pfrom->m_addr_token_bucket -= 1.0;
|
||||
}
|
||||
|
||||
if(p2pdebug)
|
||||
fprintf(stderr,"%s: %s.nTime=%d\n", __func__, addr.ToString().c_str(), addr.nTime);
|
||||
|
||||
if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60)
|
||||
addr.nTime = nNow - 5 * 24 * 60 * 60;
|
||||
pfrom->AddAddressKnown(addr);
|
||||
++num_proc;
|
||||
bool fReachable = IsReachable(addr);
|
||||
if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
|
||||
{
|
||||
@@ -7147,6 +7172,15 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||
fprintf(stderr,"%s: %s with nTime=%d is not reachable\n",__func__,addr.ToString().c_str(), addr.nTime);
|
||||
}
|
||||
}
|
||||
pfrom->m_addr_processed += num_proc;
|
||||
pfrom->m_addr_rate_limited += num_rate_limit;
|
||||
LogPrintf("ProcessMessage: Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d%s\n",
|
||||
vAddr.size(),
|
||||
num_proc,
|
||||
num_rate_limit,
|
||||
pfrom->GetId(),
|
||||
fLogIPs ? ", peeraddr=" + pfrom->addr.ToString() : "");
|
||||
|
||||
addrman.Add(vAddrOk, pfrom->addr, 2 * 60 * 60);
|
||||
if (vAddr.size() < 1000)
|
||||
pfrom->fGetAddr = false;
|
||||
|
||||
Reference in New Issue
Block a user