Add FINGER_BAN_ALLOWLIST to exempt trusted front-end IPs from banning
CI / Build and Test (gcc, g++, ubuntu-latest) (push) Failing after 5m2s
CI / Code Coverage (push) Skipped
Build and Publish Docker Image / build-and-test (push) Failing after 6m13s
Build and Publish Docker Image / build-and-push-image (push) Skipped
Build and Publish Docker Image / security-scan (push) Skipped
CI / Build and Test (gcc, g++, ubuntu-latest) (push) Failing after 5m2s
CI / Code Coverage (push) Skipped
Build and Publish Docker Image / build-and-test (push) Failing after 6m13s
Build and Publish Docker Image / build-and-push-image (push) Skipped
Build and Publish Docker Image / security-scan (push) Skipped
The per-IP ban tracker treats every globally-routable client equally, but an aggregating front-end like the finger-web proxy funnels the whole internet's federated lookups through a single IP. A burst from any one client of the proxy (or a load test) is then attributed to the proxy's IP and, once it crosses the failure threshold, the daemon blocks the proxy — taking out finger lookups for everyone. Per-client abuse protection for the proxied path belongs in the proxy (which now rate-limits per real client IP), so the daemon should trust it. Add a FINGER_BAN_ALLOWLIST env var (comma-separated IPs). Allowlisted addresses are marked non-trackable in the listener, so their connections are never blocked and never recorded as offenses. Unset = unchanged behaviour. - parse_ip_allowlist() in ban.cpp (trims entries, skips blanks) + unit tests - listener() consults the set when computing 'trackable' - documented in docker-compose.yml and DOCKER.md
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include "ban.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
bool is_bannable_address(const boost::asio::ip::address &addr) {
|
||||
if (addr.is_loopback() || addr.is_unspecified() || addr.is_multicast()) {
|
||||
@@ -28,6 +29,27 @@ bool is_bannable_address(const boost::asio::ip::address &addr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unordered_set<std::string> parse_ip_allowlist(std::string_view csv) {
|
||||
std::unordered_set<std::string> out;
|
||||
std::size_t start = 0;
|
||||
while (start <= csv.size()) {
|
||||
const std::size_t comma = csv.find(',', start);
|
||||
const std::size_t end =
|
||||
(comma == std::string_view::npos) ? csv.size() : comma;
|
||||
std::string_view tok = csv.substr(start, end - start);
|
||||
const std::size_t a = tok.find_first_not_of(" \t\r\n");
|
||||
if (a != std::string_view::npos) {
|
||||
const std::size_t b = tok.find_last_not_of(" \t\r\n");
|
||||
out.emplace(tok.substr(a, b - a + 1));
|
||||
}
|
||||
if (comma == std::string_view::npos) {
|
||||
break;
|
||||
}
|
||||
start = comma + 1;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Count timestamps that fall within (now - window, now]. The deque is kept in
|
||||
// ascending order, so the in-window entries are always a suffix.
|
||||
|
||||
Reference in New Issue
Block a user