Пример #1
0
        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");
        }
Пример #2
0
        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));
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
            }
        }
Пример #5
0
        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"));
        }