Example #1
0
 private void UpdateLogFiles(IPBanConfig newConfig)
 {
     // remove existing log files that are no longer in config
     foreach (IPBanLogFileScanner file in logFilesToParse.ToArray())
     {
         if (newConfig.LogFilesToParse.FirstOrDefault(f => f.PathsAndMasks.Contains(file.PathAndMask)) is null)
         {
             file.Dispose();
             logFilesToParse.Remove(file);
         }
     }
     foreach (IPBanLogFileToParse newFile in newConfig.LogFilesToParse)
     {
         string[] pathsAndMasks = newFile.PathsAndMasks;
         for (int i = 0; i < pathsAndMasks.Length; i++)
         {
             string pathAndMask = pathsAndMasks[i];
             if (!string.IsNullOrWhiteSpace(pathAndMask))
             {
                 // if we don't have this log file and the platform matches, add it
                 bool noMatchingLogFile = logFilesToParse.FirstOrDefault(f => f.PathAndMask == pathAndMask) is null;
                 bool platformMatches   = !string.IsNullOrWhiteSpace(newFile.PlatformRegex) &&
                                          Regex.IsMatch(OSUtility.Description, newFile.PlatformRegex.ToString().Trim(), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
                 if (noMatchingLogFile && platformMatches)
                 {
                     // log files use a timer internally and do not need to be updated regularly
                     IPBanIPAddressLogFileScannerOptions options = new IPBanIPAddressLogFileScannerOptions
                     {
                         Dns                         = service.DnsLookup,
                         LoginHandler                = service,
                         MaxFileSizeBytes            = newFile.MaxFileSize,
                         PathAndMask                 = pathAndMask,
                         PingIntervalMilliseconds    = (service.ManualCycle ? 0 : newFile.PingInterval),
                         RegexFailure                = newFile.FailedLoginRegex,
                         RegexSuccess                = newFile.SuccessfulLoginRegex,
                         RegexFailureTimestampFormat = newFile.FailedLoginRegexTimestampFormat,
                         RegexSuccessTimestampFormat = newFile.SuccessfulLoginRegexTimestampFormat,
                         Source                      = newFile.Source,
                         FailedLoginThreshold        = newFile.FailedLoginThreshold
                     };
                     IPBanLogFileScanner scanner = new IPBanLogFileScanner(options);
                     logFilesToParse.Add(scanner);
                     Logger.Info("Adding log file to parse: {0}", pathAndMask);
                 }
                 else
                 {
                     Logger.Trace("Ignoring log file path {0}, regex: {1}, no matching file: {2}, platform match: {3}",
                                  pathAndMask, newFile.PlatformRegex, noMatchingLogFile, platformMatches);
                 }
             }
         }
     }
 }
Example #2
0
 private void UpdateLogFiles(IPBanConfig newConfig)
 {
     // remove existing log files that are no longer in config
     foreach (LogFileScanner file in logFilesToParse.ToArray())
     {
         if (newConfig.LogFilesToParse.FirstOrDefault(f => f.PathsAndMasks.Contains(file.PathAndMask)) is null)
         {
             file.Dispose();
             logFilesToParse.Remove(file);
         }
     }
     foreach (IPBanLogFileToParse newFile in newConfig.LogFilesToParse)
     {
         string[] pathsAndMasks = newFile.PathAndMask.Split('\n');
         for (int i = 0; i < pathsAndMasks.Length; i++)
         {
             string pathAndMask = pathsAndMasks[i].Trim();
             if (pathAndMask.Length != 0)
             {
                 // if we don't have this log file and the platform matches, add it
                 if (logFilesToParse.FirstOrDefault(f => f.PathAndMask == pathAndMask) is null &&
                     !string.IsNullOrWhiteSpace(newFile.PlatformRegex) &&
                     Regex.IsMatch(OSUtility.Description, newFile.PlatformRegex.ToString().Trim(), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant))
                 {
                     // log files use a timer internally and do not need to be updated regularly
                     IPBanIPAddressLogFileScannerOptions options = new IPBanIPAddressLogFileScannerOptions
                     {
                         Dns                         = DnsLookup,
                         LoginHandler                = this,
                         MaxFileSizeBytes            = newFile.MaxFileSize,
                         PathAndMask                 = pathAndMask,
                         PingIntervalMilliseconds    = newFile.PingInterval,
                         Recursive                   = newFile.Recursive,
                         RegexFailure                = newFile.FailedLoginRegex,
                         RegexSuccess                = newFile.SuccessfulLoginRegex,
                         RegexFailureTimestampFormat = newFile.FailedLoginRegexTimestampFormat,
                         RegexSuccessTimestampFormat = newFile.SuccessfulLoginRegexTimestampFormat,
                         Source                      = newFile.Source
                     };
                     LogFileScanner scanner = new IPBanIPAddressLogFileScanner(options);
                     logFilesToParse.Add(scanner);
                     Logger.Debug("Adding log file to parse: {0}", pathAndMask);
                 }
                 else
                 {
                     Logger.Debug("Ignoring log file path {0}, regex: {1}", pathAndMask, newFile.PlatformRegex);
                 }
             }
         }
     }
Example #3
0
        internal async Task UpdateConfiguration()
        {
            try
            {
                ConfigFilePath = (!File.Exists(ConfigFilePath) ? Path.Combine(AppContext.BaseDirectory, IPBanService.ConfigFileName) : ConfigFilePath);
                string newXml = await ConfigReaderWriter.CheckForConfigChange();

                if (!string.IsNullOrWhiteSpace(newXml))
                {
                    IPBanConfig oldConfig = Config;
                    IPBanConfig newConfig = IPBanConfig.LoadFromXml(newXml, DnsLookup);
                    ConfigChanged?.Invoke(newConfig);
                    whitelistChanged = (Config is null || Config.Whitelist != newConfig.Whitelist || Config.WhitelistRegex != newConfig.WhitelistRegex);
                    Config           = newConfig;
                    LoadFirewall(oldConfig);
                    ParseAndAddUriFirewallRules(newConfig);
                    Logger.Info("Config file changed");
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
            }

            if (Config is null)
            {
                throw new ApplicationException("Configuration failed to load, make sure to check for XML errors or unblock all the files.");
            }
            if (Firewall is null)
            {
                throw new ApplicationException("Firewall failed to load, check that your firewall is enabled and setup in configuration properly");
            }

            // set or unset default banned ip address handler based on config
            if (Config.UseDefaultBannedIPAddressHandler && BannedIPAddressHandler is null)
            {
                BannedIPAddressHandler = new DefaultBannedIPAddressHandler();
            }
            else if (!Config.UseDefaultBannedIPAddressHandler && BannedIPAddressHandler != null && BannedIPAddressHandler is DefaultBannedIPAddressHandler)
            {
                BannedIPAddressHandler = NullBannedIPAddressHandler.Instance;
            }

            // will only execute once
            UpdateBannedIPAddressesOnStart();

            // will only execute once
            SetupWindowsEventViewer();
        }
Example #4
0
        private void ParseAndAddUriFirewallRules(IPBanConfig newConfig)
        {
            List <IPBanUriFirewallRule> toRemove = new List <IPBanUriFirewallRule>(updaters.Where(u => u is IPBanUriFirewallRule).Select(u => u as IPBanUriFirewallRule));

            using StringReader reader = new StringReader(newConfig.FirewallUriRules);
            string line;

            while ((line = reader.ReadLine()) != null)
            {
                line = line.Trim();
                string[] pieces = line.Split(',');
                if (pieces.Length == 3)
                {
                    if (TimeSpan.TryParse(pieces[1], out TimeSpan interval))
                    {
                        if (Uri.TryCreate(pieces[2], UriKind.Absolute, out Uri uri))
                        {
                            string rulePrefix            = pieces[0];
                            IPBanUriFirewallRule newRule = new IPBanUriFirewallRule(Firewall, this, RequestMaker, rulePrefix, interval, uri);
                            if (updaters.Where(u => u.Equals(newRule)).FirstOrDefault() is IPBanUriFirewallRule existingRule)
                            {
                                // exact duplicate rule, do nothing
                                toRemove.Remove(existingRule);
                            }
                            else
                            {
                                // new rule, add it
                                updaters.Add(newRule);
                            }
                        }
                        else
                        {
                            Logger.Warn("Invalid uri format in uri firewall rule {0}", line);
                        }
                    }
                    else
                    {
                        Logger.Warn("Invalid timestamp format in uri firewall rule {0}", line);
                    }
                }
            }

            // remove any left-over rules that were not in the new config
            foreach (IPBanUriFirewallRule updater in toRemove.ToArray())
            {
                updater.DeleteRule();
                RemoveUpdater(updater);
            }
        }
Example #5
0
        internal async Task UpdateConfiguration()
        {
            try
            {
                ConfigFilePath = (!File.Exists(ConfigFilePath) ? Path.Combine(AppContext.BaseDirectory, IPBanConfig.DefaultFileName) : ConfigFilePath);
                var configChange = await ConfigReaderWriter.CheckForConfigChange();

                if (!string.IsNullOrWhiteSpace(configChange.Item1))
                {
                    IPBanConfig oldConfig = Config;
                    IPBanConfig newConfig = IPBanConfig.LoadFromXml(configChange.Item1, DnsLookup, DnsList, RequestMaker);
                    ConfigChanged?.Invoke(newConfig);
                    whitelistChanged = (Config is null || Config.Whitelist != newConfig.Whitelist || Config.WhitelistRegex != newConfig.WhitelistRegex);
                    Config           = newConfig;
                    LoadFirewall(oldConfig);
                    ParseAndAddUriFirewallRules(newConfig);

                    // if the config change was not a force refresh with no actual config values changed, log it
                    if (!configChange.Item2)
                    {
                        Logger.Info("Config file changed");
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
            }

            if (Config is null)
            {
                throw new ApplicationException("Configuration failed to load, make sure to check for XML errors or unblock all the files.");
            }
            if (Firewall is null)
            {
                throw new ApplicationException("Firewall failed to load, check that your firewall is enabled and setup in configuration properly");
            }

            // set or unset default banned ip address handler based on config
            if (Config.UseDefaultBannedIPAddressHandler && BannedIPAddressHandler is null)
            {
                BannedIPAddressHandler = new DefaultBannedIPAddressHandler();
            }
            else if (!Config.UseDefaultBannedIPAddressHandler && BannedIPAddressHandler != null && BannedIPAddressHandler is DefaultBannedIPAddressHandler)
            {
                BannedIPAddressHandler = NullBannedIPAddressHandler.Instance;
            }
        }
Example #6
0
        /// <summary>
        /// Create a log file scanner
        /// </summary>
        /// <param name="options">Options</param>
        public IPBanLogFileScanner(IPBanIPAddressLogFileScannerOptions options) : base(options.PathAndMask, options.MaxFileSizeBytes, options.PingIntervalMilliseconds)
        {
            options.ThrowIfNull(nameof(options));
            options.LoginHandler.ThrowIfNull(nameof(options.LoginHandler));
            options.Dns.ThrowIfNull(nameof(options.Dns));
            Source = options.Source;

            this.loginHandler = options.LoginHandler;
            this.dns          = options.Dns;

            this.regexFailure = IPBanConfig.ParseRegex(options.RegexFailure, true);
            this.regexFailureTimestampFormat = options.RegexFailureTimestampFormat;

            this.regexSuccess = IPBanConfig.ParseRegex(options.RegexSuccess, true);
            this.regexSuccessTimestampFormat = options.RegexSuccessTimestampFormat;
        }
 /// <summary>
 /// Create a log file scanner
 /// </summary>
 /// <param name="loginHandler">Interface for handling logins</param>
 /// <param name="dns">Interface for dns lookup</param>
 /// <param name="source">The source, i.e. SSH or SMTP, etc.</param>
 /// <param name="pathAndMask">File path and mask (i.e. /var/log/auth*.log)</param>
 /// <param name="recursive">Whether to parse all sub directories of path and mask recursively</param>
 /// <param name="regexFailure">Regex to parse file lines to pull out failed login ipaddress and username</param>
 /// <param name="regexSuccess">Regex to parse file lines to pull out successful login ipaddress and username</param>
 /// <param name="maxFileSizeBytes">Max size of file (in bytes) before it is deleted or 0 for unlimited</param>
 /// <param name="pingIntervalMilliseconds">Ping interval in milliseconds, less than 1 for manual ping required</param>
 public IPBanIPAddressLogFileScanner
 (
     IIPAddressEventHandler loginHandler,
     IDnsLookup dns,
     string source,
     string pathAndMask,
     bool recursive,
     string regexFailure,
     string regexSuccess,
     long maxFileSizeBytes        = 0,
     int pingIntervalMilliseconds = 0
 ) : base(pathAndMask, recursive, maxFileSizeBytes, pingIntervalMilliseconds)
 {
     loginHandler.ThrowIfNull(nameof(loginHandler));
     dns.ThrowIfNull(nameof(dns));
     Source            = source;
     this.loginHandler = loginHandler;
     this.dns          = dns;
     this.regexFailure = IPBanConfig.ParseRegex(regexFailure);
     this.regexSuccess = IPBanConfig.ParseRegex(regexSuccess);
 }
Example #8
0
        /// <summary>
        /// Check if an ip address range is whitelisted
        /// </summary>
        /// <param name="range">Range</param>
        /// <returns>True if whitelisted, false otherwise</returns>
        public bool IsWhitelisted(IPAddressRange range)
        {
            IPBanConfig config = Config;

            return(config != null && Config.IsWhitelisted(range));
        }
Example #9
0
        /// <summary>
        /// Check if an entry is whitelisted
        /// </summary>
        /// <param name="entry">Entry</param>
        /// <returns>True if whitelisted, false otherwise</returns>
        public bool IsWhitelisted(string entry)
        {
            IPBanConfig config = Config;

            return(config != null && config.IsWhitelisted(entry));
        }
Example #10
0
 /// <inheritdoc />
 public IIPBanFirewall CreateFirewall(IPBanConfig config, IIPBanFirewall previousFirewall)
 {
     return(IPBanFirewallUtility.CreateFirewall(config.FirewallRulePrefix, previousFirewall));
 }
Example #11
0
        private void LoadFirewall(IPBanConfig oldConfig)
        {
            IIPBanFirewall existing = Firewall;

            Firewall = FirewallCreator.CreateFirewall(Config, Firewall);
            if (existing != Firewall)
            {
                AddUpdater(Firewall);
                Logger.Warn("Loaded firewall type {0}", Firewall.GetType());
                if (existing != null)
                {
                    RemoveUpdater(existing);

                    // transfer banned ip to new firewall
                    Firewall.BlockIPAddresses(null, ipDB.EnumerateBannedIPAddresses()).Sync();
                }
            }

            if (oldConfig is null)
            {
                // clear out all previous custom rules
                foreach (string rule in Firewall.GetRuleNames(Firewall.RulePrefix + "EXTRA_").ToArray())
                {
                    Firewall.DeleteRule(rule);
                }
            }
            else
            {
                // check for updated / new / removed block rules
                List <string> deleteList = new List <string>(oldConfig.ExtraRules.Select(r => r.Name));

                // cleanup rules that are no longer in the config
                foreach (string newRule in Config.ExtraRules.Select(r => r.Name))
                {
                    deleteList.Remove(newRule);
                }
                foreach (string rule in deleteList)
                {
                    foreach (string ruleName in Firewall.GetRuleNames(rule).ToArray())
                    {
                        Firewall.DeleteRule(ruleName);
                    }
                }
            }

            // ensure firewall is cleared out if needed - will only execute once
            UpdateBannedIPAddressesOnStart();

            // ensure windows event viewer is setup if needed - will only execute once
            SetupWindowsEventViewer();

            // add/update global rules
            Firewall.AllowIPAddresses("GlobalWhitelist", Config.Whitelist);
            Firewall.BlockIPAddresses("GlobalBlacklist", Config.BlackList);

            // add/update user specified rules
            foreach (IPBanFirewallRule rule in Config.ExtraRules)
            {
                if (rule.Block)
                {
                    Firewall.BlockIPAddresses(rule.Name, rule.IPAddressRanges, rule.AllowPortRanges);
                }
                else
                {
                    Firewall.AllowIPAddresses(rule.Name, rule.IPAddressRanges, rule.AllowPortRanges);
                }
            }
        }
        /// <summary>
        /// Test a log file
        /// </summary>
        /// <param name="fileName">Log file</param>
        public static void RunLogFileTest(string fileName,
                                          string regexFailureFile,
                                          string regexFailureTimestampFormat,
                                          string regexSuccessFile,
                                          string regexSuccessTimestampFormat)
        {
            IPBanLogFileScanner scanner = new(new()
            {
                Dns = new DefaultDnsLookup(),
                FailedLoginThreshold = 3,
                FailedLogLevel = LogLevel.Warning,
                LoginHandler = new LogFileWriter(),
                MaxFileSizeBytes = 0,
                PathAndMask = fileName.Trim(),
                PingIntervalMilliseconds = 0,
                RegexFailure = (File.Exists(regexFailureFile) && regexFailureFile.Length > 2 ? IPBanConfig.ParseRegex(File.ReadAllText(regexFailureFile)) : null),
                RegexFailureTimestampFormat = regexFailureTimestampFormat.Trim('.'),
                RegexSuccess = (File.Exists(regexSuccessFile) && regexSuccessFile.Length > 2 ? IPBanConfig.ParseRegex(File.ReadAllText(regexSuccessFile)) : null),
                RegexSuccessTimestampFormat = regexSuccessTimestampFormat.Trim('.'),
                Source = "test",
                SuccessfulLogLevel = LogLevel.Warning
            });

            // start with empty file
            File.Move(fileName, fileName + ".temp");
            File.WriteAllText(fileName, string.Empty);

            // read the empty file
            scanner.ProcessFiles();

            // get rid of the empty file
            File.Delete(fileName);

            // put the full file back
            File.Move(fileName + ".temp", fileName);

            // now the scanner will process the entire file
            scanner.ProcessFiles();
        }
Example #13
0
 /// <inheritdoc />
 public IIPBanFirewall CreateFirewall(System.Collections.Generic.IReadOnlyCollection <Type> allTypes,
                                      IPBanConfig config,
                                      IIPBanFirewall previousFirewall)
 {
     return(IPBanFirewallUtility.CreateFirewall(allTypes, config.FirewallRulePrefix, previousFirewall));
 }