Exemple #1
0
        public IEnumerable <IPAddressRange> EnumerateIPAddresses(string ruleNamePrefix = null)
        {
            string tempFile = OSUtility.Instance.GetTempFileName();

            try
            {
                string prefix = RulePrefix + (ruleNamePrefix ?? string.Empty);
                RunProcess("ipset", true, $"save > \"{tempFile}\"");
                bool inSet = false;
                foreach (string line in File.ReadLines(tempFile))
                {
                    string[] pieces = line.Split(' ');
                    if (pieces.Length > 1 && pieces[0].Equals("create", StringComparison.OrdinalIgnoreCase))
                    {
                        inSet = (pieces[1].StartsWith(prefix, StringComparison.OrdinalIgnoreCase));
                    }
                    else if (inSet && pieces.Length > 2 && pieces[0] == "add")
                    {
                        yield return(IPAddressRange.Parse(pieces[2]));
                    }
                }
            }
            finally
            {
                ExtensionMethods.FileDeleteWithRetry(tempFile);
            }
        }
Exemple #2
0
        private void LoadVersionFromWmic()
        {
            string tempFile = 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.
            // this process can hang and fail to run after windows update or other cases on system restart,
            // so put a short timeout in and fallback to WMI api if needed
            Exception lastError = null;

            Logger.Info("Attempting to load os info from wmic");

            // attempt to run wmic to generate the info we want
            StartProcessAndWait(5000, "cmd", "/C wmic path Win32_OperatingSystem get Caption,Version /format:table > \"" + tempFile + "\"");

            // try up to 10 times to read the file in case file is still in use
            try
            {
                for (int i = 0; i < 10; i++)
                {
                    try
                    {
                        // if this throws, we will try again
                        string[] lines = File.ReadAllLines(tempFile);

                        // if we have enough lines, try to parse them out
                        if (lines.Length > 1)
                        {
                            int versionIndex = lines[0].IndexOf("Version");
                            if (versionIndex >= 0)
                            {
                                FriendlyName = lines[1].Substring(0, versionIndex).Trim();
                                if (string.IsNullOrWhiteSpace(Version))
                                {
                                    Version = lines[1].Substring(versionIndex).Trim();
                                }
                                return;
                            }
                        }

                        throw new InvalidDataException("Invalid file generated by wmic");
                    }
                    catch (Exception ex)
                    {
                        lastError = ex;
                        if (ex is InvalidDataException)
                        {
                            break;
                        }
                    }
                    Thread.Sleep(200);
                }
            }
            finally
            {
                ExtensionMethods.FileDeleteWithRetry(tempFile);
            }
            throw new ApplicationException("Unable to load os version using wmic", lastError);
        }
Exemple #3
0
        public IEnumerable <string> EnumerateAllowedIPAddresses()
        {
            string tempFile = OSUtility.Instance.GetTempFileName();

            try
            {
                RunProcess("ipset", true, $"save > \"{tempFile}\"");
                bool inAllow = true;
                foreach (string line in File.ReadLines(tempFile))
                {
                    string[] pieces = line.Split(' ');
                    if (pieces.Length > 1 && pieces[0].Equals("create", StringComparison.OrdinalIgnoreCase))
                    {
                        inAllow = (pieces[1].Equals(AllowRuleName));
                    }
                    else if (inAllow && pieces.Length > 2 && pieces[0] == "add")
                    {
                        yield return(pieces[2]);
                    }
                }
            }
            finally
            {
                ExtensionMethods.FileDeleteWithRetry(tempFile);
            }
        }
Exemple #4
0
        private static void LoadVersionFromLinux()
        {
            Name    = FriendlyName = OSUtility.Linux;
            isLinux = true;
            string tempFile = GetTempFileName();

            using Process p = Process.Start("/bin/bash", "-c \"cat /etc/*release* > " + tempFile + "\"");
            p.WaitForExit();
            System.Threading.Tasks.Task.Delay(100); // wait a small bit for file to really be closed
            string versionText = File.ReadAllText(tempFile).Trim();

            ExtensionMethods.FileDeleteWithRetry(tempFile);
            if (string.IsNullOrWhiteSpace(versionText))
            {
                Logger.Error(new IOException("Unable to load os version from /etc/*release* ..."));
            }
            else
            {
                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);
                }
            }

            UsesYumPackageManager = FriendlyName.Contains("centos", StringComparison.OrdinalIgnoreCase) ||
                                    OSUtility.FriendlyName.Contains("fedora", StringComparison.OrdinalIgnoreCase) ||
                                    OSUtility.FriendlyName.Contains("red hat", StringComparison.OrdinalIgnoreCase) ||
                                    OSUtility.FriendlyName.Contains("redhat", StringComparison.OrdinalIgnoreCase);
        }
 /// <summary>
 /// Update - if the text file path exists, all ip addresses from each line will be banned
 /// </summary>
 /// <param name="cancelToken">Cancel token</param>
 public async Task Update(CancellationToken cancelToken)
 {
     try
     {
         foreach (string file in Directory.GetFiles(textFilePathDir, textFilePathMask, SearchOption.TopDirectoryOnly))
         {
             string[] lines = (await File.ReadAllLinesAsync(file, cancelToken)).Where(l => IPAddress.TryParse(l, out _)).ToArray();
             Logger.Warn("Queueing {0} ip addresses to ban from {1} file", lines.Length, file);
             List <IPAddressLogEvent> bans = new();
             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);
             ExtensionMethods.FileDeleteWithRetry(file);
         }
     }
     catch (Exception ex)
     {
         Logger.Error(ex);
     }
 }
Exemple #6
0
        public override IEnumerable <string> EnumerateBannedIPAddresses()
        {
            string tempFile = OSUtility.GetTempFileName();

            try
            {
                RunProcess("ipset", true, $"save > \"{tempFile}\"");
                bool inBlockRule = true;
                foreach (string line in File.ReadLines(tempFile))
                {
                    string[] pieces = line.Split(' ');
                    if (pieces.Length > 1 && pieces[0].Equals("create", StringComparison.OrdinalIgnoreCase))
                    {
                        inBlockRule = (!pieces[1].Equals(AllowRuleName) &&
                                       (pieces[1].StartsWith(BlockRulePrefix) || pieces[1].StartsWith(RulePrefix + "6_Block_")));
                    }
                    else if (inBlockRule && pieces.Length > 2 && pieces[0] == "add")
                    {
                        yield return(pieces[2]);
                    }
                }
            }
            finally
            {
                ExtensionMethods.FileDeleteWithRetry(tempFile);
            }
        }
Exemple #7
0
        private void RemoveAllTablesAndSets()
        {
            if (!IsIPV4)
            {
                return;
            }

            try
            {
                string dir = AppDomain.CurrentDomain.BaseDirectory;
                foreach (string setFile in Directory.GetFiles(dir, "*.set")
                         .Union(Directory.GetFiles(dir, "*.tbl")
                                .Union(Directory.GetFiles(dir, "*.set6"))
                                .Union(Directory.GetFiles(dir, "*.tbl6"))))
                {
                    ExtensionMethods.FileDeleteWithRetry(setFile);
                }
                RunProcess(IpTablesProcess, true, "-F");
                RunProcess(ip6TablesProcess, true, "-F");
                RunProcess("ipset", true, "destroy");
            }
            catch
            {
            }
        }
Exemple #8
0
 /// <summary>
 /// Move a file with retry
 /// </summary>
 /// <param name="sourceFile">Source file to move</param>
 /// <param name="destFile">Destination file to move to</param>
 /// <param name="millisecondsBetweenRetry">Milliseconds between each retry</param>
 /// <param name="retryCount">Retry count</param>
 public static void FileMoveWithRetry(string sourceFile, string destFile, int millisecondsBetweenRetry = 200, int retryCount = 10)
 {
     if (File.Exists(sourceFile))
     {
         ExtensionMethods.FileDeleteWithRetry(destFile);
         Retry(() => Directory.CreateDirectory(Path.GetDirectoryName(destFile)), millisecondsBetweenRetry, retryCount);
         Retry(() => File.Move(sourceFile, destFile), millisecondsBetweenRetry, retryCount);
     }
 }
Exemple #9
0
        /// <summary>
        /// Create a test IPBanService
        /// </summary>
        /// <param name="directory">Root directory</param>
        /// <param name="configFileName">Config file name</param>
        /// <param name="defaultBannedIPAddressHandlerUrl">Url for banned ip handling or null to not handle banned ip</param>
        /// <param name="configFileModifier">Change config file (param are file text, returns new file text)</param>
        /// <returns>Service</returns>
        public static T CreateAndStartIPBanTestService <T>(string directory = null, string configFileName = null, string defaultBannedIPAddressHandlerUrl = null,
                                                           Func <string, string> configFileModifier = null) where T : IPBanService
        {
            DefaultHttpRequestMaker.DisableLiveRequests = true;

            // cleanup any db, set or tbl files
            foreach (string file in Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.set")
                     .Union(Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.tbl"))
                     .Union(Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.set6"))
                     .Union(Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.tbl6"))
                     .Union(Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.sqlite"))
                     .Union(Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.sqlite-wal"))
                     .Union(Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.sqlite-shm"))
                     .Union(Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*-journal")))
            {
                ExtensionMethods.FileDeleteWithRetry(file, 1000);
            }

            if (string.IsNullOrWhiteSpace(directory))
            {
                directory = Path.GetDirectoryName(IPBanAssembly.Location);
            }
            if (string.IsNullOrWhiteSpace(configFileName))
            {
                configFileName = IPBanService.ConfigFileName;
            }
            string configFilePath = Path.Combine(directory, configFileName);
            string configFileText = File.ReadAllText(configFilePath);

            configFilePath += ".tmp";
            if (configFileModifier != null)
            {
                configFileText = configFileModifier(configFileText);
            }
            ExtensionMethods.FileWriteAllTextWithRetry(configFilePath, configFileText);
            T service = IPBanService.CreateService <T>() as T;

            service.ExternalIPAddressLookup = LocalMachineExternalIPAddressLookupTest.Instance;
            service.ConfigFilePath          = configFilePath;
            service.MultiThreaded           = false;
            service.ManualCycle             = true;
            if (defaultBannedIPAddressHandlerUrl is null)
            {
                service.BannedIPAddressHandler = NullBannedIPAddressHandler.Instance;
            }
            else
            {
                service.BannedIPAddressHandler = new DefaultBannedIPAddressHandler {
                    BaseUrl = defaultBannedIPAddressHandlerUrl
                };
            }
            service.Version = "1.1.1.1";
            service.StartAsync().Sync();
            service.DB.Truncate(true);
            service.Firewall.Truncate();
            return(service);
        }
Exemple #10
0
 /// <summary>
 /// Dispose of all resources, does not delete the database file
 /// </summary>
 public void Dispose()
 {
     GC.Collect();
     GC.WaitForPendingFinalizers();
     if (autoDelete)
     {
         ExtensionMethods.FileDeleteWithRetry(dbPath);
     }
 }
Exemple #11
0
 /// <summary>
 /// Dispose of all resources, does not delete the database file
 /// </summary>
 public void Dispose()
 {
     GC.SuppressFinalize(this);
     GC.Collect();
     GC.WaitForPendingFinalizers();
     SqliteConnection.ClearAllPools();
     if (autoDelete)
     {
         ExtensionMethods.FileDeleteWithRetry(dbPath);
     }
 }
Exemple #12
0
 public static void RemoveDatabaseFiles(string folder)
 {
     // cleanup any db, set or tbl files
     foreach (string file in Directory.GetFiles(folder, "*.set")
              .Union(Directory.GetFiles(folder, "*.tbl"))
              .Union(Directory.GetFiles(folder, "*.set6"))
              .Union(Directory.GetFiles(folder, "*.tbl6"))
              .Union(Directory.GetFiles(folder, "*.sqlite"))
              .Union(Directory.GetFiles(folder, "*.sqlite-wal"))
              .Union(Directory.GetFiles(folder, "*.sqlite-shm"))
              .Union(Directory.GetFiles(folder, "*-journal")))
     {
         ExtensionMethods.FileDeleteWithRetry(file, 1000);
     }
 }
 /// <summary>
 /// Update - if the text file path exists, all ip addresses from each line will be unbanned
 /// </summary>
 /// <param name="cancelToken">Cancel token</param>
 public async Task Update(CancellationToken cancelToken)
 {
     try
     {
         foreach (string file in Directory.GetFiles(textFilePathDir, textFilePathMask, SearchOption.TopDirectoryOnly))
         {
             string[] lines = (await File.ReadAllLinesAsync(file, cancelToken)).Where(l => IPAddress.TryParse(l, out _)).ToArray();
             Logger.Warn("Queueing {0} ip addresses to unban from {1} file", lines.Length, file);
             UnblockIPAddresses(lines);
             ExtensionMethods.FileDeleteWithRetry(file);
         }
     }
     catch (Exception ex)
     {
         Logger.Error(ex);
     }
 }
Exemple #14
0
 /// <summary>
 /// Update - if the text file path exists, all ip addresses from each line will be unbanned
 /// </summary>
 /// <param name="cancelToken">Cancel token</param>
 public async Task Update(CancellationToken cancelToken)
 {
     try
     {
         if (File.Exists(textFilePath))
         {
             string[] lines = (await File.ReadAllLinesAsync(textFilePath, cancelToken)).Where(l => IPAddress.TryParse(l, out _)).ToArray();
             Logger.Warn("Queueing {0} ip addresses to unban from {1} file", lines.Length, textFilePath);
             UnblockIPAddresses(lines);
             ExtensionMethods.FileDeleteWithRetry(textFilePath);
         }
     }
     catch (Exception ex)
     {
         Logger.Error(ex);
     }
 }
Exemple #15
0
        // deleteRule will drop the rule and matching set before creating the rule and set, use this is you don't care to update the rule and set in place
        protected bool UpdateRuleDelta(string ruleName, string action, IEnumerable <IPBanFirewallIPAddressDelta> deltas, string hashType,
                                       int maxCount, bool deleteRule, IEnumerable <PortRange> allowPorts, CancellationToken cancelToken)
        {
            string ipFileTemp = OSUtility.Instance.GetTempFileName();

            try
            {
                // add and remove the appropriate ip addresses from the set
                using (StreamWriter writer = File.CreateText(ipFileTemp))
                {
                    if (cancelToken.IsCancellationRequested)
                    {
                        throw new OperationCanceledException(cancelToken);
                    }
                    writer.WriteLine($"create {ruleName} hash:{hashType} family {INetFamily} hashsize {hashSize} maxelem {maxCount} -exist");
                    foreach (IPBanFirewallIPAddressDelta delta in deltas)
                    {
                        if (cancelToken.IsCancellationRequested)
                        {
                            throw new OperationCanceledException(cancelToken);
                        }

                        if (IPAddressRange.TryParse(delta.IPAddress, out IPAddressRange range) &&
                            range.Begin.AddressFamily == addressFamily && range.End.AddressFamily == addressFamily)
                        {
                            try
                            {
                                if (delta.Added)
                                {
                                    if (range.Begin.Equals(range.End))
                                    {
                                        writer.WriteLine($"add {ruleName} {range.Begin} -exist");
                                    }
                                    else
                                    {
                                        writer.WriteLine($"add {ruleName} {range.ToCidrString()} -exist");
                                    }
                                }
                                else
                                {
                                    if (range.Begin.Equals(range.End))
                                    {
                                        writer.WriteLine($"del {ruleName} {range.Begin} -exist");
                                    }
                                    else
                                    {
                                        writer.WriteLine($"del {ruleName} {range.ToCidrString()} -exist");
                                    }
                                }
                            }
                            catch
                            {
                                // ignore invalid cidr ranges
                            }
                        }
                    }
                }

                if (cancelToken.IsCancellationRequested)
                {
                    throw new OperationCanceledException(cancelToken);
                }
                else
                {
                    // restore the deltas into the existing set
                    bool result = (RunProcess("ipset", true, $"restore < \"{ipFileTemp}\"") == 0);
                    CreateOrUpdateRule(ruleName, action, hashType, maxCount, allowPorts, cancelToken);
                    return(result);
                }
            }
            finally
            {
                ExtensionMethods.FileDeleteWithRetry(ipFileTemp);
            }
        }
Exemple #16
0
        /// <summary>
        /// Static constructor
        /// </summary>
        static OSUtility()
        {
            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 = OSUtility.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();
                    ExtensionMethods.FileDeleteWithRetry(tempFile);
                    if (string.IsNullOrWhiteSpace(versionText))
                    {
                        Logger.Error(new IOException("Unable to load os version from /etc/*release* ..."));
                    }
                    else
                    {
                        Name         = OSUtility.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        = OSUtility.Windows;
                    string tempFile = OSUtility.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);
                                ExtensionMethods.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
                                {
                                    Logger.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
                    isMac        = true;
                    Name         = OSUtility.Mac;
                    FriendlyName = "OSX";
                }
                else
                {
                    Name         = OSUtility.Unknown;
                    FriendlyName = "Unknown";
                }
            }
            catch (Exception ex)
            {
                Logger.Error("Error determining platform info", ex);
            }
        }
Exemple #17
0
        private void LoadOSInfo()
        {
            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
            CpuArchitecture = RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant();
            Version         = Environment.OSVersion.Version.ToString();
            Description     = RuntimeInformation.OSDescription;

            // attempt to get detailed version info
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                Name    = FriendlyName = OSUtility.Linux;
                isLinux = true;
                string tempFile = 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();
                ExtensionMethods.FileDeleteWithRetry(tempFile);
                if (string.IsNullOrWhiteSpace(versionText))
                {
                    Logger.Error(new IOException("Unable to load os version from /etc/*release* ..."));
                }
                else
                {
                    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        = FriendlyName = OSUtility.Windows;
                isWindows   = true;
                processVerb = "runas";
                try
                {
                    LoadVersionFromWmic();
                }
                catch (Exception ex)
                {
                    Logger.Error(ex, "Failed to load os info from wmic");

                    // last resort, try wmi api
                    LoadVersionFromWmiApi();
                }

                // Windows loves to add a trailing .0 for some reason
                Version = Regex.Replace(Version, "\\.0$", string.Empty);
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                // TODO: Implement better for MAC
                Name         = FriendlyName = OSUtility.Mac;
                FriendlyName = "OSX";
                isMac        = true;
            }
            else
            {
                Name         = OSUtility.Unknown;
                FriendlyName = "Unknown";
            }
        }
Exemple #18
0
        // deleteRule will drop the rule and matching set before creating the rule and set, use this is you don't care to update the rule and set in place
        protected bool UpdateRule(string ruleName, string action, IEnumerable <string> ipAddresses, string hashType, int maxCount,
                                  IEnumerable <PortRange> allowPorts, CancellationToken cancelToken)
        {
            string ipFileTemp = OSUtility.GetTempFileName();

            try
            {
                // add and remove the appropriate ip addresses from the set
                using (StreamWriter writer = File.CreateText(ipFileTemp))
                {
                    if (cancelToken.IsCancellationRequested)
                    {
                        throw new OperationCanceledException(cancelToken);
                    }
                    RunProcess("ipset", true, out IReadOnlyList <string> sets, "-L -n");
                    if (sets.Contains(ruleName))
                    {
                        writer.WriteLine($"flush {ruleName}");// hash:{hashType} family {INetFamily} hashsize {hashSize} maxelem {maxCount} -exist");
                    }
                    writer.WriteLine($"create {ruleName} hash:{hashType} family {INetFamily} hashsize {hashSize} maxelem {maxCount} -exist");
                    foreach (string ipAddress in ipAddresses)
                    {
                        if (cancelToken.IsCancellationRequested)
                        {
                            throw new OperationCanceledException(cancelToken);
                        }

                        if (IPAddressRange.TryParse(ipAddress, out IPAddressRange range) &&
                            range.Begin.AddressFamily == addressFamily && range.End.AddressFamily == addressFamily)
                        {
                            try
                            {
                                if (hashType != hashTypeCidrMask || range.Begin.Equals(range.End))
                                {
                                    writer.WriteLine($"add {ruleName} {range.Begin} -exist");
                                }
                                else
                                {
                                    writer.WriteLine($"add {ruleName} {range.ToCidrString()} -exist");
                                }
                            }
                            catch
                            {
                                // ignore invalid cidr ranges
                            }
                        }
                    }
                }

                if (cancelToken.IsCancellationRequested)
                {
                    throw new OperationCanceledException(cancelToken);
                }
                else
                {
                    // restore the set
                    bool result = (RunProcess("ipset", true, $"restore < \"{ipFileTemp}\"") == 0);
                    CreateOrUpdateRule(ruleName, action, hashType, maxCount, allowPorts, cancelToken);
                    return(result);
                }
            }
            finally
            {
                ExtensionMethods.FileDeleteWithRetry(ipFileTemp);
            }
        }
Exemple #19
0
        // deleteRule will drop the rule and matching set before creating the rule and set, use this is you don't care to update the rule and set in place
        protected bool UpdateRuleDelta(string ruleName, string action, IEnumerable<IPBanFirewallIPAddressDelta> deltas, string hashType,
            int maxCount, bool deleteRule, IEnumerable<PortRange> allowPorts, CancellationToken cancelToken)
        {

#if ENABLE_FIREWALL_PROFILING

            Stopwatch timer = Stopwatch.StartNew();

#endif

            string ipFileTemp = OSUtility.GetTempFileName();
            try
            {
                // add and remove the appropriate ip addresses from the set
                using (StreamWriter writer = File.CreateText(ipFileTemp))
                {
                    if (cancelToken.IsCancellationRequested)
                    {
                        throw new OperationCanceledException(cancelToken);
                    }
                    writer.WriteLine($"create {ruleName} hash:{hashType} family {INetFamily} hashsize {hashSize} maxelem {maxCount} -exist");
                    foreach (IPBanFirewallIPAddressDelta delta in deltas)
                    {
                        if (cancelToken.IsCancellationRequested)
                        {
                            throw new OperationCanceledException(cancelToken);
                        }

                        if (IPAddressRange.TryParse(delta.IPAddress, out IPAddressRange range) &&
                            range.Begin.AddressFamily == addressFamily && range.End.AddressFamily == addressFamily)
                        {
                            try
                            {
                                if (delta.Added)
                                {
                                    if (range.Begin.Equals(range.End))
                                    {
                                        writer.WriteLine($"add {ruleName} {range.Begin} -exist");
                                    }
                                    else
                                    {
                                        writer.WriteLine($"add {ruleName} {range.ToCidrString()} -exist");
                                    }
                                }
                                else
                                {
                                    if (range.Begin.Equals(range.End))
                                    {
                                        writer.WriteLine($"del {ruleName} {range.Begin} -exist");
                                    }
                                    else
                                    {
                                        writer.WriteLine($"del {ruleName} {range.ToCidrString()} -exist");
                                    }
                                }
                            }
                            catch
                            {
                                // ignore invalid cidr ranges
                            }
                        }
                    }
                }

                if (cancelToken.IsCancellationRequested)
                {
                    throw new OperationCanceledException(cancelToken);
                }
                else
                {
                    // restore the deltas into the existing set
                    bool result = (RunProcess("ipset", true, $"restore < \"{ipFileTemp}\"") == 0);
                    CreateOrUpdateRule(ruleName, action, hashType, maxCount, allowPorts, cancelToken);
                    return result;
                }
            }
            finally
            {
                ExtensionMethods.FileDeleteWithRetry(ipFileTemp);

#if ENABLE_FIREWALL_PROFILING

                timer.Stop();
                Logger.Warn("BlockIPAddressesDelta rule '{0}' took {1:0.00}ms with {2} ips",
                    ruleName, timer.Elapsed.TotalMilliseconds, deltas.Count());

#endif

            }
        }