diff --git a/docs/conf/providers/dronebl.example.conf b/docs/conf/providers/dronebl.example.conf index 12c25fcda..5f3b289b1 100644 --- a/docs/conf/providers/dronebl.example.conf +++ b/docs/conf/providers/dronebl.example.conf @@ -8,4 +8,80 @@ records="3,5,6,7,8,9,10,11,13,14,15,16,17,19" action="zline" duration="7d" - reason="You are listed in DroneBL. Please visit https://dronebl.org/lookup.do?ip=%ip%&network=%network.url% for more information."> + reason="You are listed in DroneBL: %reason%. Please visit https://dronebl.org/lookup.do?ip=%ip%&network=%network.url% for more information."> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/conf/providers/efnet-rbl.example.conf b/docs/conf/providers/efnet-rbl.example.conf index 78dce53cb..0130951dc 100644 --- a/docs/conf/providers/efnet-rbl.example.conf +++ b/docs/conf/providers/efnet-rbl.example.conf @@ -8,4 +8,24 @@ records="1,2,3,4,5" action="zline" duration="7d" - reason="You are listed in the EFnet RBL. Please visit https://rbl.efnetrbl.org/?i=%ip% for more information."> + reason="You are listed in the EFnet RBL: %reason%. Please visit https://rbl.efnetrbl.org/?i=%ip% for more information."> + + + + + + + + + + diff --git a/docs/conf/providers/torexit.example.conf b/docs/conf/providers/torexit.example.conf index abc35c696..1be1a5b40 100644 --- a/docs/conf/providers/torexit.example.conf +++ b/docs/conf/providers/torexit.example.conf @@ -10,3 +10,7 @@ action="zline" duration="7d" reason="Tor exit nodes are not allowed on this network. See https://metrics.torproject.org/rs.html#search/%ip% for more information."> + + diff --git a/src/modules/m_dnsbl.cpp b/src/modules/m_dnsbl.cpp index 737ed2c62..bda050480 100644 --- a/src/modules/m_dnsbl.cpp +++ b/src/modules/m_dnsbl.cpp @@ -96,6 +96,9 @@ public: // A range of DNSBL result types to match against. CharState records; + // A map of DNSBL replies to their descriptions. + insp::flat_map replies; + // The message to send to users who's IP address is in a DNSBL. std::string reason; @@ -365,12 +368,16 @@ public: if (match) { + const auto it = config->replies.find(result); + const auto reasonstr = it == config->replies.end() ? INSP_FORMAT("Result {}", result) : it->second; + const std::string reason = Template::Replace(config->reason, { { "dnsbl", config->name }, { "dnsbl.url", Percent::Encode(config->name) }, { "ip", them->GetAddress() }, { "network", ServerInstance->Config->Network }, { "network.url", Percent::Encode(ServerInstance->Config->Network) }, + { "reason", reasonstr }, { "result", ConvToStr(result) }, }); @@ -421,9 +428,9 @@ public: } } - ServerInstance->SNO.WriteGlobalSno('d', "{} {} ({}) detected as being on the '{}' DNSBL with result {}{}", + ServerInstance->SNO.WriteGlobalSno('d', "{} {} ({}) detected as being on the '{}' DNSBL: {}{}", them->IsFullyConnected() ? "User" : "Connecting user", them->GetRealMask(), them->GetAddress(), - config->name, result, them->exempt ? " -- exempt" : ""); + config->name, reasonstr, them->exempt ? " -- exempt" : ""); } else config->stats_misses++; @@ -594,6 +601,30 @@ public: auto entry = std::make_shared(this, tag); newdnsbls.push_back(entry); } + for (const auto& [_, tag] : ServerInstance->Config->ConfTags("dnsblreply")) + { + const auto dnsblname = tag->getString("name"); + auto dnsbl = std::find_if(newdnsbls.begin(), newdnsbls.end(), [&dnsblname](const auto& d) + { + return insp::equalsci(d->name, dnsblname); + }); + if (dnsbl == newdnsbls.end()) + throw ModuleException(this, " must be set to the name of a DNSBL at " + tag->source.str()); + + const auto dnsbldesc = tag->getString("description"); + if (dnsbldesc.empty()) + throw ModuleException(this, " must not be empty at " + tag->source.str()); + + const auto dnsblreply = tag->getNum("reply", std::numeric_limits::max()); + if (dnsblreply > 16'777'215) + { + throw ModuleException(this, INSP_FORMAT(" ({}) is not a valid DNSBL reply at {}", + dnsblreply, tag->source.str())); + } + + (*dnsbl)->replies[dnsblreply] = dnsbldesc; + } + data.dnsbls.swap(newdnsbls); }