예제 #1
0
 private bool DeleteRules(string ruleNamePrefix, int startIndex = 0)
 {
     try
     {
         lock (policy)
         {
             foreach (INetFwRule rule in EnumerateRulesMatchingPrefix(ruleNamePrefix).ToArray())
             {
                 try
                 {
                     Match match = Regex.Match(rule.Name, $"^{ruleNamePrefix}(?<num>[0-9]+)$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
                     if (match.Success && int.TryParse(match.Groups["num"].Value, NumberStyles.None, CultureInfo.InvariantCulture, out int num) && num >= startIndex)
                     {
                         policy.Rules.Remove(rule.Name);
                     }
                 }
                 catch
                 {
                 }
             }
         }
         return(true);
     }
     catch (Exception ex)
     {
         IPBanLog.Error("Error deleting rules", ex);
         return(false);
     }
 }
 /// <summary>
 /// Update - if the text file path exists, all ip addresses from each line will be banned
 /// </summary>
 public async Task Update()
 {
     try
     {
         if (File.Exists(textFilePath))
         {
             string[] lines = (await File.ReadAllLinesAsync(textFilePath)).Where(l => IPAddress.TryParse(l, out _)).ToArray();
             IPBanLog.Warn("Queueing {0} ip addresses to ban from {1} file", lines.Length, textFilePath);
             List <IPAddressLogEvent> bans = new List <IPAddressLogEvent>();
             foreach (string[] pieces in lines.Select(l => l.Split(',')))
             {
                 if (pieces.Length < 1)
                 {
                     continue;
                 }
                 string ipAddress = pieces[0];
                 string source    = (pieces.Length < 2 ? "Block" : pieces[1]);
                 bans.Add(new IPAddressLogEvent(ipAddress, string.Empty, source, 1, IPAddressEventType.Blocked));
             }
             service.AddIPAddressLogEvents(bans);
             IPBanExtensionMethods.FileDeleteWithRetry(textFilePath);
         }
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex);
     }
 }
예제 #3
0
        private void SetupEventLogWatcher()
        {
            try
            {
                List <string> ignored     = new List <string>();
                string        queryString = GetEventLogQueryString(ignored);
                if (queryString != null && queryString != previousQueryString)
                {
                    IPBanLog.Warn("Event viewer query string: {0}", queryString);
                    foreach (string path in ignored)
                    {
                        IPBanLog.Warn("Ignoring event viewer path {0}", path);
                    }

                    watcher?.Dispose();
                    query   = new EventLogQuery(null, PathType.LogName, queryString);
                    watcher = new EventLogWatcher(query);
                    watcher.EventRecordWritten += EventRecordWritten;
                    watcher.Enabled             = true;
                    previousQueryString         = queryString;
                }
            }
            catch (Exception ex)
            {
                IPBanLog.Error("Failed to create event viewer watcher", ex);
            }
        }
예제 #4
0
 public bool IsIPAddressAllowed(string ipAddress, int port = -1)
 {
     try
     {
         lock (policy)
         {
             for (int i = 0; ; i += MaxIpAddressesPerRule)
             {
                 string ruleName = AllowRulePrefix + i.ToString(CultureInfo.InvariantCulture);
                 try
                 {
                     INetFwRule rule = policy.Rules.Item(ruleName);
                     if (rule is null)
                     {
                         break;
                     }
                     else if (rule.RemoteAddresses.Contains(ipAddress))
                     {
                         return(true);
                     }
                 }
                 catch
                 {
                     // OK, rule does not exist
                 }
             }
         }
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex);
     }
     return(false);
 }
예제 #5
0
 /// <summary>
 /// Set a field / variable from configuration manager app settings. If null or not found, nothing is changed.
 /// </summary>
 /// <typeparam name="T">Type of value to set</typeparam>
 /// <param name="key">Key</param>
 /// <param name="value">Value</param>
 /// <param name="defaultValue">Default value if array was empty</param>
 public void GetConfigArray <T>(string key, ref T[] value, T[] defaultValue)
 {
     try
     {
         var      converter = TypeDescriptor.GetConverter(typeof(T));
         string[] items     = (appSettings[key] ?? string.Empty).Split('|', ';', ',');
         List <T> list      = new List <T>();
         foreach (string item in items)
         {
             string normalizedItem = item.Trim();
             if (normalizedItem.Length != 0)
             {
                 list.Add((T)converter.ConvertFromInvariantString(normalizedItem));
             }
         }
         if (list.Count == 0)
         {
             value = (defaultValue ?? list.ToArray());
         }
         else
         {
             value = list.ToArray();
         }
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex, "Error deserializing appSettings key {0}", key);
     }
 }
예제 #6
0
 private void EventRecordWritten(object sender, EventRecordWrittenEventArgs e)
 {
     try
     {
         if (e != null && e.EventRecord != null)
         {
             EventRecord rec = e.EventRecord;
             string      xml = null;
             try
             {
                 xml = rec.ToXml();
             }
             catch
             {
             }
             if (xml != null)
             {
                 ProcessEventViewerXml(xml);
             }
         }
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex);
     }
 }
예제 #7
0
 private async Task RunConsoleService(string[] args)
 {
     try
     {
         await start.Invoke(args);
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex);
     }
 }
예제 #8
0
 public virtual Task <bool> AllowIPAddresses(IEnumerable <string> ipAddresses, CancellationToken cancelToken = default)
 {
     try
     {
         return(Task.FromResult(UpdateRule(AllowRuleName, "ACCEPT", ipAddresses, hashTypeSingleIP, allowRuleMaxCount, null, cancelToken)));
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex);
         return(Task.FromResult(false));
     }
 }
예제 #9
0
 private Task <bool> BlockOrAllowIPAddresses(string ruleNamePrefix, bool block, IEnumerable <string> ipAddresses, IEnumerable <PortRange> allowedPorts = null, CancellationToken cancelToken = default)
 {
     try
     {
         string        prefix          = ruleNamePrefix.TrimEnd('_') + "_";
         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)
             {
                 if (block)
                 {
                     CreateBlockRule(ipAddressesList, 0, MaxIpAddressesPerRule, prefix + i.ToStringInvariant(), allowedPorts);
                 }
                 else
                 {
                     CreateAllowRule(ipAddressesList, 0, MaxIpAddressesPerRule, prefix + i.ToStringInvariant(), allowedPorts);
                 }
                 i += MaxIpAddressesPerRule;
                 ipAddressesList.Clear();
             }
         }
         if (cancelToken.IsCancellationRequested)
         {
             throw new OperationCanceledException(cancelToken);
         }
         if (ipAddressesList.Count != 0)
         {
             if (block)
             {
                 CreateBlockRule(ipAddressesList, 0, MaxIpAddressesPerRule, prefix + i.ToStringInvariant(), allowedPorts);
             }
             else
             {
                 CreateAllowRule(ipAddressesList, 0, MaxIpAddressesPerRule, prefix + i.ToStringInvariant(), allowedPorts);
             }
             i += MaxIpAddressesPerRule;
         }
         DeleteRules(prefix, i);
         return(Task.FromResult(true));
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex);
         return(Task.FromResult(false));
     }
 }
예제 #10
0
 public virtual Task <bool> AllowIPAddresses(string ruleNamePrefix, IEnumerable <IPAddressRange> ipAddresses, IEnumerable <PortRange> allowedPorts = null, CancellationToken cancelToken = default)
 {
     try
     {
         ruleNamePrefix.ThrowIfNullOrEmpty();
         return(Task.FromResult(UpdateRule(RulePrefix + ruleNamePrefix, "ACCEPT", ipAddresses.Select(r => r.ToCidrString()), hashTypeCidrMask, blockRuleMaxCount, allowedPorts, cancelToken)));
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex);
         return(Task.FromResult(false));
     }
 }
예제 #11
0
 public virtual Task <bool> BlockIPAddressesDelta(string ruleNamePrefix, IEnumerable <IPBanFirewallIPAddressDelta> deltas, IEnumerable <PortRange> allowedPorts = null, CancellationToken cancelToken = default)
 {
     try
     {
         string ruleName = (string.IsNullOrWhiteSpace(ruleNamePrefix) ? BlockRuleName : RulePrefix + ruleNamePrefix);
         return(Task.FromResult(UpdateRuleDelta(ruleName, "DROP", deltas, hashTypeSingleIP, blockRuleMaxCount, false, allowedPorts, cancelToken)));
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex);
         return(Task.FromResult(false));
     }
 }
예제 #12
0
 /// <summary>
 /// Get a value from configuration manager app settings
 /// </summary>
 /// <typeparam name="T">Type of value to get</typeparam>
 /// <param name="key">Key</param>
 /// <param name="defaultValue">Default value if null or not found</param>
 /// <returns>Value</returns>
 public T GetConfig <T>(string key, T defaultValue = default)
 {
     try
     {
         var converter = TypeDescriptor.GetConverter(typeof(T));
         return((T)converter.ConvertFromInvariantString(appSettings[key]));
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex, "Error deserializing appSettings key {0}", key);
         return(defaultValue);
     }
 }
예제 #13
0
 protected override void OnStart(string[] args)
 {
     base.OnStart(args);
     Task.Run(async() =>
     {
         try
         {
             await runner.start.Invoke(args);
         }
         catch (Exception ex)
         {
             IPBanLog.Error(ex);
         }
     });
 }
예제 #14
0
 /// <summary>
 /// Set a field / variable from configuration manager app settings. If null or not found, nothing is changed.
 /// </summary>
 /// <typeparam name="T">Type of value to set</typeparam>
 /// <param name="key">Key</param>
 /// <param name="value">Value</param>
 public void GetConfig <T>(string key, ref T value)
 {
     try
     {
         var converter = TypeDescriptor.GetConverter(typeof(T));
         if (appSettings.ContainsKey(key))
         {
             value = (T)converter.ConvertFromInvariantString(appSettings[key]);
         }
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex, "Error deserializing appSettings key {0}", key);
     }
 }
 /// <summary>
 /// Update - if the text file path exists, all ip addresses from each line will be unbanned
 /// </summary>
 public async Task Update()
 {
     try
     {
         if (File.Exists(textFilePath))
         {
             string[] lines = (await File.ReadAllLinesAsync(textFilePath)).Where(l => IPAddress.TryParse(l, out _)).ToArray();
             IPBanLog.Warn("Queueing {0} ip addresses to unban from {1} file", lines.Length, textFilePath);
             UnblockIPAddresses(lines);
             IPBanExtensionMethods.FileDeleteWithRetry(textFilePath);
         }
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex);
     }
 }
예제 #16
0
        /// <summary>
        /// Get a value from configuration manager app settings
        /// </summary>
        /// <typeparam name="T">Type of value to get</typeparam>
        /// <param name="key">Key</param>
        /// <param name="value">Value to set</param>
        /// <param name="minValue">Min value</param>
        /// <param name="maxValue">Max value</param>
        /// <param name="clampSmallTimeSpan">Whether to clamp small timespan to max value</param>
        /// <returns>Value</returns>
        public void GetConfig <T>(string key, ref T value, T?minValue = null, T?maxValue = null, bool clampSmallTimeSpan = true) where T : struct, IComparable <T>
        {
            try
            {
                var converter = TypeDescriptor.GetConverter(typeof(T));
                value = (T)converter.ConvertFromInvariantString(appSettings[key]);
            }
            catch (Exception ex)
            {
                IPBanLog.Error(ex, "Error deserializing appSettings key {0}", key);
            }

            if (minValue != null && maxValue != null)
            {
                value = value.Clamp(minValue.Value, maxValue.Value, clampSmallTimeSpan);
            }
        }
예제 #17
0
        public bool IsIPAddressBlocked(string ipAddress, out string ruleName, int port = -1)
        {
            ruleName = null;

            try
            {
                lock (policy)
                {
                    for (int i = 0; ; i += MaxIpAddressesPerRule)
                    {
                        string firewallRuleName = BlockRulePrefix + i.ToString(CultureInfo.InvariantCulture);
                        try
                        {
                            INetFwRule rule = policy.Rules.Item(firewallRuleName);
                            if (rule is null)
                            {
                                // no more rules to check
                                break;
                            }
                            else
                            {
                                HashSet <string> set = new HashSet <string>(rule.RemoteAddresses.Split(',').Select(i2 => IPAddressRange.Parse(i2).Begin.ToString()));
                                if (set.Contains(ipAddress))
                                {
                                    ruleName = firewallRuleName;
                                    return(true);
                                }
                            }
                        }
                        catch
                        {
                            // no more rules to check
                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                IPBanLog.Error(ex);
            }
            return(false);
        }
예제 #18
0
        private async Task FirewallTask(AsyncQueue <Func <CancellationToken, Task> > queue)
        {
            while (!firewallQueueCancel.IsCancellationRequested)
            {
                KeyValuePair <bool, Func <CancellationToken, Task> > nextAction = await queue.TryDequeueAsync(firewallQueueCancel.Token);

                if (nextAction.Key && nextAction.Value != null)
                {
                    try
                    {
                        await nextAction.Value.Invoke(firewallQueueCancel.Token);
                    }
                    catch (Exception ex)
                    {
                        IPBanLog.Error(ex);
                    }
                }
            }
        }
예제 #19
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");
     }
 }
예제 #20
0
        protected int RunProcess(string program, bool requireExitCode, out IReadOnlyList <string> lines, string commandLine, params object[] args)
        {
            commandLine = string.Format(commandLine, args);
            string bash = "-c \"" + program + " " + commandLine.Replace("\"", "\\\"") + "\"";

            IPBanLog.Debug("Running firewall process: {0} {1}", program, commandLine);
            using (Process p = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName = "/bin/bash",
                    Arguments = bash,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    RedirectStandardOutput = true
                }
            })
            {
                p.Start();
                List <string> lineList = new List <string>();
                string        line;
                while ((line = p.StandardOutput.ReadLine()) != null)
                {
                    lineList.Add(line);
                }
                lines = lineList;
                if (!p.WaitForExit(60000))
                {
                    IPBanLog.Error("Process {0} {1} timed out", program, commandLine);
                    p.Kill();
                }
                if (requireExitCode && p.ExitCode != 0)
                {
                    IPBanLog.Error("Process {0} {1} had exit code {2}", program, commandLine, p.ExitCode);
                }
                return(p.ExitCode);
            }
        }
예제 #21
0
        /// <summary>
        /// Initialize and start the service
        /// </summary>
        public async Task StartAsync()
        {
            if (IsRunning)
            {
                return;
            }

            try
            {
                IsRunning = true;
                ipDB      = new IPBanDB(DatabasePath ?? "ipban.sqlite");
                AddWindowsEventViewer();
                AddUpdater(new IPBanUnblockIPAddressesUpdater(this, Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "unban.txt")));
                AddUpdater(new IPBanBlockIPAddressesUpdater(this, Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ban.txt")));
                AssemblyVersion = IPBanService.IPBanAssembly.GetName().Version.ToString();
                await ReadAppSettings();

                UpdateBannedIPAddressesOnStart();
                IPBanDelegate?.Start(this);
                if (!ManualCycle)
                {
                    if (RunFirstCycleRightAway)
                    {
                        await RunCycle(); // run one cycle right away
                    }
                    cycleTimer          = new System.Timers.Timer(Config.CycleTime.TotalMilliseconds);
                    cycleTimer.Elapsed += async(sender, e) => await CycleTimerElapsed(sender, e);

                    cycleTimer.Start();
                }
                IPBanLog.Warn("IPBan {0} service started and initialized. Operating System: {1}", IPBanOS.Name, IPBanOS.OSString());
                IPBanLog.WriteLogLevels();
            }
            catch (Exception ex)
            {
                IPBanLog.Error("Critical error in IPBanService.Start", ex);
            }
        }
예제 #22
0
 public IPBanWindowsServiceRunner(IPBanServiceRunner runner, string[] args)
 {
     runner.ThrowIfNull();
     try
     {
         IPBanLog.Warn("Running as a Windows service");
         this.runner = runner;
         CanShutdown = false;
         CanStop     = CanHandleSessionChangeEvent = CanHandlePowerEvent = true;
         var acceptedCommandsField = typeof(ServiceBase).GetField("acceptedCommands", BindingFlags.Instance | BindingFlags.NonPublic);
         if (acceptedCommandsField != null)
         {
             int acceptedCommands = (int)acceptedCommandsField.GetValue(this);
             acceptedCommands |= 0x00000100; // SERVICE_ACCEPT_PRESHUTDOWN;
             acceptedCommandsField.SetValue(this, acceptedCommands);
         }
         Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
     }
     catch (Exception ex)
     {
         IPBanLog.Error(ex);
     }
 }
예제 #23
0
        /// <summary>
        /// Ping the files, this is normally done on a timer, but if you have passed a 0 second
        /// ping interval to the constructor, you must call this manually
        /// </summary>
        public void PingFiles()
        {
            try
            {
                if (pingTimer != null)
                {
                    pingTimer.Enabled = false;
                }
            }
            catch
            {
            }


            foreach (WatchedFile file in GetCurrentWatchedFiles())
            {
                try
                {
                    // 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, 16))
                    {
                        try
                        {
                            if (fs.Length != 0)
                            {
                                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, 256))
                        {
                            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
            {
                if (pingTimer != null)
                {
                    pingTimer.Enabled = true;
                }
            }
            catch
            {
            }
        }
예제 #24
0
        /// <summary>
        /// Check if a user name is active on the local machine
        /// </summary>
        /// <param name="userName">User name to check</param>
        /// <returns>True if user name is active, false otherwise</returns>
        public static bool UserIsActive(string userName)
        {
            if (string.IsNullOrWhiteSpace(userName))
            {
                return(false);
            }
            userName = userName.Trim();

            try
            {
                if (isWindows)
                {
                    // Windows: WMI
                    SelectQuery query = new SelectQuery("Win32_UserAccount");
                    ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
                    foreach (ManagementObject user in searcher.Get())
                    {
                        if (user["Disabled"] is null || user["Disabled"].Equals(false))
                        {
                            string possibleMatch = user["Name"]?.ToString();
                            if (possibleMatch != null && possibleMatch.Equals(userName, StringComparison.OrdinalIgnoreCase))
                            {
                                return(true);
                            }
                        }
                    }
                }
                else if (isLinux)
                {
                    // Linux: /etc/passwd
                    if (File.Exists("/etc/passwd"))
                    {
                        bool     enabled = false;
                        string[] lines;
                        if (File.Exists("/etc/shadow"))
                        {
                            lines = File.ReadAllLines("/etc/shadow");
                            // example line:
                            // root:!$1$Fp$SSSuo3L.xA5s/kMEEIloU1:18049:0:99999:7:::
                            foreach (string[] pieces in lines.Select(l => l.Split(':')).Where(p => p.Length == 9))
                            {
                                string checkUserName = pieces[0].Trim();
                                if (checkUserName.Equals(userName))
                                {
                                    string pwdHash = pieces[1].Trim();
                                    if (pwdHash.Length != 0 && pwdHash[0] != '*' && pwdHash[0] != '!')
                                    {
                                        enabled = true;
                                        break;
                                    }
                                    else
                                    {
                                        return(false);
                                    }
                                }
                            }
                        }

                        if (enabled)
                        {
                            // user is OK in shadow file, check passwd file
                            lines = File.ReadAllLines("/etc/passwd");
                            // example line:
                            // root:x:0:0:root:/root:/bin/bash
                            foreach (string[] pieces in lines.Select(l => l.Split(':')).Where(p => p.Length == 7))
                            {
                                // x means shadow file is where the password is at
                                string checkUserName = pieces[0].Trim();
                                string nologin       = pieces[6];
                                if (checkUserName.Equals(userName) && nologin.IndexOf("nologin", StringComparison.OrdinalIgnoreCase) < 0 &&
                                    !nologin.Contains("/bin/false"))
                                {
                                    return(true);
                                }
                            }
                        }
                    }
                }
                // TODO: MAC
            }
            catch (Exception ex)
            {
                IPBanLog.Error("Error determining if user is active", ex);
            }

            return(false);
        }
예제 #25
0
        static IPBanOS()
        {
            try
            {
                tempFolder = Path.GetTempPath();
                if (string.IsNullOrWhiteSpace(tempFolder))
                {
                    if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                    {
                        tempFolder = "c:\\temp";
                    }
                    else
                    {
                        tempFolder = "/tmp";
                    }
                }
                Directory.CreateDirectory(tempFolder);

                // 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))
                {
                    isLinux = true;
                    string tempFile = IPBanOS.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();
                    IPBanExtensionMethods.FileDeleteWithRetry(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))
                {
                    isWindows   = true;
                    processVerb = "runas";
                    Name        = IPBanOS.Windows;
                    string tempFile = IPBanOS.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);
                                IPBanExtensionMethods.FileDeleteWithRetry(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("Error determining platform info", ex);
            }
        }
예제 #26
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, 1, 50);
            GetConfig <bool>("ResetFailedLoginCountForUnbannedIPAddresses", ref resetFailedLoginCountForUnbannedIPAddresses);
            GetConfigArray <TimeSpan>("BanTime", ref banTimes, emptyTimeSpanArray);
            for (int i = 0; i < banTimes.Length; i++)
            {
                banTimes[i] = banTimes[i].Clamp(TimeSpan.FromMinutes(1.0), maxBanTimeSpan);
            }
            GetConfig <bool>("ClearBannedIPAddressesOnRestart", ref clearBannedIPAddressesOnRestart);
            GetConfig <TimeSpan>("ExpireTime", ref expireTime, TimeSpan.FromMinutes(1.0), maxBanTimeSpan);
            GetConfig <TimeSpan>("CycleTime", ref cycleTime, TimeSpan.FromSeconds(5.0), TimeSpan.FromMinutes(1.0), false);
            GetConfig <TimeSpan>("MinimumTimeBetweenFailedLoginAttempts", ref minimumTimeBetweenFailedLoginAttempts, TimeSpan.Zero, TimeSpan.FromSeconds(15.0), false);
            GetConfig <string>("FirewallRulePrefix", ref firewallRulePrefix);

            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, whiteListRanges, ref whiteListRegex, whiteListString, whiteListRegexString);
            PopulateList(blackList, blackListRanges, ref blackListRegex, blacklistString, blacklistRegexString);
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                expressionsFailure = new XmlSerializer(typeof(EventViewerExpressionsToBlock)).Deserialize(new XmlNodeReader(doc.SelectSingleNode("//ExpressionsToBlock"))) as EventViewerExpressionsToBlock;
                if (expressionsFailure != null)
                {
                    foreach (EventViewerExpressionGroup group in expressionsFailure.Groups)
                    {
                        foreach (EventViewerExpression expression in group.Expressions)
                        {
                            expression.Regex = (expression.Regex?.ToString() ?? string.Empty).Trim();
                        }
                    }
                }
                expressionsSuccess = new XmlSerializer(typeof(EventViewerExpressionsToNotify)).Deserialize(new XmlNodeReader(doc.SelectSingleNode("//ExpressionsToNotify"))) as EventViewerExpressionsToNotify;
                if (expressionsSuccess != null)
                {
                    foreach (EventViewerExpressionGroup group in expressionsSuccess.Groups)
                    {
                        group.NotifyOnly = true;
                        foreach (EventViewerExpression expression in group.Expressions)
                        {
                            expression.Regex = (expression.Regex?.ToString() ?? string.Empty).Trim();
                        }
                    }
                }
            }
            else
            {
                expressionsFailure = new EventViewerExpressionsToBlock();
                expressionsSuccess = new EventViewerExpressionsToNotify();
            }
            try
            {
                if (new XmlSerializer(typeof(IPBanLogFilesToParse)).Deserialize(new XmlNodeReader(doc.SelectSingleNode("//LogFilesToParse"))) is IPBanLogFilesToParse logFilesToParse)
                {
                    logFiles = logFilesToParse.LogFiles;
                }
                else
                {
                    logFiles = emptyLogFilesToParseArray;
                }
            }
            catch (Exception ex)
            {
                IPBanLog.Error(ex);
                logFiles = new IPBanLogFileToParse[0];
            }
            GetConfig <string>("ProcessToRunOnBan", ref processToRunOnBan);
            GetConfig <bool>("UseDefaultBannedIPAddressHandler", ref useDefaultBannedIPAddressHandler);

            // 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().ToUpperInvariant().Trim();
                if (userNameTrimmed.Length > 0)
                {
                    userNameWhitelist.Add(userNameTrimmed);
                }
            }
            string userNameWhiteListRegexString = GetConfig <string>("UserNameWhiteListRegex", string.Empty);

            if (!string.IsNullOrWhiteSpace(userNameWhiteListRegexString))
            {
                userNameWhitelistRegex = new Regex(userNameWhiteListRegexString, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Singleline);
            }
            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);

            // parse firewall block rules, one per line
            ParseFirewallBlockRules();
        }
예제 #27
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 is 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 == "0.0.0.0/0,::/0" ? "*" : 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 == "*" && remoteIPAddresses != "0.0.0.0/0,::/0"))
                {
                    // 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);
            }
        }