public void TestOriginBlacklisting() { var key = GetRandomKey(); var ip = GetRandomIP(); var interval = TimeSpan.FromMinutes(1); Assert.AreEqual( false, Hacker.isOriginBlacklistedAsync(ip).Run(), "Origin must not be blacklisted"); var startTime = DateTime.Now; Hacker.BlacklistOriginAsync(ip, interval).Run(); Assert.AreEqual( true, Hacker.isOriginBlacklistedAsync(ip).Run(), "Origin must be blacklisted"); WaitForIntervalToElapse(interval, startTime); Assert.AreEqual( false, Hacker.isOriginBlacklistedAsync(ip).Run(), "Origin must not be blacklisted after expiration time"); }
public void TestOriginBlaclistingAndWhitelisting() { var ip = GetRandomIP(); var key = GetRandomKey(); Assert.AreEqual( Hacker.Result.Allowed, Hacker.DefendAsync(key, ip).Run(), string.Format("Allow traffic on {0} from {1}", key, ip)); Hacker.BlacklistOriginAsync(ip).Run(); Assert.AreEqual( Hacker.Result.OriginBlocked, Hacker.DefendAsync(key, ip).Run(), string.Format("Block traffic on {0} from {1}", key, ip)); Assert.AreEqual( Hacker.Result.OriginBlocked, Hacker.DefendAsync(GetRandomKey(), ip).Run(), string.Format("Allow any traffic from {1}", key, ip)); Hacker.WhitelistOriginAsync(ip).Run(); Assert.AreEqual( Hacker.Result.Allowed, Hacker.DefendAsync(key, ip).Run(), string.Format("Allow traffic on {0} from {1} after whitelist", key, ip)); }
public static async Task <Hacker.Result> DefendURL(HttpContext context) { Hacker.Result result = Hacker.Result.Allowed; Stopwatch watch = new Stopwatch(); watch.Start(); if (!Initialized) { lock (lockObject) { if (!Initialized) { Hacker.Logger = new TraceLogger(); Hacker.Logger.LogInformation(ClassName + ' ' + "Initialize"); Hacker.Store = new RedisDefenceStore(HackerSprayConfig.Settings.Redis, HackerSprayConfig.Settings.Prefix, Hacker.Config); Hacker.Logger.LogInformation(ClassName + ' ' + " Initialized"); Initialized = true; } } } // 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 = context.Request.GetClientIp(); 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) { Hacker.Logger.LogDebug(ClassName + ' ' + "Path matched: " + context.Request.Path); if (path.Mode == "key") { result = await Hacker.DefendAsync(context.Request.Path, originIP, path.Interval, path.MaxAttempts, TimeSpan.MaxValue, long.MaxValue, TimeSpan.MaxValue, long.MaxValue); if (result == Hacker.Result.TooManyHitsOnKey) { Hacker.Logger.LogInformation(ClassName + ' ' + "TooManyHitsOnKey Blacklist Path: " + context.Request.Path); await Hacker.BlacklistKeyAsync(path.Name, path.Interval); } } else if (path.Mode == "origin") { result = await Hacker.DefendAsync(context.Request.Path, originIP, TimeSpan.MaxValue, long.MaxValue, path.Interval, path.MaxAttempts, TimeSpan.MaxValue, long.MaxValue); if (result == Hacker.Result.TooManyHitsFromOrigin) { Hacker.Logger.LogInformation(ClassName + ' ' + "TooManyHitsFromOrigin Blacklist origin: " + originIP); await Hacker.BlacklistOriginAsync(originIP, path.Interval); } } else //(path.Mode == "key+origin") { result = await Hacker.DefendAsync(context.Request.Path, originIP, TimeSpan.MaxValue, long.MaxValue, TimeSpan.MaxValue, long.MaxValue, path.Interval, path.MaxAttempts); } break; } } watch.Stop(); Hacker.Logger.LogDebug(ClassName + ' ' + "DefendURL: " + context.Request.Path + " " + watch.ElapsedMilliseconds); return(result); }
public async Task Invoke(HttpContext context) { var path = context.Request.Path; Stopwatch watch = new Stopwatch(); watch.Start(); if (path.HasValue) { Debug("Defend Begin: " + path); // 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 = context.Connection.RemoteIpAddress; //if (context.Request.Headers.ContainsKey(XForwardedForHeader)) // originIP = IPAddress.Parse(context.Request.Headers[XForwardedForHeader]).MapToIPv4(); var result = Hacker.Result.Allowed; foreach (var key in _keys) { if (key.Method == context.Request.Method && key.Key == path) { Debug("Defend: " + path); if (key.Mode == HackerSprayOptionKey.HitCountMode.PerKey) { result = await Hacker.DefendAsync(path, originIP, key.Interval, key.MaxAttempts, TimeSpan.MaxValue, long.MaxValue, TimeSpan.MaxValue, long.MaxValue); if (result == Hacker.Result.TooManyHitsOnKey) { await Hacker.BlacklistKeyAsync(path, key.Interval); } } else if (key.Mode == HackerSprayOptionKey.HitCountMode.PerOrigin) { result = await Hacker.DefendAsync(path, originIP, TimeSpan.MaxValue, long.MaxValue, key.Interval, key.MaxAttempts, TimeSpan.MaxValue, long.MaxValue); if (result == Hacker.Result.TooManyHitsFromOrigin) { await Hacker.BlacklistOriginAsync(originIP, key.Interval); } } else //(key.Item5 == Mode.PerKeyOrigin) { result = await Hacker.DefendAsync(path, originIP, TimeSpan.MaxValue, long.MaxValue, TimeSpan.MaxValue, long.MaxValue, key.Interval, key.MaxAttempts); } Debug("Defend Result: " + Enum.GetName(typeof(Hacker.Result), result)); break; } } watch.Stop(); Debug("Defend End: " + path + " " + watch.ElapsedMilliseconds); if (result == Hacker.Result.Allowed) { await _next.Invoke(context); } else { Info("Blocked: " + path); context.Response.StatusCode = (int)HttpStatusCode.NotAcceptable; await context.Response.WriteAsync(Enum.GetName(typeof(Hacker.Result), result)); } //watch.Stop(); //Debug("Finished: " + path + " " + watch.ElapsedMilliseconds); } else { await _next.Invoke(context); } }
public void TestOriginRangeBlocking() { Hacker.ClearBlacklistsAsync().Run(); Hacker.ClearAllHitsAsync().Run(); var ipsInRange = new[] { IPAddress.Parse("10.10.10.10"), IPAddress.Parse("10.10.10.11"), IPAddress.Parse("10.10.254.254"), IPAddress.Parse("10.11.10.9"), IPAddress.Parse("10.11.10.10"), IPAddress.Parse("9.1.1.1"), IPAddress.Parse("9.1.1.10"), IPAddress.Parse("9.10.10.9"), IPAddress.Parse("10.11.10.12"), IPAddress.Parse("127.254.254.254"), IPAddress.Parse("100.100.100.100"), IPAddress.Parse("128.10.10.12"), IPAddress.Parse("128.10.10.254"), IPAddress.Parse("128.10.10.128"), }; var ipsOutofRange = new[] { IPAddress.Parse("10.10.10.9"), IPAddress.Parse("9.10.10.10"), IPAddress.Parse("10.11.10.11"), IPAddress.Parse("128.10.10.11"), IPAddress.Parse("200.200.200.200"), IPAddress.Parse("1.1.1.1"), IPAddress.Parse("10.0.0.0") }; Hacker.BlacklistOriginAsync(IPAddress.Parse("10.10.10.10"), IPAddress.Parse("10.11.10.10")).Run(); Hacker.BlacklistOriginAsync(IPAddress.Parse("9.1.1.1"), IPAddress.Parse("9.10.10.9")).Run(); Hacker.BlacklistOriginAsync(IPAddress.Parse("10.11.10.12"), IPAddress.Parse("127.254.254.254")).Run(); Hacker.BlacklistOriginAsync(IPAddress.Parse("128.10.10.12"), IPAddress.Parse("128.10.10.254")).Run(); Array.ForEach(ipsInRange, ip => Assert.AreEqual(Hacker.Result.OriginBlocked, Hacker.DefendAsync("TestOriginRangeBlocking", ip).Run(), ip.ToString() + " must be blocked.")); Hacker.ClearAllHitsAsync().Run(); Array.ForEach(ipsOutofRange, ip => Assert.AreEqual(Hacker.Result.Allowed, Hacker.DefendAsync("TestOriginRangeBlocking", ip).Run(), ip.ToString() + " must be allowed")); Hacker.WhitelistOriginAsync(IPAddress.Parse("9.1.1.1"), IPAddress.Parse("9.10.10.9")).Run(); Array.ForEach(new[] { IPAddress.Parse("9.1.1.1"), IPAddress.Parse("9.1.1.10"), IPAddress.Parse("9.10.10.9") }, ip => Assert.AreEqual(Hacker.Result.Allowed, Hacker.DefendAsync("TestOriginRangeBlocking", ip).Run(), ip.ToString() + " must be allowed")); Hacker.ClearBlacklistsAsync().Run(); Hacker.ClearAllHitsAsync().Run(); Array.ForEach(ipsInRange, ip => Assert.AreEqual(Hacker.Result.Allowed, Hacker.DefendAsync("TestOriginRangeBlocking", ip).Run(), ip.ToString() + " must be allowed when there's no blacklisting.")); Hacker.ClearAllHitsAsync().Run(); Array.ForEach(ipsOutofRange, ip => Assert.AreEqual(Hacker.Result.Allowed, Hacker.DefendAsync("TestOriginRangeBlocking", ip).Run(), ip.ToString() + " must be allowed when there's no blacklisting")); }