@@ -18,7 +18,13 @@ public class ReportInfo
1818public static class BadActor
1919{
2020 private static readonly IMemoryCache IpCache = new MemoryCache ( new MemoryCacheOptions ( ) ) ;
21- private static readonly TimeSpan CacheDuration = TimeSpan . FromMinutes ( 10 ) ;
21+
22+ // Good actors: cache “clean” for 30 days
23+ private static readonly TimeSpan CacheDurationGoodActor = TimeSpan . FromDays ( 30 ) ;
24+ // Bad actors: re-check every 5 days so reputation/ownership can change
25+ private static readonly TimeSpan CacheDurationBadActor = TimeSpan . FromDays ( 5 ) ;
26+ // AbuseIPDB API is down or unreachable
27+ private static readonly TimeSpan CacheDurationFailure = TimeSpan . FromMinutes ( 10 ) ;
2228
2329 private static readonly ConcurrentQueue < ReportInfo > RetryQueue = [ ] ;
2430 private static bool _isProcessingQueue ;
@@ -39,8 +45,13 @@ private readonly struct IpCacheEntry
3945
4046 public static async Task < bool > ClientOnBlackListAsync ( string remoteIp )
4147 {
48+ // Malformed / empty IPs are always blocked
4249 if ( string . IsNullOrWhiteSpace ( remoteIp ) || ! IPAddress . TryParse ( remoteIp , out _ ) ) return true ;
50+
51+ // Localhost and internal IPs are never blocked
4352 if ( remoteIp is "127.0.0.1" or InternalIp ) return false ;
53+
54+ // Is the IP cached? Return the cached result
4455 if ( IpCache . TryGetValue ( remoteIp , out IpCacheEntry entry ) ) return entry . IsBlocked ;
4556
4657 try
@@ -75,13 +86,14 @@ public static async Task<bool> ClientOnBlackListAsync(string remoteIp)
7586 var isDisallowed = IsDisallowedUsageType ( usageType ) ;
7687 var isVpnBot = IsVpnBotUsageType ( usageType ) && abuseScore >= 3 ;
7788
78- // Block disallowed, no need to report
89+ // 1) Hard- disallowed: IPv6, non-public, disallowed usage, or blacklisted ISP
7990 if ( ipVersion == 6 || isPublic == false || isDisallowed || IsBlackListed ( isp ) )
8091 {
81- IpCache . Set ( remoteIp , new IpCacheEntry { IsBlocked = true } , CacheDuration ) ;
92+ IpCache . Set ( remoteIp , new IpCacheEntry { IsBlocked = true } , CacheDurationBadActor ) ;
8293 return true ;
8394 }
8495
96+ // 2) VPN / data-center with bad abuse score
8597 if ( isVpnBot )
8698 {
8799 shouldBlock = true ;
@@ -90,6 +102,7 @@ public static async Task<bool> ClientOnBlackListAsync(string remoteIp)
90102 shouldBlock = false ;
91103 }
92104
105+ // 3) General abuse / TOR handling
93106 if ( isBlocked )
94107 {
95108 shouldBlock = true ;
@@ -107,7 +120,10 @@ public static async Task<bool> ClientOnBlackListAsync(string remoteIp)
107120 }
108121 }
109122
110- IpCache . Set ( remoteIp , new IpCacheEntry { IsBlocked = shouldBlock } , CacheDuration ) ;
123+ // 4) Cache result with different TTLs for good vs bad actors
124+ var ttl = shouldBlock ? CacheDurationBadActor : CacheDurationGoodActor ;
125+
126+ IpCache . Set ( remoteIp , new IpCacheEntry { IsBlocked = shouldBlock } , ttl ) ;
111127 return shouldBlock ;
112128 }
113129
@@ -119,7 +135,8 @@ public static async Task<bool> ClientOnBlackListAsync(string remoteIp)
119135 SentrySdk . CaptureException ( ex ) ;
120136 }
121137
122- IpCache . Set ( remoteIp , new IpCacheEntry { IsBlocked = false } , TimeSpan . FromMinutes ( 1 ) ) ;
138+ // Fallback: API failure / unexpected flow -> treat as not blocked, but cache briefly
139+ IpCache . Set ( remoteIp , new IpCacheEntry { IsBlocked = false } , CacheDurationFailure ) ;
123140 return false ;
124141 }
125142
0 commit comments