Example #1
0
        public void TestWhitelistDns()
        {
            IPBanConfig config = IPBanConfig.LoadFromXml("<?xml version='1.0'?><configuration>" +
                                                         "<appSettings><add key='Whitelist' value='test.com' /></appSettings></configuration>",
                                                         this);

            Assert.IsTrue(config.IsWhitelisted("99.88.77.66"));
            Assert.IsFalse(config.IsBlackListed("99.88.77.66"));
        }
Example #2
0
        public void TestUserNameWhitelistBan()
        {
            using IPBanConfig.TempConfigChanger configChanger = new IPBanConfig.TempConfigChanger(service, xml =>
            {
                return(IPBanConfig.ChangeConfigAppSetting(xml, "UserNameWhitelist", "OnlyMe"));
            }, out string newConfig);

            // TODO: ensure non OnlyMe users are banned immediately
            // TODO: ensure OnlyMe user gets 20 failed logins before ban
        }
Example #3
0
        public void TestListComments()
        {
            IPBanConfig config = IPBanConfig.LoadFromXml("<?xml version='1.0'?><configuration>" +
                                                         "<appSettings><add key='Whitelist' value='99.99.99.99?TestIP?2020-05-25," +
                                                         "88.88.88.88?TestIP2?2020-05-24' /></appSettings></configuration>",
                                                         DefaultDnsLookup.Instance);

            Assert.AreEqual(string.Join(",", config.Whitelist.OrderBy(i => i)), "88.88.88.88,99.99.99.99");
            Assert.IsTrue(config.IsWhitelisted("99.99.99.99"));
            Assert.IsTrue(config.IsWhitelisted("88.88.88.88"));
            Assert.IsFalse(config.IsWhitelisted("77.77.77.77"));
        }
Example #4
0
        private void AssertLogFilesToParse(IPBanConfig cfg)
        {
            const int maxFileSize  = 16777216;
            const int pingInterval = 10000;

            // path and mask, fail expression, success expression, platform regex, recursive, source
            object[] logFileData = new object[]
            {
                "/var/log/auth*.log\n/var/log/secure*",
                @"failed\s+password\s+for\s+(invalid\s+user\s+)?(?<username>.+?\s+)from\s+(?<ipaddress>.+?)\s+port\s+[0-9]+\s+ssh|did\s+not\s+receive\s+identification\s+string\s+from\s+(?<ipaddress>[^\s]+)|connection\s+closed\s+by\s+(invalid\s+user\s+)?(?<username>.+?\s+)?(?<ipaddress>.+?)\s+port\s+[0-9]+\s+\[preauth\]\s*(\(no\s+attempt\s+to\s+login\s+after\s+timeout\))?|disconnected\s+from\s+(invalid\s+user\s+)?(?<username>.+?)\s+(?<ipaddress>.+?)\s+port\s+[0-9]+\s+\[preauth\]|disconnected\s+from\s+(?<ipaddress>.+?)\s+port\s+[0-9]+\s+\[preauth\]|disconnected\s+from\s+authenticating\s+user\s+(?<username>.+?)\s+(?<ipaddress>.+?)\s+port\s+[0-9]+\s+\[preauth\]",
                @"Accepted\s+password\s+for\s+(?<username>.+?)\s+from\s+(?<ipaddress>.+?)\s+port\s+[0-9]+\s+ssh",
                "Linux", false, "SSH",

                "/var/log/ipbancustom*.log",
                @"(?<timestamp>\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d\.?\d*Z?,\s)?ipban\sfailed\slogin,\sip\saddress:\s(?<ipaddress>.+?),\ssource:\s(?<source>.+?),\suser:\s?(?<username>[^\s,]+)?",
                @"(?<timestamp>\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d\.?\d*Z?,\s)?ipban\ssuccess\slogin,\sip\saddress:\s(?<ipaddress>.+?),\ssource:\s(?<source>.+?),\suser:\s?(?<username>[^\s,]+)?",
                "Linux", false, "IPBanCustom",

                "C:/Program Files/Microsoft/Exchange Server/*.log",
                @".*?,.*?,.*?,.*?,(?<ipaddress>.+?),(?<username>.+?),.*?AuthFailed",
                @"",
                "Windows", true, "MSExchange",

                "C:/Program Files/Smarter Tools/Smarter Mail/*.log\nC:/ Program Files(x86) / Smarter Tools / Smarter Mail/*.log\nC:/SmarterMail/logs/*.log\nC:/Smarter Mail/logs/*.log",
                @"\[(?<ipaddress>[^\]]+)\](\[.*?\]\s+)?(The domain given in the EHLO command violates an EHLO SMTP|IP blocked by brute force abuse detection rule)",
                @"",
                "Windows", true, "SmarterMail",

                "C:/Program Files/Tomcat/logs/*access_log*.txt",
                @"^(?<ipaddress>.*?)\s.*?((php|md5sum|cgi-bin|joomla).*?\s404\s[0-9]+$|\s400\s-)$",
                @"",
                "Windows", true, "Apache",

                "C:/IPBanCustomLogs/*.log",
                @"ipban\sfailed\slogin,\sip\saddress:\s(?<ipaddress>.+?),\ssource:\s(?<source>.+?),\suser:\s?(?<username>[^\s,]+)?",
                @"ipban\ssuccess\slogin,\sip\saddress:\s(?<ipaddress>.+?),\ssource:\s(?<source>.+?),\suser:\s?(?<username>[^\s,]+)?",
                "Windows", true, "IPBanCustom"
            };

            Assert.AreEqual(logFileData.Length / 6, cfg.LogFilesToParse.Count);
            for (int i = 0; i < logFileData.Length; i += 6)
            {
                AssertLogFileToParse(cfg.LogFilesToParse[i / 6],
                                     (string)logFileData[i + 1],
                                     maxFileSize,
                                     (string)logFileData[i],
                                     pingInterval,
                                     (string)logFileData[i + 3],
                                     (bool)logFileData[i + 4],
                                     (string)logFileData[i + 5],
                                     (string)logFileData[i + 2]);
            }
        }
Example #5
0
 private void AssertLogFileToParse(IPBanLogFileToParse file, string failedLoginRegex, int maxFileSize, string pathAndMask, int pingInterval, string platformRegex,
                                   bool recursive, string source, string successfulLoginRegex)
 {
     Assert.AreEqual(IPBanConfig.ParseRegex(failedLoginRegex)?.ToString(), IPBanConfig.ParseRegex(file.FailedLoginRegex)?.ToString());
     Assert.AreEqual(maxFileSize, file.MaxFileSize);
     Assert.AreEqual(Regex.Replace(pathAndMask.Trim().Replace('\n', '|'), "\\s+", string.Empty), Regex.Replace(file.PathAndMask.Trim().Replace('\n', '|'), "\\s+", string.Empty));
     Assert.AreEqual(pingInterval, file.PingInterval);
     Assert.AreEqual(IPBanConfig.ParseRegex(platformRegex)?.ToString(), IPBanConfig.ParseRegex(file.PlatformRegex)?.ToString());
     Assert.AreEqual(recursive, file.Recursive);
     Assert.AreEqual(source, file.Source);
     Assert.AreEqual(IPBanConfig.ParseRegex(successfulLoginRegex)?.ToString(), IPBanConfig.ParseRegex(file.SuccessfulLoginRegex)?.ToString());
 }
Example #6
0
 private void AssertLogFileToParse(IPBanLogFileToParse file, string failedLoginRegex, string failedLoginRegexTimestampFormat,
                                   int maxFileSize, string pathAndMask, int pingInterval, string platformRegex,
                                   string source, string successfulLoginRegex, string successfulLoginRegexTimestampFormat,
                                   LogLevel failedLogLevel = LogLevel.Warning, LogLevel successLogLevel = LogLevel.Warning)
 {
     Assert.AreEqual(IPBanConfig.ParseRegex(failedLoginRegex)?.ToString(), IPBanConfig.ParseRegex(file.FailedLoginRegex)?.ToString());
     Assert.AreEqual(failedLoginRegexTimestampFormat, file.FailedLoginRegexTimestampFormat);
     Assert.AreEqual(maxFileSize, file.MaxFileSize);
     Assert.AreEqual(Regex.Replace(pathAndMask.Trim().Replace('\n', '|'), "\\s+", string.Empty), Regex.Replace(file.PathAndMask.Trim().Replace('\n', '|'), "\\s+", string.Empty));
     Assert.AreEqual(pingInterval, file.PingInterval);
     Assert.AreEqual(IPBanConfig.ParseRegex(platformRegex)?.ToString(), IPBanConfig.ParseRegex(file.PlatformRegex)?.ToString());
     Assert.AreEqual(source, file.Source);
     Assert.AreEqual(IPBanConfig.ParseRegex(successfulLoginRegex)?.ToString(), IPBanConfig.ParseRegex(file.SuccessfulLoginRegex)?.ToString());
     Assert.AreEqual(successfulLoginRegexTimestampFormat, file.SuccessfulLoginRegexTimestampFormat);
     Assert.AreEqual(failedLogLevel, file.FailedLoginLogLevel);
     Assert.AreEqual(successLogLevel, file.SuccessfulLoginLogLevel);
 }
Example #7
0
        public async Task TestDefaultConfig()
        {
            // ensure config file is read properly
            IPBanService service = IPBanService.CreateAndStartIPBanTestService <IPBanService>();

            try
            {
                IPBanConfig cfg = service.Config;
                Assert.IsNotNull(cfg);
                Assert.AreEqual(TimeSpan.FromDays(1.0), cfg.BanTimes.First());
                Assert.AreEqual(1, cfg.BanTimes.Length);
                Assert.IsEmpty(cfg.BlacklistFilter.IPAddressRanges);
                Assert.IsTrue(string.IsNullOrEmpty(cfg.BlacklistFilter.Regex?.ToString()));
                Assert.IsFalse(cfg.ClearBannedIPAddressesOnRestart);
                Assert.IsFalse(cfg.ClearFailedLoginsOnSuccessfulLogin);
                Assert.IsFalse(cfg.ProcessInternalIPAddresses);
                Assert.AreEqual(TimeSpan.FromSeconds(15.0), cfg.CycleTime);
                Assert.AreEqual(TimeSpan.FromDays(1.0), cfg.ExpireTime);
                Assert.AreEqual("https://checkip.amazonaws.com/", cfg.ExternalIPAddressUrl);
                Assert.AreEqual(5, cfg.FailedLoginAttemptsBeforeBan);
                Assert.AreEqual(20, cfg.FailedLoginAttemptsBeforeBanUserNameWhitelist);
                Assert.AreEqual("IPBan_", cfg.FirewallRulePrefix);
                Assert.AreEqual(TimeSpan.FromSeconds(1.0), cfg.MinimumTimeBetweenFailedLoginAttempts);
                Assert.IsEmpty(cfg.ProcessToRunOnBan);
                Assert.IsEmpty(cfg.ProcessToRunOnUnban);
                Assert.IsFalse(cfg.ResetFailedLoginCountForUnbannedIPAddresses);
                Assert.IsTrue(cfg.UseDefaultBannedIPAddressHandler);
                Assert.IsEmpty(cfg.UserNameWhitelist);
                Assert.IsEmpty(cfg.UserNameWhitelistRegex);
                Assert.IsEmpty(cfg.WhitelistFilter.IPAddressRanges);
                Assert.IsTrue(string.IsNullOrEmpty(cfg.WhitelistFilter.Regex?.ToString()));
                Assert.AreEqual(0, cfg.ExtraRules.Count);
                Assert.AreEqual(cfg.FirewallUriRules.Trim(), "EmergingThreats,01:00:00:00,https://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt");

                AssertLogFilesToParse(cfg);
                AssertEventViewer(cfg);
                string xml = await service.ConfigReaderWriter.ReadConfigAsync();

                IPBanConfig prod = IPBanConfig.LoadFromXml(xml);
                Assert.IsTrue(prod.UseDefaultBannedIPAddressHandler);
            }
            finally
            {
                IPBanService.DisposeIPBanTestService(service);
            }
        }
Example #8
0
        public async Task TestDefaultConfig()
        {
            // ensure config file is read properly
            IPBanService service = IPBanService.CreateAndStartIPBanTestService <IPBanService>();

            try
            {
                IPBanConfig cfg = service.Config;
                Assert.IsNotNull(cfg);
                Assert.AreEqual(TimeSpan.FromDays(1.0), cfg.BanTimes.First());
                Assert.AreEqual(1, cfg.BanTimes.Length);
                Assert.IsEmpty(cfg.BlackList);
                Assert.IsEmpty(cfg.BlackListRegex);
                Assert.IsFalse(cfg.ClearBannedIPAddressesOnRestart);
                Assert.AreEqual(TimeSpan.FromSeconds(15.0), cfg.CycleTime);
                Assert.AreEqual(TimeSpan.FromDays(1.0), cfg.ExpireTime);
                Assert.AreEqual("https://checkip.amazonaws.com/", cfg.ExternalIPAddressUrl);
                Assert.AreEqual(5, cfg.FailedLoginAttemptsBeforeBan);
                Assert.AreEqual(20, cfg.FailedLoginAttemptsBeforeBanUserNameWhitelist);
                Assert.AreEqual(1, cfg.FirewallOSAndType.Count);
                Assert.AreEqual("*:Default", cfg.FirewallOSAndType.Keys.First() + ":" + cfg.FirewallOSAndType.Values.First());
                Assert.AreEqual("IPBan_", cfg.FirewallRulePrefix);
                Assert.AreEqual(TimeSpan.FromSeconds(1.0), cfg.MinimumTimeBetweenFailedLoginAttempts);
                Assert.IsEmpty(cfg.ProcessToRunOnBan);
                Assert.IsFalse(cfg.ResetFailedLoginCountForUnbannedIPAddresses);
                Assert.IsTrue(cfg.UseDefaultBannedIPAddressHandler);
                Assert.IsEmpty(cfg.UserNameWhitelist);
                Assert.IsEmpty(cfg.UserNameWhitelistRegex);
                Assert.IsEmpty(cfg.WhiteList);
                Assert.IsEmpty(cfg.WhiteListRegex);
                Assert.AreEqual(0, cfg.ExtraRules.Count);

                AssertLogFilesToParse(cfg);
                AssertEventViewer(cfg);
                string xml = await service.ReadConfigAsync();

                IPBanConfig prod = IPBanConfig.LoadFromXml(xml, null);
                Assert.IsTrue(prod.UseDefaultBannedIPAddressHandler);
            }
            finally
            {
                IPBanService.DisposeIPBanTestService(service);
            }
        }
Example #9
0
        public async Task TestUserNameWhitelistRegexBan()
        {
            using IPBanConfig.TempConfigChanger configChanger = new IPBanConfig.TempConfigChanger(service, xml =>
            {
                return(IPBanConfig.ChangeConfigAppSetting(xml, "UserNameWhitelistRegex", "ftp_[0-9]+"));
            }, out string newConfig);

            service.AddIPAddressLogEvents(new IPAddressLogEvent[]
            {
                // a single failed login with a non-blacklisted user name should not get banned
                new IPAddressLogEvent("99.99.99.99", "ftp_1", "RDP", 1, IPAddressEventType.FailedLogin),

                // a single failed login with a failed user name whitelist regex should get banned
                new IPAddressLogEvent("99.99.99.90", "NaughtyUserName", "RDP", 1, IPAddressEventType.FailedLogin)
            });
            await service.RunCycle();

            Assert.IsTrue(service.Firewall.IsIPAddressBlocked("99.99.99.90", out _));
            Assert.IsFalse(service.Firewall.IsIPAddressBlocked("99.99.99.99", out _));
        }
Example #10
0
 private void AssertEventViewerGroup(EventViewerExpressionGroup group, string keywords, int windowsMinimumMajorVersion, int windowsMinimumMinorVersion,
                                     bool notifyOnly, string path, string source, params string[] expressions)
 {
     Assert.NotNull(group);
     Assert.AreEqual(keywords, group.Keywords);
     Assert.AreEqual(ulong.Parse(keywords.Replace("0x", string.Empty), System.Globalization.NumberStyles.HexNumber), group.KeywordsULONG);
     Assert.AreEqual(windowsMinimumMajorVersion, group.MinimumWindowsMajorVersion);
     Assert.AreEqual(windowsMinimumMinorVersion, group.MinimumWindowsMinorVersion);
     Assert.AreEqual(notifyOnly, group.NotifyOnly);
     Assert.AreEqual(path, group.Path);
     Assert.AreEqual(source, group.Source);
     Assert.NotNull(group.Expressions);
     Assert.AreEqual(group.Expressions.Count, expressions.Length / 2);
     for (int i = 0; i < expressions.Length;)
     {
         int   groupIndex = i / 2;
         Regex regex      = IPBanConfig.ParseRegex(group.Expressions[groupIndex].Regex);
         Assert.AreEqual(expressions[i++], group.Expressions[groupIndex].XPath?.Trim());
         Assert.AreEqual(expressions[i++], (regex is null ? string.Empty : regex.ToString()));
     }
 }
Example #11
0
        public async Task TestIPWhitelist()
        {
            const string whitelist = "192.168.0.0/16";

            string config = await service.ReadConfigAsync();

            string newConfig = IPBanConfig.ChangeConfigAppSetting(config, "Whitelist", whitelist);
            await service.WriteConfigAsync(newConfig);

            try
            {
                // load new config
                service.RunCycle().Sync();

                string banIP   = "99.99.99.99";
                string noBanIP = "192.168.99.99";

                service.AddIPAddressLogEvents(new IPAddressLogEvent[]
                {
                    // should be banned
                    new IPAddressLogEvent(banIP, "user1", "RDP", 999, IPAddressEventType.FailedLogin),

                    // whitelisted
                    new IPAddressLogEvent(noBanIP, "user2", "RDP", 999, IPAddressEventType.FailedLogin),
                });

                // process failed logins
                service.RunCycle().Sync();

                Assert.IsTrue(service.Firewall.IsIPAddressBlocked(banIP, out _));
                Assert.IsFalse(service.Firewall.IsIPAddressBlocked(noBanIP, out _));
                Assert.IsTrue(service.DB.TryGetIPAddress(banIP, out IPBanDB.IPAddressEntry e1));
                Assert.IsFalse(service.DB.TryGetIPAddress(noBanIP, out IPBanDB.IPAddressEntry e2));
            }
            finally
            {
                // restore config
                await service.WriteConfigAsync(config);
            }
        }
Example #12
0
        public async Task TestExtraFirewallRules()
        {
            string config = await service.ReadConfigAsync();

            string newConfig = IPBanConfig.ChangeConfigAppSetting(config, "FirewallRules", @"
                ReddisAllowIP;allow;10.0.0.1,10.0.0.2,192.168.1.168/24;6379;.
                WebOnly;block;0.0.0.0/1,128.0.0.0/1,::/1,8000::/1;22,80,443,3389;^(?:(?!Windows).)+$
            ");
            await service.WriteConfigAsync(newConfig);

            await service.RunCycle();

            List <string> rules      = service.Firewall.GetRuleNames().ToList();
            string        reddisRule = service.Firewall.RulePrefix + "EXTRA_ReddisAllowIP";
            string        webRule    = service.Firewall.RulePrefix + "EXTRA_WebOnly";

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                // on Windows, block is the default, so only the allow rules should show up
                Assert.IsTrue(rules.Exists((s) => s.StartsWith(reddisRule)));
                Assert.IsFalse(rules.Exists((s) => s.StartsWith(webRule)));
                Assert.AreEqual(1, service.Config.ExtraRules.Count);
                IPBanFirewallRule rule1       = service.Config.ExtraRules[0];
                string            regexString = rule1.ToString();
                Assert.AreEqual("EXTRA_ReddisAllowIP;allow;10.0.0.1/32,10.0.0.2/32,192.168.1.0/24;6379;.", regexString);
            }
            else
            {
                // on Linux, both rules are needed
                Assert.AreEqual(2, service.Config.ExtraRules.Count);
                Assert.IsTrue(rules.Exists((s) => s.StartsWith(reddisRule)));
                Assert.IsTrue(rules.Exists((s) => s.StartsWith(webRule)));
                IPBanFirewallRule rule1        = service.Config.ExtraRules[0];
                IPBanFirewallRule rule2        = service.Config.ExtraRules[1];
                string            regexString1 = rule1.ToString();
                string            regexString2 = rule2.ToString();
                Assert.AreEqual("EXTRA_ReddisAllowIP;allow;10.0.0.1/32,10.0.0.2/32,192.168.1.0/24;6379;.", regexString1);
                Assert.AreEqual("EXTRA_WebOnly;block;0.0.0.0/1,128.0.0.0/1,::/1,8000::/1;22,80,443,3389;^(?:(?!Windows).)+$", regexString2);
            }
        }
Example #13
0
        public void TestDefaultConfig()
        {
            // ensure config file is read properly
            IPBanService service = IPBanService.CreateAndStartIPBanTestService <IPBanService>();

            try
            {
                IPBanConfig cfg = service.Config;
                Assert.IsNotNull(cfg);
                Assert.AreEqual(TimeSpan.FromDays(1.0), cfg.BanTime);
                Assert.IsEmpty(cfg.BlackList);
                Assert.IsEmpty(cfg.BlackListRegex);
                Assert.IsFalse(cfg.ClearBannedIPAddressesOnRestart);
                Assert.IsFalse(cfg.CreateWhitelistFirewallRule);
                Assert.AreEqual(TimeSpan.FromSeconds(15.0), cfg.CycleTime);
                Assert.AreEqual(TimeSpan.FromDays(1.0), cfg.ExpireTime);
                Assert.AreEqual("https://checkip.amazonaws.com/", cfg.ExternalIPAddressUrl);
                Assert.AreEqual(5, cfg.FailedLoginAttemptsBeforeBan);
                Assert.AreEqual(20, cfg.FailedLoginAttemptsBeforeBanUserNameWhitelist);
                Assert.AreEqual(1, cfg.FirewallOSAndType.Count);
                Assert.AreEqual("*:Default", cfg.FirewallOSAndType.Keys.First() + ":" + cfg.FirewallOSAndType.Values.First());
                Assert.AreEqual("IPBan_", cfg.FirewallRulePrefix);
                Assert.AreEqual(TimeSpan.FromSeconds(1.0), cfg.MinimumTimeBetweenFailedLoginAttempts);
                Assert.IsEmpty(cfg.ProcessToRunOnBan);
                Assert.IsFalse(cfg.UseDefaultBannedIPAddressHandler); // the create and start test service forces this false, it is true otherwise in production by default
                Assert.IsEmpty(cfg.UserNameWhitelist);
                Assert.IsEmpty(cfg.WhiteList);
                Assert.IsEmpty(cfg.WhiteListRegex);

                AssertLogFilesToParse(cfg);
                AssertEventViewer(cfg);

                IPBanConfig prod = IPBanConfig.LoadFromFile(service.ConfigFilePath.Replace(".tmp", string.Empty), null);
                Assert.IsTrue(prod.UseDefaultBannedIPAddressHandler);
            }
            finally
            {
                IPBanService.DisposeIPBanTestService(service);
            }
        }
Example #14
0
        private void RunConfigBanTest(string key, string value, string banIP, string noBanIP, int noBanIPCount = 999)
        {
            // turn on clear failed logins upon success login
            using IPBanConfig.TempConfigChanger configChanger = new IPBanConfig.TempConfigChanger(service, xml =>
            {
                return(IPBanConfig.ChangeConfigAppSetting(xml, key, value));
            }, out string newConfig);

            List <IPAddressLogEvent> events = new List <IPAddressLogEvent>
            {
                new IPAddressLogEvent(banIP, "user1", "RDP", 999, IPAddressEventType.FailedLogin)
            };

            if (!string.IsNullOrWhiteSpace(noBanIP))
            {
                events.Add(new IPAddressLogEvent(noBanIP, "user2", "RDP", noBanIPCount, IPAddressEventType.FailedLogin));
            }
            service.AddIPAddressLogEvents(events);

            // process failed logins
            service.RunCycle().Sync();

            Assert.IsTrue(service.Firewall.IsIPAddressBlocked(banIP, out _));
            Assert.IsTrue(service.DB.TryGetIPAddress(banIP, out IPBanDB.IPAddressEntry e1));
            Assert.AreEqual(e1.FailedLoginCount, 999);
            if (!string.IsNullOrWhiteSpace(noBanIP))
            {
                Assert.IsFalse(service.Firewall.IsIPAddressBlocked(noBanIP, out _));
                if (noBanIPCount > 0)
                {
                    Assert.IsTrue(service.DB.TryGetIPAddress(noBanIP, out IPBanDB.IPAddressEntry e2));
                    Assert.AreEqual(e2.FailedLoginCount, noBanIPCount);
                }
                else
                {
                    Assert.IsFalse(service.DB.TryGetIPAddress(noBanIP, out _));
                }
            }
        }
Example #15
0
        public async Task TestUserNameBan()
        {
            string config = await service.ReadConfigAsync();

            string newConfig = IPBanConfig.ChangeConfigAppSetting(config, "Blacklist", "NaughtyUserName");
            await service.WriteConfigAsync(newConfig);

            await service.RunCycle();

            service.AddIPAddressLogEvents(new IPAddressLogEvent[]
            {
                // a single failed login with a non-blacklisted user name should not get banned
                new IPAddressLogEvent("99.99.99.99", "Good User Name", "RDP", 1, IPAddressEventType.FailedLogin),

                // a single failed login with a blacklisted user name should get banned
                new IPAddressLogEvent("99.99.99.90", "NaughtyUserName", "RDP", 1, IPAddressEventType.FailedLogin)
            });
            await service.RunCycle();

            Assert.IsTrue(service.Firewall.IsIPAddressBlocked("99.99.99.90", out _));
            Assert.IsFalse(service.Firewall.IsIPAddressBlocked("99.99.99.99", out _));
        }
Example #16
0
        public async Task TestFailedLoginsClearOnSuccessfulLogin()
        {
            // turn on clear failed logins upon success login
            string config = await service.ReadConfigAsync();

            string newConfig = IPBanConfig.ChangeConfigAppSetting(config, nameof(IPBanConfig.ClearFailedLoginsOnSuccessfulLogin), "true");
            await service.WriteConfigAsync(newConfig);

            try
            {
                await service.RunCycle();

                string ip = "99.88.77.66";
                for (int i = 0; i < 2; i++)
                {
                    service.AddIPAddressLogEvents(new IPAddressLogEvent[]
                    {
                        // fail login
                        new IPAddressLogEvent(ip, "user1", "RDP", 1, IPAddressEventType.FailedLogin),
                    });
                }

                await service.RunCycle();

                service.AddIPAddressLogEvents(new IPAddressLogEvent[]
                {
                    new IPAddressLogEvent(ip, "user1", "RDP", 1, IPAddressEventType.SuccessfulLogin),
                });

                await service.RunCycle();

                Assert.IsFalse(service.DB.TryGetIPAddress(ip, out _));
            }
            finally
            {
                // restore config
                await service.WriteConfigAsync(config);
            }
        }
Example #17
0
        private void AssertLogFilesToParse(IPBanConfig cfg)
        {
            const int    maxFileSize   = 16777216;
            const int    pingInterval  = 10000;
            const string pathAndMask1  = "/var/log/auth*.log\n/var/log/secure*";
            const string pathAndMask2  = "/var/log/ipbancustom*.log";
            const string pathAndMask3  = "C:/Program Files/Microsoft/Exchange Server/*.log";
            const string pathAndMask4  = "C:/IPBanCustomLogs/*.log";
            const string failedRegex1  = @"failed\s+password\s+for\s+(invalid\s+user\s+)?(?<username>.+?\s+)from\s+(?<ipaddress>.+?)\s+port\s+[0-9]+\s+ssh|did\s+not\s+receive\s+identification\s+string\s+from\s+(?<ipaddress>[^\s]+)|connection\s+closed\s+by\s+(invalid\s+user\s+)?(?<username>.+?\s+)?(?<ipaddress>.+?)\s+port\s+[0-9]+\s+\[preauth\]\s*(\(no\s+attempt\s+to\s+login\s+after\s+timeout\))?|disconnected\s+from\s+(invalid\s+user\s+)?(?<username>.+?)\s+(?<ipaddress>.+?)\s+port\s+[0-9]+\s+\[preauth\]|disconnected\s+from\s+(?<ipaddress>.+?)\s+port\s+[0-9]+\s+\[preauth\]|disconnected\s+from\s+authenticating\s+user\s+(?<username>.+?)\s+(?<ipaddress>.+?)\s+port\s+[0-9]+\s+\[preauth\]";
            const string successRegex1 = @"Accepted\s+password\s+for\s+(?<username>.+?)\s+from\s+(?<ipaddress>.+?)\s+port\s+[0-9]+\s+ssh";
            const string failedRegex2  = @"ipban\sfailed\slogin,\sip\saddress:\s(?<ipaddress>.+?),\ssource:\s(?<source>.+?),\suser:\s(?<username>[^\s,]+)";
            const string successRegex2 = @"ipban\ssuccess\slogin,\sip\saddress:\s(?<ipaddress>.+?),\ssource:\s(?<source>.+?),\suser:\s(?<username>[^\s,]+)";
            const string failedRegex3  = @".*?,.*?,.*?,.*?,(?<ipaddress>.+?),(?<username>.+?),.*?AuthFailed";
            const string successRegex3 = @"";
            const string failedRegex4  = @"ipban\sfailed\slogin,\sip\saddress:\s(?<ipaddress>.+?),\ssource:\s(?<source>.+?),\suser:\s(?<username>[^\s,]+)";
            const string successRegex4 = @"ipban\ssuccess\slogin,\sip\saddress:\s(?<ipaddress>.+?),\ssource:\s(?<source>.+?),\suser:\s(?<username>[^\s,]+)";

            Assert.AreEqual(4, cfg.LogFilesToParse.Count);
            AssertLogFileToParse(cfg.LogFilesToParse[0], failedRegex1, maxFileSize, pathAndMask1, pingInterval, "Linux", false, "SSH", successRegex1);
            AssertLogFileToParse(cfg.LogFilesToParse[1], failedRegex2, maxFileSize, pathAndMask2, pingInterval, "Linux", false, "IPBanCustom", successRegex2);
            AssertLogFileToParse(cfg.LogFilesToParse[2], failedRegex3, maxFileSize, pathAndMask3, pingInterval, "Windows", true, "MSExchange", successRegex3);
            AssertLogFileToParse(cfg.LogFilesToParse[3], failedRegex4, maxFileSize, pathAndMask4, pingInterval, "Windows", true, "IPBanCustom", successRegex4);
        }
Example #18
0
        private void AssertEventViewer(IPBanConfig cfg)
        {
            const int minimumWindowsMajorVersion = 6;

            EventViewerExpressionGroup[] groups = cfg.WindowsEventViewerExpressionsToBlock.Groups;
            Assert.NotNull(groups);
            Assert.AreEqual(9, groups.Length);
            AssertEventViewerGroup(groups[0], "0x8010000000000000", minimumWindowsMajorVersion, 0, false, "Security", "RDP", "//EventID", "^(4625|5152)$", "//Data[@Name='IpAddress' or @Name='Workstation' or @Name='SourceAddress']", "(?<ipaddress>.+)");
            AssertEventViewerGroup(groups[1], "0x80000000000000", minimumWindowsMajorVersion, 0, false, "Application", "IPBanCustom", "//Data", @"ipban\sfailed\slogin,\sip\saddress:\s(?<ipaddress>.+?),\ssource:\s(?<source>.+?),\suser:\s(?<username>[^\s,]+)");
            AssertEventViewerGroup(groups[2], "0x90000000000000", minimumWindowsMajorVersion, 0, false, "Application", "MSSQL", "//Provider[@Name='MSSQLSERVER']", string.Empty, "//Data", @"(?!(\[CLIENT\s?:|Reason\s?:))(?<username>.+)", "//Data", @"\[CLIENT\s?:\s?(?<ipaddress>.*?)\]");
            AssertEventViewerGroup(groups[3], "0x80000000000000", minimumWindowsMajorVersion, 0, false, "Application", "MySQL", "//Provider[@Name='MySQL']", string.Empty, "//Data", "Access denied for user '?(?<username>.*?)'@'(?<ipaddress>.*?)'");
            AssertEventViewerGroup(groups[4], "0x80000000000000", minimumWindowsMajorVersion, 0, false, "System", "MSExchange", "//Provider[@Name='MSExchangeTransport']", string.Empty, "//Data", "LogonDenied", "//Data", "(?<ipaddress_exact>.+)");
            AssertEventViewerGroup(groups[5], "0x80000000000000", minimumWindowsMajorVersion, 0, false, "Application", "phpMyAdmin", "//Data", "phpMyAdmin", "//Data", @"user denied: (?<username>.*?)\(mysql-denied\) from *(?<ipaddress>.+)");
            AssertEventViewerGroup(groups[6], "0x8000000000000000", minimumWindowsMajorVersion, 0, false, "OpenSSH/Admin", "SSH", "//Data[@Name='payload']", @"maximum authentication attempts exceeded for( invalid user)? (?<username>.*?) from (?<ipaddress>.*?)\s");
            AssertEventViewerGroup(groups[7], "0x4000000000000000", minimumWindowsMajorVersion, 0, false, "OpenSSH/Operational", "SSH", "//Data[@Name='payload']", @"Failed password for( invalid user)? (?<username>.*?) from (?<ipaddress>.*?)\s|Connection closed by (?<ipaddress>.*?) port [0-9]+ \[preauth\]");
            AssertEventViewerGroup(groups[8], "0x4000000000000000", minimumWindowsMajorVersion, 0, false, "Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Operational", "RDP", "//Opcode", "^14$", "//Data[@Name='ClientIP' or @Name='IPString']", "(?<ipaddress>.+)");

            groups = cfg.WindowsEventViewerExpressionsToNotify.Groups;
            Assert.NotNull(groups);
            Assert.AreEqual(3, groups.Length);
            AssertEventViewerGroup(groups[0], "0x8000000000000000", minimumWindowsMajorVersion, 0, true, "Security", "RDP", "//EventID", "^4624$", "//Data[@Name='IpAddress' or @Name='Workstation' or @Name='SourceAddress']", "(?<ipaddress>.+)");
            AssertEventViewerGroup(groups[1], "0x4000000000000000", minimumWindowsMajorVersion, 0, true, "OpenSSH/Operational", "SSH", "//Data[@Name='payload']", "Accepted password for (?<username>.+?) from (?<ipaddress>.+?) port [0-9]+ ssh");
            AssertEventViewerGroup(groups[2], "0x80000000000000", minimumWindowsMajorVersion, 0, true, "Application", "IPBanCustom", "//Data", @"ipban\ssuccess\slogin,\sip\saddress:\s(?<ipaddress>.+?),\ssource:\s(?<source>.+?),\suser:\s(?<username>[^\s,]+)");
        }
Example #19
0
        private async Task TestMultipleBanTimespansExternalBlockAsync(bool resetFailedLogin)
        {
            const string                        ipAddress = "99.99.99.99";
            const string                        userName  = "******";
            const string                        source    = "RDP";
            const IPAddressEventType            type      = IPAddressEventType.FailedLogin;
            KeyValuePair <DateTime?, DateTime?> banDates;

            service.IPBanDelegate = new ExternalBlocker(service);

            IPAddressLogEvent[] events = new IPAddressLogEvent[1];

            using IPBanConfig.TempConfigChanger configChanger = new IPBanConfig.TempConfigChanger(service, xml =>
            {
                xml = IPBanConfig.ChangeConfigAppSetting(xml, "BanTime", "00:00:01:00,00:00:05:00,00:00:15:00,89:00:00:00");
                xml = IPBanConfig.ChangeConfigAppSetting(xml, "ResetFailedLoginCountForUnbannedIPAddresses", resetFailedLogin.ToString());
                return(xml);
            }, out string newConfig);
            Assert.AreEqual(4, service.Config.BanTimes.Length);

            // send a block event, should get banned for 1 minute
            IPBanService.UtcNow = new DateTime(2020, 1, 1, 1, 1, 1, DateTimeKind.Utc);

            for (int i = 0; i < 2; i++)
            {
                events[0] = new IPAddressLogEvent(ipAddress, userName, source, 1, type, IPBanService.UtcNow);
                service.AddIPAddressLogEvents(events);
                await service.RunCycle();

                Assert.IsFalse(service.Firewall.IsIPAddressBlocked(ipAddress));

                // run cycle again, should get pinged by external blocker and ip should be blocked
                await service.RunCycle();

                Assert.IsTrue(service.Firewall.IsIPAddressBlocked(ipAddress));
                Assert.IsTrue(service.DB.TryGetBanDates(ipAddress, out banDates));
                Assert.AreEqual(IPBanService.UtcNow, banDates.Key);
                Assert.AreEqual(IPBanService.UtcNow.AddMinutes(1.0), banDates.Value);

                // short step, should still be blocked
                IPBanService.UtcNow += TimeSpan.FromSeconds(1.0);
                await service.RunCycle();

                Assert.IsTrue(service.Firewall.IsIPAddressBlocked(ipAddress));

                IPBanService.UtcNow += TimeSpan.FromMinutes(1.0);
                await service.RunCycle();

                Assert.IsFalse(service.Firewall.IsIPAddressBlocked(ipAddress));

                // send a fail login event, should get banned for 5 minutes
                events[0] = new IPAddressLogEvent(ipAddress, userName, source, 1, type, IPBanService.UtcNow);
                service.AddIPAddressLogEvents(events);
                await service.RunCycle();

                Assert.IsFalse(service.Firewall.IsIPAddressBlocked(ipAddress));

                DateTime savedBanDate = IPBanService.UtcNow;

                // add a failed and blocked login event, should not interfere with the ban cycle
                events[0] = new IPAddressLogEvent(ipAddress, userName, source, 1, IPAddressEventType.FailedLogin, IPBanService.UtcNow);
                service.AddIPAddressLogEvents(events);
                await service.RunCycle();

                events[0] = new IPAddressLogEvent(ipAddress, userName, source, 1, IPAddressEventType.Blocked, IPBanService.UtcNow, true);
                service.AddIPAddressLogEvents(events);
                await service.RunCycle();

                // throw in some chaos
                IPBanService.UtcNow += TimeSpan.FromSeconds(7.213);

                // blocker will ban the ip
                await service.RunCycle();

                Assert.IsTrue(service.Firewall.IsIPAddressBlocked(ipAddress));
                Assert.IsTrue(service.DB.TryGetBanDates(ipAddress, out banDates));
                Assert.AreEqual(savedBanDate, banDates.Key);
                Assert.AreEqual(savedBanDate.AddMinutes(5.0), banDates.Value);

                IPBanService.UtcNow += TimeSpan.FromMinutes(20.0);
                await service.RunCycle();

                Assert.IsFalse(service.Firewall.IsIPAddressBlocked(ipAddress));

                // send a failed login event, should get banned for 15 minutes
                events[0] = new IPAddressLogEvent(ipAddress, userName, source, 1, type, IPBanService.UtcNow);
                service.AddIPAddressLogEvents(events);
                await service.RunCycle();

                Assert.IsFalse(service.Firewall.IsIPAddressBlocked(ipAddress));

                // cycle again, blocker will ban
                await service.RunCycle();

                Assert.IsTrue(service.Firewall.IsIPAddressBlocked(ipAddress));
                Assert.IsTrue(service.DB.TryGetBanDates(ipAddress, out banDates));
                Assert.AreEqual(IPBanService.UtcNow, banDates.Key);
                Assert.AreEqual(IPBanService.UtcNow.AddMinutes(15.0), banDates.Value);

                IPBanService.UtcNow += TimeSpan.FromMinutes(30.0);
                await service.RunCycle();

                Assert.IsFalse(service.Firewall.IsIPAddressBlocked(ipAddress));

                // send a block event, should get banned for 89 days
                events[0] = new IPAddressLogEvent(ipAddress, userName, source, 1, type, IPBanService.UtcNow);
                service.AddIPAddressLogEvents(events);
                await service.RunCycle();

                Assert.IsFalse(service.Firewall.IsIPAddressBlocked(ipAddress));

                // cycle again, blocker will ban
                await service.RunCycle();

                Assert.IsTrue(service.Firewall.IsIPAddressBlocked(ipAddress));
                Assert.IsTrue(service.DB.TryGetBanDates(ipAddress, out banDates));
                Assert.AreEqual(IPBanService.UtcNow, banDates.Key);
                Assert.AreEqual(IPBanService.UtcNow.AddDays(89.0), banDates.Value);

                IPBanService.UtcNow += TimeSpan.FromDays(91.0);
                await service.RunCycle();

                Assert.IsFalse(service.Firewall.IsIPAddressBlocked(ipAddress));
            }
        }
Example #20
0
        private async Task TestMultipleBanTimespansAsync(bool resetFailedLogin)
        {
            string config = await service.ReadConfigAsync();

            string newConfig = IPBanConfig.ChangeConfigAppSetting(config, "BanTime", "00:00:01:00,00:00:02:00,00:00:03:00");

            newConfig = IPBanConfig.ChangeConfigAppSetting(newConfig, "ResetFailedLoginCountForUnbannedIPAddresses", resetFailedLogin.ToString());
            await service.WriteConfigAsync(newConfig);

            try
            {
                await service.RunCycle();

                Assert.AreEqual(3, service.Config.BanTimes.Length);
                Assert.AreEqual(resetFailedLogin, service.Config.ResetFailedLoginCountForUnbannedIPAddresses);
                for (int i = 1; i <= 3; i++)
                {
                    Assert.AreEqual(TimeSpan.FromMinutes(i), service.Config.BanTimes[i - 1]);
                }

                for (int i = 0; i < 4; i++)
                {
                    // forget all the bans, but they should still be in the database due to the multiple timespans as failed logins
                    IPBanService.UtcNow += TimeSpan.FromDays(14.0);
                    await service.RunCycle();

                    if (i < 3)
                    {
                        if (i > 0)
                        {
                            AssertIPAddressesAreNotBanned(true, true);
                        }

                        AddFailedLogins((i == 0 ? -1 : 1));

                        if (resetFailedLogin)
                        {
                            if (i > 0)
                            {
                                // after one fail login, should not be banned
                                AssertIPAddressesAreNotBanned(true, true);
                            }

                            // add more failed logins
                            AddFailedLogins();

                            // now they should be banned, fail login counts are reset upon ban
                            AssertIPAddressesAreBanned(0, 0);
                        }
                        else
                        {
                            // should have gotten back in with just a single failed login
                            AssertIPAddressesAreBanned(info1.Count + i, info2.Count + i);
                        }

                        Assert.IsTrue(service.DB.TryGetIPAddress(ip1, out IPBanDB.IPAddressEntry e1));
                        Assert.IsTrue(service.DB.TryGetIPAddress(ip2, out IPBanDB.IPAddressEntry e2));

                        // i == 3 means wrap around from 3 minutes back to 1 minute
                        TimeSpan expectedBanDuration = (i < 3 ? expectedBanDuration = TimeSpan.FromMinutes(i + 1) : TimeSpan.FromMinutes(1.0));
                        Assert.AreEqual(expectedBanDuration, e1.BanEndDate - e1.BanStartDate);
                        Assert.AreEqual(expectedBanDuration, e2.BanEndDate - e2.BanStartDate);
                        if (resetFailedLogin)
                        {
                            Assert.AreEqual(0, e1.FailedLoginCount);
                            Assert.AreEqual(0, e2.FailedLoginCount);
                        }
                        else
                        {
                            Assert.AreNotEqual(0, e1.FailedLoginCount);
                            Assert.AreNotEqual(0, e2.FailedLoginCount);
                        }
                    }
                    else
                    {
                        // the cycle will run and remove the expired ip first as they have finished the loop through the ban times, they should all have a single failed login count
                        AddFailedLogins(1);
                        AssertIPAddressesAreNotBanned(true, true);
                        Assert.IsTrue(service.DB.TryGetIPAddress(ip1, out IPBanDB.IPAddressEntry e1));
                        Assert.IsTrue(service.DB.TryGetIPAddress(ip2, out IPBanDB.IPAddressEntry e2));
                        Assert.IsNull(e1.BanStartDate);
                        Assert.IsNull(e2.BanStartDate);
                        Assert.IsNull(e1.BanEndDate);
                        Assert.IsNull(e2.BanEndDate);
                        Assert.AreEqual(1, e1.FailedLoginCount);
                        Assert.AreEqual(1, e2.FailedLoginCount);

                        // now add a bunch of fail logins, ip should ban with a time span of 1 minute
                        AddFailedLogins();
                        if (resetFailedLogin)
                        {
                            AssertIPAddressesAreBanned(0, 0);
                        }
                        else
                        {
                            AssertIPAddressesAreBanned(info1.Count + 1, info2.Count + 1);
                        }
                        Assert.IsTrue(service.DB.TryGetIPAddress(ip1, out e1));
                        Assert.IsTrue(service.DB.TryGetIPAddress(ip2, out e2));
                        TimeSpan expectedBanDuration = TimeSpan.FromMinutes(1.0);
                        Assert.AreEqual(expectedBanDuration, e1.BanEndDate - e1.BanStartDate);
                        Assert.AreEqual(expectedBanDuration, e2.BanEndDate - e2.BanStartDate);
                        if (resetFailedLogin)
                        {
                            Assert.AreEqual(0, e1.FailedLoginCount);
                            Assert.AreEqual(0, e2.FailedLoginCount);
                        }
                        else
                        {
                            Assert.AreEqual(info1.Count + 1, e1.FailedLoginCount);
                            Assert.AreEqual(info2.Count + 1, e2.FailedLoginCount);
                        }
                    }
                }
            }
            finally
            {
                // restore config
                await service.WriteConfigAsync(config);
            }
        }
Example #21
0
        private static void AssertLogFilesToParse(IPBanConfig cfg)
        {
            const int maxFileSize  = 16777216;
            const int pingInterval = 10000;

            // path and mask, fail expression, fail timestamp format, success expression, success timestamp format, platform regex, source
            object[] logFileData = new object[]
            {
                "/var/log/auth*.log\n/var/log/secure*\n/var/log/messages",
                @"failed\s+password\s+for\s+(invalid\s+user\s+)?(?<username>[^\s]+)\s+from\s+(?<ipaddress>[^\s]+)\s+port\s+[0-9]+\s+ssh|did\s+not\s+receive\s+identification\s+string\s+from\s+(?<ipaddress>[^\s]+)|connection\s+closed\s+by\s+((invalid\s+user\s+)?(?<username>[^\s]+)\s+)?(?<ipaddress>[^\s]+)\s+port\s+[0-9]+\s+\[preauth\]|disconnected\s+from\s+(invalid\s+user\s+)?(?<username>[^\s]+)\s+(?<ipaddress>[^\s]+)\s+port\s+[0-9]+\s+\[preauth\]|disconnected\s+from\s+(?<ipaddress>[^\s]+)\s+port\s+[0-9]+\s+\[preauth\]|disconnected\s+from\s+authenticating\s+user\s+(?<username>[^\s]+)\s+(?<ipaddress>[^\s]+)\s+port\s+[0-9]+\s+\[preauth\]",
                @"",
                @"Accepted\s+password\s+for\s+(?<username>[^\s]+)\s+from\s+(?<ipaddress>[^\s]+)\s+port\s+[0-9]+\s+ssh",
                @"",
                "Linux", "SSH",

                "/var/log/ipbancustom*.log",
                @"(?<timestamp>\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d(?:\.\d+)?Z?)?(?:,\s)?ipban\sfailed\slogin,\sip\saddress:\s(?<ipaddress>[^,\n]+),\ssource:\s(?<source>[^,\n]+)?,\suser:\s(?<username>[^\s,]+)?",
                @"",
                @"(?<timestamp>\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d(?:\.\d+)?Z?)?(?:,\s)?ipban\ssuccess\slogin,\sip\saddress:\s(?<ipaddress>[^,\n]+),\ssource:\s(?<source>[^,\n]+)?,\suser:\s(?<username>[^\s,]+)?",
                @"",
                "Linux", "IPBanCustom",

                "C:/Program Files/Microsoft/Exchange Server/*/TransportRoles/Logs/FrontEnd/ProtocolLog/**.log",
                @"^(?<timestamp>[0-9TZ\-:\.]+),(?:.*?\\(?:External\sAuthenticated\sRelay|Internet\sRecive\sFrontend),)?(?:[^,\n]*,){3}(?<ipaddress>[^,\n]+).*?(?:(?:504\s5\.7\.4\sUnrecognized\sauthentication\stype)|(?:LogonDenied\n?.*?(?:User\:|User\sName\:)\s(?<username>[^\n,""]+)))",
                @"",
                @"^(?<timestamp>[0-9TZ\-:\.]+)?,(?:[^,\n]*,){4}(?<ipaddress>[^,\n]+),(?:[^,\n]*),(?<username>[^,\n]*),authenticated",
                @"",
                "Windows", "MSExchange",

                "C:/Program Files/Smarter Tools/Smarter Mail/**/*.log\nC:/Program Files (x86)/Smarter Tools/Smarter Mail/**/*.log\nC:/SmarterMail/logs/**/*.log\nC:/Smarter Mail/logs/**/*.log",
                @"\[(?<ipaddress>[^\]\n]+)\](?:\[[^\]\n]*\]\s+).*?(?:(?:The\sdomain\sgiven\sin\sthe\sEHLO\scommand\sviolates\san\sEHLO\sSMTP)|(?:IP\sblocked\sby\sbrute\sforce\sabuse\sdetection\srule)|(?:login\sfailed)|(?:IP\sblocked\sby\sbrute\sforce\sabuse\sdetection\srule)|(?:IP\sis\sblacklisted)|(?:too\smany\sauthentication\sfailures)|(?:Authentication\sfailed)|(?:EHLO\sSMTP\sblocking\srule)|(?:IP\sblocked\sby\sbrute\sforce\sabuse\sdetection\srule)|(?:IP\sis\sblacklisted)|(?:Mail\srejected\sdue\sto\sSMTP\sSpam\sBlocking)|(?:Too\smany\sauthentication\sfailures))",
                @"",
                @"",
                @"",
                "Windows", "SmarterMail",

                "C:/Program Files (x86)/Mail Enable/Logging/SMTP/SMTP-Activity-*.log\nC:/Program Files/Mail Enable/Logging/SMTP/SMTP-Activity-*.log\nC:/Program Files (x86)/Mail Enable/Logging/IMAP\nC:/Program Files/Mail Enable/Logging/IMAP",
                @"^(?<timestamp>[0-9\/:\s]+)SMTP\-IN\s+[^\s]+\s+[^\s]+\s(?<ipaddress>[^\s]+)\s+[^\s]+\s+[^\s]+\s+[^\s]+\s+Invalid\sUsername\sor\sPassword\s+[^\s]+\s+[^\s]+\s+(?<username>[^\n]+)$|^(?<timestamp>[0-9\/:\s]+)IMAP\-IN\s+[^\s]+\s+(?<ipaddress>[^\s]+)\s+LOGIN\s+LOGIN\s+""(?<username>[^""]+)""\s+""[^""]+""\s+[^\s]+\s+NO\s+LOGIN\s+Failed\s+[^\s]+\s+Invalid\s+username\s+or\s+password[^\n]*$",
                @"MM/dd/yy HH:mm:ss",
                @"",
                @"",
                "Windows", "MailEnable",

                "C:/Program Files/Tomcat/logs/**/*access_log*.txt\n/var/log/httpd/access_log",
                @"^(?<ipaddress>[^\s]+)\s.*?\[(?<timestamp>.*?)\].*?(?:(?:\s40[034]\s(-|[0-9]+))|((php|md5sum|cgi-bin|joomla).*?\s404\s[0-9]+|\s400\s-))[^\n]*",
                @"dd/MMM/yyyy:HH:mm:ss zzzz",
                @"",
                @"",
                "Windows|Linux", "Apache",

                "C:/IPBanCustomLogs/**/*.log",
                @"(?<timestamp>\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d(?:\.\d+)?Z?)?(?:,\s)?ipban\sfailed\slogin,\sip\saddress:\s(?<ipaddress>[^,\n]+),\ssource:\s(?<source>[^,\n]+)?,\suser:\s(?<username>[^\s,]+)?",
                @"",
                @"(?<timestamp>\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d(?:\.\d+)?Z?)?(?:,\s)?ipban\ssuccess\slogin,\sip\saddress:\s(?<ipaddress>[^,\n]+),\ssource:\s(?<source>[^,\n]+)?,\suser:\s(?<username>[^\s,]+)?",
                @"",
                "Windows", "IPBanCustom"
            };

            Assert.AreEqual(logFileData.Length / 7, cfg.LogFilesToParse.Count);
            for (int i = 0; i < logFileData.Length; i += 7)
            {
                AssertLogFileToParse(cfg.LogFilesToParse[i / 7],
                                     (string)logFileData[i + 1],
                                     (string)logFileData[i + 2],
                                     maxFileSize,
                                     (string)logFileData[i],
                                     pingInterval,
                                     (string)logFileData[i + 5],
                                     (string)logFileData[i + 6],
                                     (string)logFileData[i + 3],
                                     (string)logFileData[i + 4]);
            }
        }
Example #22
0
        private void AssertLogFilesToParse(IPBanConfig cfg)
        {
            const int maxFileSize  = 16777216;
            const int pingInterval = 10000;

            // path and mask, fail expression, fail timestamp format, success expression, success timestamp format, platform regex, source
            object[] logFileData = new object[]
            {
                "/var/log/auth*.log\n/var/log/secure*",
                @"failed\s+password\s+for\s+(invalid\s+user\s+)?(?<username>[^\s]+)\s+from\s+(?<ipaddress>[^\s]+)\s+port\s+[0-9]+\s+ssh|did\s+not\s+receive\s+identification\s+string\s+from\s+(?<ipaddress>[^\s]+)|connection\s+closed\s+by\s+((invalid\s+user\s+)?(?<username>[^\s]+)\s+)?(?<ipaddress>[^\s]+)\s+port\s+[0-9]+\s+\[preauth\]|disconnected\s+from\s+(invalid\s+user\s+)?(?<username>[^\s]+)\s+(?<ipaddress>[^\s]+)\s+port\s+[0-9]+\s+\[preauth\]|disconnected\s+from\s+(?<ipaddress>[^\s]+)\s+port\s+[0-9]+\s+\[preauth\]|disconnected\s+from\s+authenticating\s+user\s+(?<username>[^\s]+)\s+(?<ipaddress>[^\s]+)\s+port\s+[0-9]+\s+\[preauth\]",
                @"",
                @"Accepted\s+password\s+for\s+(?<username>[^\s]+)\s+from\s+(?<ipaddress>[^\s]+)\s+port\s+[0-9]+\s+ssh",
                @"",
                "Linux", "SSH",

                "/var/log/ipbancustom*.log",
                @"(?<timestamp>\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d\.?\d*Z?,\s)?ipban\sfailed\slogin,\sip\saddress:\s(?<ipaddress>[^,\n]+),\ssource:\s(?<source>[^,\n]+),\suser:\s?(?<username>[^\s,]+)?",
                @"",
                @"(?<timestamp>\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d\.?\d*Z?,\s)?ipban\ssuccess\slogin,\sip\saddress:\s(?<ipaddress>[^,\n]+),\ssource:\s(?<source>[^,\n]+),\suser:\s?(?<username>[^\s,]+)?",
                @"",
                "Linux", "IPBanCustom",

                "C:/Program Files/Microsoft/Exchange Server/*/TransportRoles/Logs/FrontEnd/ProtocolLog/**.log",
                @"^(?<timestamp>[0-9TZ\-:\.]+),(?:[^,\n]*,){3}(?:(?<ipaddress>[^,\n]+),(?<username>[^,\n]*),.*?AuthFailed[^\n]*|(?:[^,\n]*,)(?<ipaddress>[^,\n]+),(?:[^,\n]*,){2}.*?\sof\sLogonDenied\n.*?User\sName:\s(?<username>[^\n]*))\n",
                @"",
                @"^(?<timestamp>[0-9TZ\-:\.]+)?,(?:[^,\n]*,){4}(?<ipaddress>[^,\n]+),(?:[^,\n]*),(?<username>[^,\n]*),authenticated",
                @"",
                "Windows", "MSExchange",

                "C:/Program Files/Smarter Tools/Smarter Mail/**/*.log\nC:/Program Files (x86)/Smarter Tools/Smarter Mail/**/*.log\nC:/SmarterMail/logs/**/*.log\nC:/Smarter Mail/logs/**/*.log",
                @"\[(?<ipaddress>[^\]\n]+)\](?:\[[^\]\n]*\]\s+).*?(?:(?:The\sdomain\sgiven\sin\sthe\sEHLO\scommand\sviolates\san\sEHLO\sSMTP)|(?:IP\sblocked\sby\sbrute\sforce\sabuse\sdetection\srule)|(?:login\sfailed)|(?:IP\sblocked\sby\sbrute\sforce\sabuse\sdetection\srule)|(?:IP\sis\sblacklisted)|(?:too\smany\sauthentication\sfailures)|(?:Authentication\sfailed)|(?:EHLO\sSMTP\sblocking\srule)|(?:IP\sblocked\sby\sbrute\sforce\sabuse\sdetection\srule)|(?:IP\sis\sblacklisted)|(?:Mail\srejected\sdue\sto\sSMTP\sSpam\sBlocking)|(?:Too\smany\sauthentication\sfailures))",
                @"",
                @"",
                @"",
                "Windows", "SmarterMail",

                "C:/Program Files/Tomcat/logs/**/*access_log*.txt",
                @"^(?<ipaddress>[^\s]+)\s.*?\[(?<timestamp>.*?)\].*?((php|md5sum|cgi-bin|joomla).*?\s404\s[0-9]+|\s400\s-)$",
                @"dd/MMM/yyyy:HH:mm:ss zzzz",
                @"",
                @"",
                "Windows", "Apache",

                "C:/IPBanCustomLogs/**/*.log",
                @"(?<timestamp>\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d\.?\d*Z?,\s)?ipban\sfailed\slogin,\sip\saddress:\s(?<ipaddress>[^,\n]+),\ssource:\s(?<source>[^,\n]+),\suser:\s?(?<username>[^\s,]+)?",
                @"",
                @"(?<timestamp>\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d\.?\d*Z?,\s)?ipban\ssuccess\slogin,\sip\saddress:\s(?<ipaddress>[^,\n]+),\ssource:\s(?<source>[^,\n]+),\suser:\s?(?<username>[^\s,]+)?",
                @"",
                "Windows", "IPBanCustom"
            };

            Assert.AreEqual(logFileData.Length / 7, cfg.LogFilesToParse.Count);
            for (int i = 0; i < logFileData.Length; i += 7)
            {
                AssertLogFileToParse(cfg.LogFilesToParse[i / 7],
                                     (string)logFileData[i + 1],
                                     (string)logFileData[i + 2],
                                     maxFileSize,
                                     (string)logFileData[i],
                                     pingInterval,
                                     (string)logFileData[i + 5],
                                     (string)logFileData[i + 6],
                                     (string)logFileData[i + 3],
                                     (string)logFileData[i + 4]);
            }
        }
Example #23
0
 /// <summary>
 /// Config from ConfigXml
 /// </summary>
 public IPBanConfig GetConfig() => config ??= IPBanConfig.LoadFromXml(ConfigXml);