Пример #1
0
        /// <summary>
        /// Process event viewer XML
        /// </summary>
        /// <param name="xml">XML</param>
        /// <param name="testing">True if testing, false otherwise</param>
        public void ProcessEventViewerXml(string xml, bool testing = false)
        {
            IPBanLog.Write(LogLevel.Information, "Processing xml: {0}", xml);

            XmlDocument doc = ParseXml(xml);

            ExtractEventViewerXml(doc, out string ipAddress, out string source, out string userName);
            if (AddFailedLoginForEventViewerXml(ipAddress, source, userName, doc) && testing)
            {
                Console.WriteLine("Found {0}, {1}, {2}", ipAddress, source, userName);
            }
        }
Пример #2
0
        private HashSet <WatchedFile> UpdateWatchedFiles()
        {
            HashSet <WatchedFile> watchedFilesCopy = new HashSet <WatchedFile>();

            try
            {
                // read in existing files that match the mask in the directory being watched
                if (Directory.Exists(directoryToWatch))
                {
                    foreach (string file in Directory.EnumerateFiles(directoryToWatch, fileMask, SearchOption.TopDirectoryOnly))
                    {
                        watchedFilesCopy.Add(new WatchedFile(file, new FileInfo(file).Length));
                    }
                }
            }
            catch
            {
                // nothing to do here, something failed enumerating the directory files
            }

            lock (watchedFiles)
            {
                // remove files that no longer exist
                foreach (WatchedFile existing in watchedFiles.ToArray())
                {
                    if (!watchedFilesCopy.Contains(existing))
                    {
                        IPBanLog.Debug("Removing parsed log file {0}", existing.FileName);
                        watchedFiles.Remove(existing);
                    }
                }

                // add new files
                foreach (WatchedFile newFile in watchedFilesCopy)
                {
                    // add the file, will fail if it already exists
                    if (watchedFiles.Add(newFile))
                    {
                        IPBanLog.Debug("Adding parsed log file {0}", newFile.FileName);
                    }
                }

                // make a copy so we can enumerate outside a lock
                watchedFilesCopy.Clear();
                foreach (WatchedFile file in watchedFiles)
                {
                    watchedFilesCopy.Add(file);
                }
            }

            return(watchedFilesCopy);
        }
Пример #3
0
 public Task <bool> AllowIPAddresses(IEnumerable <string> ipAddresses, CancellationToken cancelToken = default)
 {
     try
     {
         allowedIPAddresses = UpdateRule(allowRuleName, "ACCEPT", ipAddresses, allowedIPAddresses, "ip", allowRuleMaxCount, false, null, cancelToken, out bool result);
         return(Task.FromResult <bool>(result));
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex);
         return(Task.FromResult <bool>(false));
     }
 }
Пример #4
0
 public Task <bool> BlockIPAddresses(IEnumerable <string> ipAddresses, CancellationToken cancelToken = default)
 {
     try
     {
         bannedIPAddresses = UpdateRule(blockRuleName, "DROP", ipAddresses, bannedIPAddresses, "ip", blockRuleMaxCount, false, null, cancelToken, out bool result);
         return(Task.FromResult(result));
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex);
         return(Task.FromResult(false));
     }
 }
Пример #5
0
        private int RunProcess(string program, bool requireExitCode, string commandLine, params object[] args)
        {
            commandLine = program + " " + string.Format(commandLine, args);
            commandLine = "-c \"" + commandLine.Replace("\"", "\\\"") + "\"";
            IPBanLog.Write(LogLevel.Debug, "Running firewall process: /bin/bash {0}", commandLine);
            Process p = Process.Start("/bin/bash", commandLine);

            p.WaitForExit();
            if (requireExitCode && p.ExitCode != 0)
            {
                IPBanLog.Write(LogLevel.Error, "Process {0} {1} had exit code {2}", program, commandLine, p.ExitCode);
            }
            return(p.ExitCode);
        }
Пример #6
0
 /// <summary>
 /// Update - if the text file path exists, all ip addresses from each line will be unbanned
 /// </summary>
 public void Update()
 {
     try
     {
         if (File.Exists(textFilePath))
         {
             UnbanIPAddresses(File.ReadLines(textFilePath));
             File.Delete(textFilePath);
         }
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex);
     }
 }
Пример #7
0
        public void UnblockIPAddresses(IEnumerable <string> ipAddresses)
        {
            try
            {
                lock (policy)
                {
                    for (int i = 0; ; i += MaxIpAddressesPerRule)
                    {
                        string ruleName = RulePrefix + i.ToString(CultureInfo.InvariantCulture);
                        try
                        {
                            INetFwRule rule = policy.Rules.Item(ruleName);
                            if (rule == null)
                            {
                                // no more rules to check
                                break;
                            }
                            string remoteIPs = rule.RemoteAddresses;
                            foreach (string ipAddress in ipAddresses)
                            {
                                remoteIPs = Regex.Replace(remoteIPs, ipAddress.Replace(".", "\\.") + "\\/[^,]+,?", ",", RegexOptions.IgnoreCase);
                                remoteIPs = remoteIPs.Replace(",,", ",");
                                remoteIPs = remoteIPs.Trim().Trim(',');
                            }

                            // ensure we don't have a block rule with no ip addresses, this will block the entire world (WTF Microsoft)...
                            if (string.IsNullOrWhiteSpace(remoteIPs))
                            {
                                policy.Rules.Remove(rule.Name);
                            }
                            else
                            {
                                rule.RemoteAddresses = remoteIPs;
                            }
                        }
                        catch
                        {
                            // no more rules to check
                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                IPBanLog.Error(ex);
            }
        }
Пример #8
0
        /// <summary>
        /// Process a line, checking for ip addresses
        /// </summary>
        /// <param name="line">Line to process</param>
        /// <returns>True</returns>
        protected override bool OnProcessLine(string line)
        {
            IPBanLog.Debug("Parsing log file line {0}...", line);
            IPAddressLogInfo info = IPBanService.GetIPAddressInfoFromRegex(dns, regex, line);

            if (info.FoundMatch)
            {
                info.Source = info.Source ?? Source;
                IPBanLog.Debug("Log file found match, ip: {0}, user: {1}, source: {2}, count: {3}", info.IPAddress, info.UserName, info.Source, info.Count);
                failedLogin.AddFailedLogin(info);
            }
            else
            {
                IPBanLog.Debug("No match for line {0}", line);
            }

            return(true);
        }
Пример #9
0
 public bool BlockIPAddresses(IReadOnlyList <string> ipAddresses)
 {
     try
     {
         int i;
         for (i = 0; i < ipAddresses.Count; i += maxIpAddressesPerRule)
         {
             CreateBlockRule(ipAddresses, i, maxIpAddressesPerRule);
         }
         DeleteRules(i);
         return(true);
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex);
         return(false);
     }
 }
Пример #10
0
 public Task <bool> AllowIPAddresses(IEnumerable <string> ipAddresses, CancellationToken cancelToken = default)
 {
     try
     {
         List <string> ipAddressesList = new List <string>();
         int           i = 0;
         foreach (string ipAddress in ipAddresses)
         {
             if (cancelToken.IsCancellationRequested)
             {
                 throw new OperationCanceledException();
             }
             ipAddressesList.Add(ipAddress);
             if (ipAddressesList.Count == MaxIpAddressesPerRule)
             {
                 string remoteIP = CreateRuleStringForIPAddresses(ipAddressesList, i, MaxIpAddressesPerRule);
                 GetOrCreateRule(allowRulePrefix + i.ToString(CultureInfo.InvariantCulture), remoteIP, NET_FW_ACTION_.NET_FW_ACTION_ALLOW);
                 i += MaxIpAddressesPerRule;
                 ipAddressesList.Clear();
             }
         }
         if (cancelToken.IsCancellationRequested)
         {
             throw new OperationCanceledException();
         }
         if (ipAddressesList.Count != 0)
         {
             string remoteIP = CreateRuleStringForIPAddresses(ipAddressesList, i, MaxIpAddressesPerRule);
             GetOrCreateRule(allowRulePrefix + i.ToString(CultureInfo.InvariantCulture), remoteIP, NET_FW_ACTION_.NET_FW_ACTION_ALLOW);
             i += MaxIpAddressesPerRule;
         }
         if (cancelToken.IsCancellationRequested)
         {
             throw new OperationCanceledException();
         }
         DeleteRules(allowRulePrefix, i);
         return(Task.FromResult <bool>(true));
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex);
         return(Task.FromResult <bool>(false));
     }
 }
Пример #11
0
        public Task <bool> BlockIPAddresses(string ruleNamePrefix, IEnumerable <IPAddressRange> ranges, IEnumerable <PortRange> allowedPorts, CancellationToken cancelToken = default)
        {
            if (string.IsNullOrWhiteSpace(ruleNamePrefix))
            {
                return(Task.FromResult(false));
            }

            try
            {
                string ruleName = RulePrefix + "_" + ruleNamePrefix + "_0";
                UpdateRule(ruleName, "DROP", ranges.Select(r => r.ToCidrString()), null, "net", blockRuleRangesMaxCount, true, allowedPorts, cancelToken, out bool result);
                return(Task.FromResult(result));
            }
            catch (Exception ex)
            {
                IPBanLog.Error(ex);
                return(Task.FromResult(false));
            }
        }
Пример #12
0
 private static void LoadVersionFromWmiApi()
 {
     try
     {
         // WMI API sometimes fails to initialize on .NET core on some systems, not sure why...
         // fall-back to WMI, maybe future .NET core versions will fix the bug
         using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT Caption, Version FROM Win32_OperatingSystem"))
         {
             foreach (var result in searcher.Get())
             {
                 FriendlyName = result["Caption"] as string;
                 Version      = result["Version"] as string;
                 break;
             }
         }
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex, "Unable to load os version from wmi api");
     }
 }
Пример #13
0
 public Task <bool> BlockIPAddresses(IEnumerable <string> ipAddresses, CancellationToken cancelToken = default)
 {
     try
     {
         int           i = 0;
         List <string> ipAddressesList = new List <string>();
         foreach (string ipAddress in ipAddresses)
         {
             if (cancelToken.IsCancellationRequested)
             {
                 throw new OperationCanceledException(cancelToken);
             }
             ipAddressesList.Add(ipAddress);
             if (ipAddressesList.Count == MaxIpAddressesPerRule)
             {
                 CreateBlockRule(ipAddressesList, 0, MaxIpAddressesPerRule, RulePrefix + i.ToStringInvariant());
                 i += MaxIpAddressesPerRule;
                 ipAddressesList.Clear();
             }
         }
         if (cancelToken.IsCancellationRequested)
         {
             throw new OperationCanceledException(cancelToken);
         }
         if (ipAddressesList.Count != 0)
         {
             CreateBlockRule(ipAddressesList, 0, MaxIpAddressesPerRule, RulePrefix + i.ToStringInvariant());
             i += MaxIpAddressesPerRule;
         }
         DeleteRules(RulePrefix, i);
         return(Task.FromResult(true));
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex);
         return(Task.FromResult(false));
     }
 }
Пример #14
0
 public bool IsIPAddressAllowed(string ipAddress)
 {
     try
     {
         lock (policy)
         {
             string ruleName = RulePrefix + "AllowIPAddresses";
             try
             {
                 INetFwRule rule = policy.Rules.Item(ruleName);
                 return(rule != null && rule.RemoteAddresses.Contains(ipAddress));
             }
             catch
             {
                 // OK, rule does not exist
             }
         }
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex);
     }
     return(false);
 }
Пример #15
0
 public bool IsIPAddressBlocked(string ipAddress)
 {
     try
     {
         lock (policy)
         {
             for (int i = 0; ; i += maxIpAddressesPerRule)
             {
                 string ruleName = RulePrefix + i.ToString(CultureInfo.InvariantCulture);
                 try
                 {
                     INetFwRule rule = policy.Rules.Item(ruleName);
                     if (rule == null)
                     {
                         // no more rules to check
                         break;
                     }
                     else if (rule.RemoteAddresses.Contains(ipAddress))
                     {
                         return(true);
                     }
                 }
                 catch
                 {
                     // no more rules to check
                     break;
                 }
             }
         }
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex);
     }
     return(false);
 }
Пример #16
0
 /// <summary>
 /// Get a firewall ip address, clean and normalize
 /// </summary>
 /// <param name="ipAddress">IP Address</param>
 /// <param name="normalizedIP">The normalized ip ready to go in the firewall or null if invalid ip address</param>
 /// <returns>True if ip address can go in the firewall, false otherwise</returns>
 public static bool TryGetFirewallIPAddress(this string ipAddress, out string normalizedIP)
 {
     normalizedIP = ipAddress?.Trim();
     if (string.IsNullOrWhiteSpace(normalizedIP) ||
         normalizedIP == "0.0.0.0" ||
         normalizedIP == "127.0.0.1" ||
         normalizedIP == "::0" ||
         normalizedIP == "::1" ||
         !IPAddressRange.TryParse(normalizedIP, out IPAddressRange range))
     {
         normalizedIP = null;
         return(false);
     }
     try
     {
         normalizedIP = (range.Begin.Equals(range.End) ? range.Begin.ToString() : range.ToCidrString());
     }
     catch (Exception ex)
     {
         IPBanLog.Debug("Failed to normalize ip {0}, it is not a single ip or cidr range: {1}", ipAddress, ex);
         return(false);
     }
     return(true);
 }
Пример #17
0
        static IPBanOS()
        {
            try
            {
                Version     = Environment.OSVersion.VersionString;
                Description = RuntimeInformation.OSDescription;
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                {
                    string tempFile = Path.GetTempFileName();
                    Process.Start("/bin/bash", "-c \"cat /etc/*release* > " + tempFile + "\"").WaitForExit();
                    string versionText = File.ReadAllText(tempFile);
                    File.Delete(tempFile);
                    Name         = IPBanOS.Linux;
                    FriendlyName = ExtractRegex(versionText, "^(Id|Distrib_Id)=(?<value>.*?)$", string.Empty);
                    if (FriendlyName.Length != 0)
                    {
                        string codeName = ExtractRegex(versionText, "^(Name|Distrib_CodeName)=(?<value>.+)$", string.Empty);
                        if (codeName.Length != 0)
                        {
                            FriendlyName += " - " + codeName;
                        }
                        Version = ExtractRegex(versionText, "^Version_Id=(?<value>.+)$", Version);
                    }
                }
                else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    Name = IPBanOS.Windows;
                    string tempFile = Path.GetTempFileName();

                    // .net core WMI has a strange bug where WMI will not initialize on some systems
                    // since this is the only place where WMI is used, we can just work-around it
                    // with the wmic executable, which exists (as of 2018) on all supported Windows.
                    StartProcessAndWait("cmd", "/C wmic path Win32_OperatingSystem get Caption,Version /format:table > \"" + tempFile + "\"");
                    if (File.Exists(tempFile))
                    {
                        string[] lines = File.ReadAllLines(tempFile);
                        File.Delete(tempFile);
                        if (lines.Length > 1)
                        {
                            int versionIndex = lines[0].IndexOf("Version");
                            if (versionIndex >= 0)
                            {
                                FriendlyName = lines[1].Substring(0, versionIndex - 1).Trim();
                                Version      = lines[1].Substring(versionIndex).Trim();
                            }
                        }
                    }
                    else
                    {
                        // fall-back to WMI, maybe future .NET core versions will fix the bug
                        using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT Caption, Version FROM Win32_OperatingSystem"))
                        {
                            foreach (var result in searcher.Get())
                            {
                                FriendlyName = result["Caption"] as string;
                                Version      = result["Version"] as string;
                                break;
                            }
                        }
                    }
                }
                else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                {
                    // TODO: Implement better for MAC
                    Name         = IPBanOS.Mac;
                    FriendlyName = "OSX";
                }
                else
                {
                    Name         = IPBanOS.Unknown;
                    FriendlyName = "Unknown";
                }
            }
            catch (Exception ex)
            {
                IPBanLog.Error(ex);
            }
        }
Пример #18
0
        private void ExtractEventViewerXml(XmlDocument doc, out string ipAddress, out string source, out string userName)
        {
            XmlNode keywordsNode = doc.SelectSingleNode("//Keywords");
            string  keywordsText = keywordsNode.InnerText;

            if (keywordsText.StartsWith("0x"))
            {
                keywordsText = keywordsText.Substring(2);
            }
            ulong keywordsULONG = ulong.Parse(keywordsText, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture);

            ipAddress = source = userName = null;

            if (keywordsNode != null)
            {
                // we must match on keywords
                foreach (ExpressionsToBlockGroup group in service.Config.WindowsEventViewerGetGroupsMatchingKeywords(keywordsULONG))
                {
                    foreach (ExpressionToBlock expression in group.Expressions)
                    {
                        // find all the nodes, try and get an ip from any of them, all must match
                        XmlNodeList nodes = doc.SelectNodes(expression.XPath);

                        if (nodes.Count == 0)
                        {
                            IPBanLog.Write(LogLevel.Information, "No nodes found for xpath {0}", expression.XPath);
                            ipAddress = null;
                            break;
                        }

                        // if there is a regex, it must match
                        if (string.IsNullOrWhiteSpace(expression.Regex))
                        {
                            // count as a match, do not modify the ip address if it was already set
                            IPBanLog.Write(LogLevel.Information, "No regex, so counting as a match");
                        }
                        else
                        {
                            bool foundMatch = false;

                            // try and find an ip from any of the nodes
                            foreach (XmlNode node in nodes)
                            {
                                // if we get a match, stop checking nodes
                                if ((foundMatch = IPBanService.GetIPAddressAndUserNameFromRegex(expression.RegexObject, node.InnerText, ref ipAddress, ref userName)))
                                {
                                    break;
                                }
                            }

                            if (!foundMatch)
                            {
                                // match fail, null out ip, we have to match ALL the nodes or we get null ip and do not ban
                                IPBanLog.Write(LogLevel.Information, "Regex {0} did not match any nodes with xpath {1}", expression.Regex, expression.XPath);
                                ipAddress = null;
                                break;
                            }
                        }
                    }

                    if (ipAddress != null)
                    {
                        source = group.Source;
                        break;
                    }
                    ipAddress = source = userName = null; // set null for the next node attempt
                }
            }
        }
Пример #19
0
        private bool GetOrCreateRule(string ruleName, string remoteIPAddresses, NET_FW_ACTION_ action, IEnumerable <PortRange> allowedPorts = null)
        {
            remoteIPAddresses = (remoteIPAddresses ?? string.Empty).Trim();
            bool emptyIPAddressString = string.IsNullOrWhiteSpace(remoteIPAddresses) || remoteIPAddresses == "*";
            bool ruleNeedsToBeAdded   = false;

            lock (policy)
            {
recreateRule:
                INetFwRule rule = null;
                try
                {
                    rule = policy.Rules.Item(ruleName);
                }
                catch
                {
                    // ignore exception, assume does not exist
                }
                if (rule == null)
                {
                    rule                = Activator.CreateInstance(ruleType) as INetFwRule;
                    rule.Name           = ruleName;
                    rule.Enabled        = true;
                    rule.Action         = action;
                    rule.Description    = "Automatically created by IPBan";
                    rule.Direction      = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN;
                    rule.EdgeTraversal  = false;
                    rule.Grouping       = "IPBan";
                    rule.LocalAddresses = "*";
                    rule.Profiles       = int.MaxValue; // all
                    ruleNeedsToBeAdded  = true;
                }

                // do not ever set an empty string, Windows treats this as * which means everything
                if (!emptyIPAddressString)
                {
                    try
                    {
                        PortRange[] allowedPortsArray = (allowedPorts?.ToArray());
                        if (allowedPortsArray != null && allowedPortsArray.Length != 0)
                        {
                            rule.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP;
                            string localPorts;
                            if (action == NET_FW_ACTION_.NET_FW_ACTION_BLOCK)
                            {
                                localPorts = IPBanFirewallUtility.GetPortRangeStringBlockExcept(allowedPortsArray);
                            }
                            else
                            {
                                localPorts = IPBanFirewallUtility.GetPortRangeStringAllow(allowedPortsArray);
                            }
                            rule.LocalPorts = localPorts;
                        }
                        else
                        {
                            try
                            {
                                rule.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_ANY;
                            }
                            catch
                            {
                                // failed to set protocol to any, we are switching from tcp back to any without ports, the only option is to
                                //  recreate the rule
                                if (!ruleNeedsToBeAdded)
                                {
                                    policy.Rules.Remove(ruleName);
                                    goto recreateRule;
                                }
                            }
                        }
                        rule.RemoteAddresses = remoteIPAddresses;
                    }
                    catch (Exception ex)
                    {
                        // if something failed, do not create the rule
                        emptyIPAddressString = true;
                        IPBanLog.Error(ex);
                    }
                }

                if (emptyIPAddressString || string.IsNullOrWhiteSpace(rule.RemoteAddresses) || rule.RemoteAddresses == "*")
                {
                    // if no ip addresses, remove the rule as it will allow or block everything with an empty RemoteAddresses string
                    try
                    {
                        rule = null;
                        policy.Rules.Remove(ruleName);
                    }
                    catch
                    {
                    }
                }
                else if (ruleNeedsToBeAdded)
                {
                    policy.Rules.Add(rule);
                }
                return(rule != null);
            }
        }
Пример #20
0
        private IPBanConfig(string xml, IDnsLookup dns)
        {
            this.dns = dns;

            // deserialize with XmlDocument, the .net core Configuration class is quite buggy
            XmlDocument doc = new XmlDocument();

            doc.LoadXml(xml);
            foreach (XmlNode node in doc.SelectNodes("//appSettings/add"))
            {
                appSettings[node.Attributes["key"].Value] = node.Attributes["value"].Value;
            }

            GetConfig <int>("FailedLoginAttemptsBeforeBan", ref failedLoginAttemptsBeforeBan);
            GetConfig <TimeSpan>("BanTime", ref banTime);
            GetConfig <bool>("ClearBannedIPAddressesOnRestart", ref clearBannedIPAddressesOnRestart);
            GetConfig <TimeSpan>("ExpireTime", ref expireTime);
            GetConfig <TimeSpan>("CycleTime", ref cycleTime);
            GetConfig <TimeSpan>("MinimumTimeBetweenFailedLoginAttempts", ref minimumTimeBetweenFailedLoginAttempts);
            GetConfig <string>("FirewallRulePrefix", ref firewallRulePrefix);
            GetConfig <bool>("CreateWhitelistFirewallRule", ref createWhitelistFirewallRule);

            string whiteListString      = GetConfig <string>("Whitelist", string.Empty);
            string whiteListRegexString = GetConfig <string>("WhitelistRegex", string.Empty);
            string blacklistString      = GetConfig <string>("Blacklist", string.Empty);
            string blacklistRegexString = GetConfig <string>("BlacklistRegex", string.Empty);

            PopulateList(whiteList, ref whiteListRegex, whiteListString, whiteListRegexString);
            PopulateList(blackList, ref blackListRegex, blacklistString, blacklistRegexString);
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                expressions = new XmlSerializer(typeof(ExpressionsToBlock)).Deserialize(new XmlNodeReader(doc.SelectSingleNode("//ExpressionsToBlock"))) as ExpressionsToBlock;
                if (expressions != null)
                {
                    foreach (ExpressionsToBlockGroup group in expressions.Groups)
                    {
                        foreach (ExpressionToBlock expression in group.Expressions)
                        {
                            expression.Regex = (expression.Regex ?? string.Empty).Trim();
                        }
                    }
                }
            }
            else
            {
                expressions = new ExpressionsToBlock {
                    Groups = new ExpressionsToBlockGroup[0]
                };
            }
            try
            {
                LogFilesToParse logFilesToParse = new XmlSerializer(typeof(LogFilesToParse)).Deserialize(new XmlNodeReader(doc.SelectSingleNode("//LogFilesToParse"))) as LogFilesToParse;
                logFiles = (logFilesToParse == null ? new LogFileToParse[0] : logFilesToParse.LogFiles);
            }
            catch (Exception ex)
            {
                IPBanLog.Error(ex);
                logFiles = new LogFileToParse[0];
            }
            GetConfig <string>("ProcessToRunOnBan", ref processToRunOnBan);

            // retrieve firewall configuration
            string[] firewallTypes = GetConfig <string>("FirewallType", string.Empty).Split(',', StringSplitOptions.RemoveEmptyEntries);
            foreach (string firewallOSAndType in firewallTypes)
            {
                string[] pieces = firewallOSAndType.Split(':');
                if (pieces.Length == 2)
                {
                    osAndFirewallType[pieces[0]] = pieces[1];
                }
            }

            string userNameWhiteListString = GetConfig <string>("UserNameWhiteList", string.Empty);

            foreach (string userName in userNameWhiteListString.Split(','))
            {
                string userNameTrimmed = userName.Normalize().Trim();
                if (userNameTrimmed.Length > 0)
                {
                    userNameWhitelist.Add(userNameTrimmed);
                }
            }
            GetConfig <int>("UserNameWhiteListMinimumEditDistance", ref userNameWhitelistMaximumEditDistance);
            GetConfig <int>("FailedLoginAttemptsBeforeBanUserNameWhitelist", ref failedLoginAttemptsBeforeBanUserNameWhitelist);
            GetConfig <string>("GetUrlUpdate", ref getUrlUpdate);
            GetConfig <string>("GetUrlStart", ref getUrlStart);
            GetConfig <string>("GetUrlStop", ref getUrlStop);
            GetConfig <string>("GetUrlConfig", ref getUrlConfig);
            GetConfig <string>("ExternalIPAddressUrl", ref externalIPAddressUrl);
        }
Пример #21
0
 /// <summary>
 /// Log current log levels
 /// </summary>
 public static void WriteLogLevels(IPBan.LogLevel level = LogLevel.Warn)
 {
     IPBanLog.Write(level, "Log levels: {0},{1},{2},{3},{4},{5}", logger.IsFatalEnabled, logger.IsErrorEnabled, logger.IsWarnEnabled, logger.IsInfoEnabled, logger.IsDebugEnabled, logger.IsTraceEnabled);
 }
Пример #22
0
        private IPAddressLogInfo ExtractEventViewerXml(XmlDocument doc)
        {
            XmlNode keywordsNode = doc.SelectSingleNode("//Keywords");
            string  keywordsText = keywordsNode.InnerText;

            if (keywordsText.StartsWith("0x"))
            {
                keywordsText = keywordsText.Substring(2);
            }
            ulong            keywordsULONG = ulong.Parse(keywordsText, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture);
            IPAddressLogInfo info          = null;

            if (keywordsNode != null)
            {
                // we must match on keywords
                foreach (ExpressionsToBlockGroup group in service.Config.WindowsEventViewerGetGroupsMatchingKeywords(keywordsULONG))
                {
                    foreach (ExpressionToBlock expression in group.Expressions)
                    {
                        // find all the nodes, try and get an ip from any of them, all must match
                        XmlNodeList nodes = doc.SelectNodes(expression.XPath);

                        if (nodes.Count == 0)
                        {
                            IPBanLog.Info("No nodes found for xpath {0}", expression.XPath);
                            info = null;
                            break;
                        }

                        // if there is a regex, it must match
                        if (string.IsNullOrWhiteSpace(expression.Regex))
                        {
                            // count as a match, do not modify the ip address if it was already set
                            IPBanLog.Info("No regex, so counting as a match");
                        }
                        else
                        {
                            info = null;

                            // try and find an ip from any of the nodes
                            foreach (XmlNode node in nodes)
                            {
                                // if we get a match, stop checking nodes
                                info = IPBanService.GetIPAddressInfoFromRegex(service.DnsLookup, expression.RegexObject, node.InnerText);
                                if (info.FoundMatch)
                                {
                                    break;
                                }
                            }

                            if (info != null && !info.FoundMatch)
                            {
                                // match fail, null out ip, we have to match ALL the nodes or we get null ip and do not ban
                                IPBanLog.Info("Regex {0} did not match any nodes with xpath {1}", expression.Regex, expression.XPath);
                                info = null;
                                break;
                            }
                        }
                    }

                    if (info != null && info.FoundMatch && info.IPAddress != null)
                    {
                        info.Source = info.Source ?? group.Source;
                        break;
                    }
                    info = null; // set null for next attempt
                }
            }

            return(info);
        }
Пример #23
0
        static IPBanOS()
        {
            try
            {
                // start off with built in version info, this is not as detailed or nice as we like,
                //  so we try some other ways to get more detailed information
                Version     = Environment.OSVersion.VersionString;
                Description = RuntimeInformation.OSDescription;

                // attempt to get detailed version info
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                {
                    string tempFile = Path.GetTempFileName();
                    Process.Start("/bin/bash", "-c \"cat /etc/*release* > " + tempFile + "\"").WaitForExit();
                    System.Threading.Tasks.Task.Delay(100); // wait a small bit for file to really be closed
                    string versionText = File.ReadAllText(tempFile).Trim();
                    File.Delete(tempFile);
                    if (string.IsNullOrWhiteSpace(versionText))
                    {
                        IPBanLog.Error(new IOException("Unable to load os version from /etc/*release* ..."));
                    }
                    else
                    {
                        Name         = IPBanOS.Linux;
                        FriendlyName = ExtractRegex(versionText, "^(Id|Distrib_Id)=(?<value>.*?)$", string.Empty);
                        if (FriendlyName.Length != 0)
                        {
                            string codeName = ExtractRegex(versionText, "^(Name|Distrib_CodeName)=(?<value>.+)$", string.Empty);
                            if (codeName.Length != 0)
                            {
                                FriendlyName += " - " + codeName;
                            }
                            Version = ExtractRegex(versionText, "^Version_Id=(?<value>.+)$", Version);
                        }
                    }
                }
                else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    Name = IPBanOS.Windows;
                    string tempFile = Path.GetTempFileName();

                    // .net core WMI has a strange bug where WMI will not initialize on some systems
                    // since this is the only place where WMI is used, we can just work-around it
                    // with the wmic executable, which exists (as of 2018) on all supported Windows.
                    StartProcessAndWait("cmd", "/C wmic path Win32_OperatingSystem get Caption,Version /format:table > \"" + tempFile + "\"");
                    if (File.Exists(tempFile))
                    {
                        // try up to 10 times to read the file
                        for (int i = 0; i < 10; i++)
                        {
                            try
                            {
                                string[] lines = File.ReadAllLines(tempFile);
                                File.Delete(tempFile);
                                if (lines.Length > 1)
                                {
                                    int versionIndex = lines[0].IndexOf("Version");
                                    if (versionIndex >= 0)
                                    {
                                        FriendlyName = lines[1].Substring(0, versionIndex - 1).Trim();
                                        Version      = lines[1].Substring(versionIndex).Trim();
                                        break;
                                    }
                                }
                                throw new IOException("Invalid file generated from wmic");
                            }
                            catch (Exception ex)
                            {
                                if (i < 9)
                                {
                                    System.Threading.Tasks.Task.Delay(200).Wait();
                                }
                                else
                                {
                                    IPBanLog.Error(ex, "Unable to load os version using wmic, trying wmi api...");

                                    // last resort, try wmi api
                                    LoadVersionFromWmiApi();
                                }
                            }
                        }
                    }
                    else
                    {
                        // last resort, try wmi api
                        LoadVersionFromWmiApi();
                    }
                }
                else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                {
                    // TODO: Implement better for MAC
                    Name         = IPBanOS.Mac;
                    FriendlyName = "OSX";
                }
                else
                {
                    Name         = IPBanOS.Unknown;
                    FriendlyName = "Unknown";
                }
            }
            catch (Exception ex)
            {
                IPBanLog.Error(ex);
            }
        }
Пример #24
0
        private bool PingFile(WatchedFile file, FileStream fs)
        {
            const int maxCountBeforeNewline = 1024;
            int       b;
            long      lastNewlinePos = -1;

            byte[] bytes;
            long   end = Math.Min(file.LastLength, fs.Length);
            int    countBeforeNewline = 0;

            fs.Position = file.LastPosition;

            while (fs.Position < end && countBeforeNewline++ != maxCountBeforeNewline)
            {
                // read until last \n is found
                b = fs.ReadByte();
                if (b == '\n')
                {
                    lastNewlinePos     = fs.Position - 1;
                    countBeforeNewline = 0;
                }
            }

            if (countBeforeNewline == maxCountBeforeNewline)
            {
                throw new InvalidOperationException("Log file " + this.fileMask + " may not be a plain text new line delimited file");
            }

            if (lastNewlinePos > -1)
            {
                // set file position ready for the next read right after the newline
                fs.Position = file.LastPosition;
                bytes       = new BinaryReader(fs).ReadBytes((int)(lastNewlinePos - fs.Position));

                // set position for next ping
                file.LastPosition = lastNewlinePos + 1;

                // read text and run regex to find ip addresses to ban
                string   subString = Encoding.UTF8.GetString(bytes);
                string[] lines     = subString.Split('\n');
                string   ipAddress = null;
                string   userName  = null;
                bool     foundOne  = false;

                // find ip and user name from all lines
                foreach (string line in lines)
                {
                    IPBanLog.Write(LogLevel.Debug, "Parsing log file line {0}...", line);
                    bool foundMatch = IPBanService.GetIPAddressAndUserNameFromRegex(Regex, line.Trim(), ref ipAddress, ref userName);
                    if (foundMatch)
                    {
                        IPBanLog.Write(LogLevel.Debug, "Found match, ip: {0}, user: {1}", ipAddress, userName);
                        service.AddFailedLogin(ipAddress, Source, userName);
                        foundOne = true;
                    }
                    else
                    {
                        IPBanLog.Write(LogLevel.Debug, "No match!");
                    }
                }

                if (foundOne)
                {
                    // signal that we have found ip addresses
                    ipEvent.Set();
                }
            }

            return(maxFileSize > 0 && fs.Length > maxFileSize);
        }
Пример #25
0
        private void PingFiles()
        {
            try
            {
                pingTimer.Enabled = false;
            }
            catch
            {
            }

            try
            {
                // re-open files and read one byte to flush disk cache
                foreach (WatchedFile file in UpdateWatchedFiles())
                {
                    // if file length has changed, ping the file
                    bool delete = false;

                    // ugly hack to force file to flush
                    using (FileStream fs = new FileStream(file.FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                    {
                        try
                        {
                            fs.Position = fs.Length - 1;
                            fs.ReadByte();
                        }
                        catch
                        {
                        }
                    }

                    long len = new FileInfo(file.FileName).Length;

                    // if file has shrunk (deleted and recreated for example) reset positions to 0
                    if (len < file.LastLength || len < file.LastPosition)
                    {
                        file.LastPosition = 0;
                    }

                    // use file info for length compare to avoid doing a full file open
                    if (len != file.LastLength)
                    {
                        using (FileStream fs = new FileStream(file.FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                        {
                            file.LastLength = len;
                            delete          = PingFile(file, fs);
                        }
                    }
                    else
                    {
                        IPBanLog.Debug("Watched file {0} length has not changed", file.FileName);
                    }
                    if (delete)
                    {
                        try
                        {
                            File.Delete(file.FileName);
                        }
                        catch
                        {
                            // OK someone else might have it open, in which case we have no chance to delete
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                IPBanLog.Error(ex);
            }

            try
            {
                pingTimer.Enabled = true;
            }
            catch
            {
            }
        }
Пример #26
0
        private bool PingFile(WatchedFile file, FileStream fs)
        {
            const int maxCountBeforeNewline = 1024;
            int       b;
            long      lastNewlinePos = -1;

            byte[] bytes;
            long   end = Math.Min(file.LastLength, fs.Length);
            int    countBeforeNewline = 0;

            fs.Position = file.LastPosition;

            IPBanLog.Info("Processing watched file {0}, len = {1}, pos = {2}", file.FileName, file.LastLength, file.LastPosition);

            while (fs.Position < end && countBeforeNewline++ != maxCountBeforeNewline)
            {
                // read until last \n is found
                b = fs.ReadByte();
                if (b == '\n')
                {
                    lastNewlinePos     = fs.Position - 1;
                    countBeforeNewline = 0;
                }
            }

            if (countBeforeNewline == maxCountBeforeNewline)
            {
                throw new InvalidOperationException("Log file " + this.fileMask + " may not be a plain text new line delimited file");
            }

            if (lastNewlinePos > -1)
            {
                // set file position ready for the next read right after the newline
                fs.Position = file.LastPosition;
                bytes       = new BinaryReader(fs).ReadBytes((int)(lastNewlinePos - fs.Position));

                // set position for next ping
                file.LastPosition = lastNewlinePos + 1;

                // read text and run regex to find ip addresses to ban
                string   subString = Encoding.UTF8.GetString(bytes);
                string[] lines     = subString.Split('\n');
                bool     foundOne  = false;

                // find ip and user name from all lines
                foreach (string line in lines)
                {
                    string trimmedLine = line.Trim();
                    IPBanLog.Debug("Parsing log file line {0}...", trimmedLine);
                    IPAddressLogInfo info = IPBanService.GetIPAddressInfoFromRegex(dns, Regex, trimmedLine);
                    if (info.FoundMatch)
                    {
                        info.Source = info.Source ?? Source;
                        IPBanLog.Debug("Log file found match, ip: {0}, user: {1}, source: {2}, count: {3}", info.IPAddress, info.UserName, info.Source, info.Count);
                        failedLogin.AddFailedLogin(info);
                        foundOne = true;
                    }
                    else
                    {
                        IPBanLog.Debug("No match for line {0}", line);
                    }
                }

                if (foundOne)
                {
                    // signal that we have found ip addresses
                    ipEvent.Set();
                }
            }

            return(maxFileSize > 0 && fs.Length > maxFileSize);
        }