public void TestKeyBlacklistingAndWhitelisting() { var ip = GetRandomIP(); var key = GetRandomKey(); Assert.AreEqual( HackerSprayer.Result.Allowed, HackerSprayer.DefendAsync(key, ip).Run(), string.Format("Allow traffic on {0} from {1}", key, ip)); HackerSprayer.BlacklistKeyAsync(key, TimeSpan.FromMinutes(5)).Run(); Assert.AreEqual( HackerSprayer.Result.KeyBlocked, HackerSprayer.DefendAsync(key, ip).Run(), string.Format("Block traffic on {0} from {1}", key, ip)); Assert.AreEqual( HackerSprayer.Result.KeyBlocked, HackerSprayer.DefendAsync(key, GetRandomIP()).Run(), string.Format("Allow any traffic from {1}", key, ip)); HackerSprayer.WhitelistKeyAsync(key).Run(); Assert.AreEqual( HackerSprayer.Result.Allowed, HackerSprayer.DefendAsync(key, ip).Run(), string.Format("Allow traffic on {0} from {1} after whitelist", key, ip)); }
public void TestKeyBlacklisting() { var key = GetRandomKey(); var ip = GetRandomIP(); var interval = TimeSpan.FromMinutes(1); Assert.AreEqual( false, HackerSprayer.IsKeyBlacklistedAsync(key).Run(), "Key must not be blacklisted"); var startTime = DateTime.Now; HackerSprayer.BlacklistKeyAsync(key, interval).Run(); Assert.AreEqual( true, HackerSprayer.IsKeyBlacklistedAsync(key).Run(), "Key must be blacklisted"); string [] blacklistedKeys = HackerSprayer.GetKeyBlacklists().Run(); Assert.IsTrue(Array.Exists(blacklistedKeys, k => k == key), "Key must be in the blacklist"); WaitForIntervalToElapse(interval, startTime); Assert.AreEqual( false, HackerSprayer.IsKeyBlacklistedAsync(key).Run(), "Key must not be blacklisted after expiration time"); }
public static async Task <HackerSprayer.Result> DefendURL(HttpContext context) { HackerSprayer.Result result = HackerSprayer.Result.Allowed; if (!Initialized) { lock (lockObject) { if (!Initialized) { Initialized = true; HackerSprayer.Store = new RedisDefenceStore(HackerSprayConfig.Settings.Redis, HackerSprayConfig.Settings.Prefix, HackerSprayer.Config); } } } // This handles load balancers passing the original client IP // through this header. // WARNING: If your load balancer is not passing original client IP // through this header, then you will be blocking your load balancer, // causing a total outage. Also ensure this Header cannot be spoofed. // Your load balancer should be configured in a way that it does not accept // this header from the request, instead it always sets it itself. var originIP = IPAddress.Parse(context.Request.Headers["X-Forward-For"] ?? context.Request.UserHostAddress).MapToIPv4(); foreach (var path in HackerSprayConfig.Settings.Paths) { if ((path.Post && context.Request.HttpMethod == "POST") || (!path.Post && context.Request.HttpMethod == "GET") && path.Name == context.Request.Path) { if (path.Mode == "perkey") { result = await HackerSprayer.DefendAsync(context.Request.Path, originIP, path.Interval, path.MaxAttempts, TimeSpan.MaxValue, long.MaxValue, TimeSpan.MaxValue, long.MaxValue); } else if (path.Mode == "perorigin") { result = await HackerSprayer.DefendAsync(context.Request.Path, originIP, TimeSpan.MaxValue, long.MaxValue, path.Interval, path.MaxAttempts, TimeSpan.MaxValue, long.MaxValue); } else //(path.Mode == "perkeyorigin") { result = await HackerSprayer.DefendAsync(context.Request.Path, originIP, TimeSpan.MaxValue, long.MaxValue, TimeSpan.MaxValue, long.MaxValue, path.Interval, path.MaxAttempts); } // Blacklist origin. After that, it becomes least expensive to block requests if (result == HackerSprayer.Result.TooManyHitsFromOrigin) { await HackerSprayer.BlacklistOriginAsync(originIP, path.Interval); } else if (result == HackerSprayer.Result.TooManyHitsOnKey) { await HackerSprayer.BlacklistKeyAsync(path.Name, path.Interval); } //else if (result == HackerSprayer.Result.TooManyHitsOnKeyFromOrigin) // There is nothing for that, because we neither want to block the key for all ip, // nor do we want to block the ip for all key. It just has to be checked each // and every time. Thus this is the most expensive check. break; } } return(result); }