mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-08-28 17:01:16 +00:00
Update blocking of abusive services
This commit is contained in:
@@ -109,6 +109,10 @@ CLOUDFLARE_IPS_RETRY_SLEEP_MS=250
|
||||
CLOUDFLARE_IPS_STORAGE_PATH=storage/app/cloudflare/trusted-proxies.json
|
||||
CLOUDFLARE_TRUST_REMOTE_ADDR_FALLBACK=true
|
||||
|
||||
# Block configured indexer apps only when they proxy NZB downloads instead of redirecting to the downloader.
|
||||
BLOCK_PROXY_INDEXER_APPS=false
|
||||
BLOCK_PROXY_INDEXER_APP_USER_AGENTS=Prowlarr/,NZBHydra2
|
||||
|
||||
APP_LOCALE=en
|
||||
APP_FALLBACK_LOCALE=en
|
||||
APP_FAKER_LOCALE=en_US
|
||||
|
||||
@@ -17,6 +17,7 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
* Blocks:
|
||||
* - AIOStreams (User-Agent based)
|
||||
* - UsenetStreamer (User-Agent based)
|
||||
* - Configured indexer apps on public indexer API/RSS endpoints (User-Agent based, opt-in)
|
||||
* - Oracle Cloud (ASN: AS31898)
|
||||
* - Cloudflare WARP (ASN: AS13335)
|
||||
*/
|
||||
@@ -71,6 +72,16 @@ class BlockAbusiveServices
|
||||
return $this->blockedResponse('Access denied: Streaming services are not allowed.');
|
||||
}
|
||||
|
||||
if ($this->shouldBlockProxyIndexerApp($request, $userAgent)) {
|
||||
Log::warning('Blocked proxy indexer app request', [
|
||||
'ip' => $ip,
|
||||
'user_agent' => $userAgent,
|
||||
'uri' => $request->getRequestUri(),
|
||||
]);
|
||||
|
||||
return $this->blockedResponse('Access denied: Proxy indexer app access is not allowed.');
|
||||
}
|
||||
|
||||
// Check for blocked ASNs
|
||||
$asnInfo = $this->getAsnInfo($ip);
|
||||
if ($asnInfo !== null && isset($this->blockedAsns[$asnInfo['asn']])) {
|
||||
@@ -107,6 +118,78 @@ class BlockAbusiveServices
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether an opt-in proxy indexer app block should apply.
|
||||
*/
|
||||
protected function shouldBlockProxyIndexerApp(Request $request, string $userAgent): bool
|
||||
{
|
||||
if (! (bool) config('nntmux.block_proxy_indexer_apps', false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $this->isPublicIndexerEndpoint($request)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->matchesAnyUserAgentPattern(
|
||||
$userAgent,
|
||||
$this->configuredProxyIndexerAppUserAgents()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect public indexer API/RSS endpoints while leaving unrelated requests alone.
|
||||
*/
|
||||
protected function isPublicIndexerEndpoint(Request $request): bool
|
||||
{
|
||||
if ($request->is('api/v1/api') || $request->is('api/v2/*')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $request->is('rss/*') && ! $request->is('rss/health');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, string>
|
||||
*/
|
||||
protected function configuredProxyIndexerAppUserAgents(): array
|
||||
{
|
||||
$configured = config('nntmux.block_proxy_indexer_app_user_agents', []);
|
||||
|
||||
if (is_string($configured)) {
|
||||
$configured = preg_split('/[\r\n,]+/', $configured) ?: [];
|
||||
}
|
||||
|
||||
if (! is_array($configured)) {
|
||||
Log::warning('Ignoring invalid proxy indexer app User-Agent configuration.', [
|
||||
'configured_type' => get_debug_type($configured),
|
||||
]);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_values(array_filter(array_map(
|
||||
static fn (mixed $pattern): string => is_string($pattern) ? trim($pattern) : '',
|
||||
$configured,
|
||||
)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, string> $patterns
|
||||
*/
|
||||
protected function matchesAnyUserAgentPattern(string $userAgent, array $patterns): bool
|
||||
{
|
||||
$lowerUserAgent = strtolower($userAgent);
|
||||
|
||||
foreach ($patterns as $pattern) {
|
||||
if (str_contains($lowerUserAgent, strtolower($pattern))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ASN information for an IP address.
|
||||
* Uses ip-api.com with caching to minimize API calls.
|
||||
|
||||
@@ -21,6 +21,8 @@ return [
|
||||
'purge_inactive_users' => env('PURGE_INACTIVE_USERS', false),
|
||||
'purge_inactive_users_days' => env('PURGE_INACTIVE_USERS_DAYS', 180),
|
||||
'mysql_search_fallback' => env('MYSQL_SEARCH_FALLBACK', false), // Disable MySQL LIKE fallback when Manticore/Elasticsearch return no results
|
||||
'block_proxy_indexer_apps' => (bool) env('BLOCK_PROXY_INDEXER_APPS', false),
|
||||
'block_proxy_indexer_app_user_agents' => env('BLOCK_PROXY_INDEXER_APP_USER_AGENTS', 'Prowlarr/,NZBHydra2'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user