コード例 #1
0
ファイル: IPBanUriFirewallRule.cs プロジェクト: s4ndxyz/IPBan
        private Task ProcessResult(string text, CancellationToken cancelToken)
        {
            using StringReader reader = new(text);
            string line;
            List <IPAddressRange> ranges = new();
            int lines = 0;

            while ((line = reader.ReadLine()) != null)
            {
                if (lines++ > 10000)
                {
                    // prevent too many lines from crashing us
                    break;
                }

                // trim line, ignore if necessary
                line = line.Trim();
                if (line.Length == 0 || line.StartsWith("#") || line.StartsWith("'") || line.StartsWith("REM") ||
                    !IPAddressRange.TryParse(line, out IPAddressRange range))
                {
                    continue;
                }
                else if (whitelistChecker is null || !whitelistChecker.IsWhitelisted(range))
                {
                    // make sure to add only ranges that are not whitelisted
                    ranges.Add(range);
                }
            }

            return(firewall.BlockIPAddresses(RulePrefix, ranges, null, cancelToken));
        }
コード例 #2
0
ファイル: IPBanLinuxFirewall.cs プロジェクト: SMG999/IPBan
        public override Task <bool> AllowIPAddresses(string ruleNamePrefix, IEnumerable <IPAddressRange> ipAddresses, IEnumerable <PortRange> allowedPorts = null, CancellationToken cancelToken = default)
        {
            IEnumerable <IPAddressRange> ipv4 = ipAddresses.Where(i => IPAddressRange.TryParse(i, out IPAddressRange obj) && obj.Begin.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);
            IEnumerable <IPAddressRange> ipv6 = ipAddresses.Where(i => IPAddressRange.TryParse(i, out IPAddressRange obj) && obj.Begin.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6);
            bool result = base.AllowIPAddresses(ruleNamePrefix, ipv4, allowedPorts, cancelToken).Sync();

            if (result)
            {
                result = firewall6.AllowIPAddresses(ruleNamePrefix, ipv6, allowedPorts, cancelToken).Sync();
            }
            return(Task.FromResult(result));
        }
コード例 #3
0
        public IEnumerable <IPAddressRange> EnumerateIPAddresses(string ruleNamePrefix = null)
        {
            string prefix = (string.IsNullOrWhiteSpace(ruleNamePrefix) ? RulePrefix : RulePrefix + ruleNamePrefix);

            foreach (INetFwRule rule in EnumerateRulesMatchingPrefix(prefix))
            {
                string ipList = rule.RemoteAddresses;
                if (!string.IsNullOrWhiteSpace(ipList) && ipList != "*")
                {
                    string[] ips = ipList.Split(',');
                    foreach (string ip in ips)
                    {
                        if (IPAddressRange.TryParse(ip, out IPAddressRange range))
                        {
                            yield return(range);
                        }
                        // else // should never happen
                    }
                }
            }
        }
コード例 #4
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 TryNormalizeIPAddress(this string ipAddress, out string normalizedIP)
 {
     normalizedIP = (ipAddress ?? string.Empty).Trim();
     if (string.IsNullOrWhiteSpace(normalizedIP) ||
         normalizedIP == "-" ||
         normalizedIP == "0.0.0.0" ||
         normalizedIP == "127.0.0.1" ||
         normalizedIP == "::0" ||
         normalizedIP == "::1" ||
         !IPAddressRange.TryParse(normalizedIP, out IPAddressRange range))
     {
         // try parsing assuming the ip is followed by a port
         int pos = normalizedIP.LastIndexOf(':');
         if (pos >= 0)
         {
             normalizedIP = normalizedIP.Substring(0, pos);
             if (!IPAddressRange.TryParse(normalizedIP, out range))
             {
                 normalizedIP = null;
                 return(false);
             }
         }
         else
         {
             normalizedIP = null;
             return(false);
         }
     }
     try
     {
         normalizedIP = (range.Begin.Equals(range.End) ? range.Begin.ToString() : range.ToCidrString());
     }
     catch (Exception ex)
     {
         Logger.Debug("Failed to normalize ip {0}, it is not a single ip or cidr range: {1}", ipAddress, ex);
         return(false);
     }
     return(true);
 }
コード例 #5
0
        private void PopulateList(HashSet <System.Net.IPAddress> set, List <IPAddressRange> ranges, HashSet <string> others, ref Regex regex, string setValue, string regexValue)
        {
            setValue   = (setValue ?? string.Empty).Trim();
            regexValue = (regexValue ?? string.Empty).Replace("*", @"[0-9A-Fa-f:]+?").Trim();
            set.Clear();
            regex = null;

            if (!string.IsNullOrWhiteSpace(setValue))
            {
                foreach (string entry in setValue.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(e => e.Trim()))
                {
                    if (entry != "0.0.0.0" && entry != "::0" && entry != "127.0.0.1" && entry != "::1" && entry != "localhost")
                    {
                        try
                        {
                            if (IPAddressRange.TryParse(entry, out IPAddressRange range))
                            {
                                if (range.Begin.Equals(range.End))
                                {
                                    set.Add(range.Begin);
                                }
                                else if (!ranges.Contains(range))
                                {
                                    ranges.Add(range);
                                }
                            }
                            else
                            {
                                if (dns != null)
                                {
                                    try
                                    {
                                        // add entries for each ip address that matches the dns entry
                                        IPAddress[] addresses = dns.GetHostEntryAsync(entry).Sync().AddressList;
                                        if (addresses != null)
                                        {
                                            foreach (IPAddress adr in addresses)
                                            {
                                                set.Add(adr);
                                            }
                                        }
                                    }
                                    catch
                                    {
                                        // eat exception, nothing we can do
                                        others.Add(entry);
                                    }
                                }
                                else
                                {
                                    // add the entry itself
                                    others.Add(entry);
                                }
                            }
                        }
                        catch (System.Net.Sockets.SocketException)
                        {
                            // ignore, dns lookup fails
                        }
                    }
                }
            }

            if (!string.IsNullOrWhiteSpace(regexValue))
            {
                regex = ParseRegex(regexValue);
            }
        }
コード例 #6
0
        private void PopulateList(HashSet <System.Net.IPAddress> set,
                                  HashSet <IPAddressRange> ranges,
                                  HashSet <string> others,
                                  ref Regex regex,
                                  string setValue,
                                  string regexValue)
        {
            setValue   = (setValue ?? string.Empty).Trim();
            regexValue = (regexValue ?? string.Empty).Replace("*", @"[0-9A-Fa-f:]+?").Trim();
            set.Clear();
            regex = null;

            if (!string.IsNullOrWhiteSpace(setValue))
            {
                foreach (string entry in setValue.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(e => e.Trim()))
                {
                    string entryWithoutComment = entry;
                    int    pos = entryWithoutComment.IndexOf('?');
                    if (pos >= 0)
                    {
                        entryWithoutComment = entryWithoutComment.Substring(0, pos);
                    }
                    entryWithoutComment = entryWithoutComment.Trim();
                    if (!ignoreListEntries.Contains(entryWithoutComment))
                    {
                        if (IPAddressRange.TryParse(entryWithoutComment, out IPAddressRange range))
                        {
                            if (range.Begin.Equals(range.End))
                            {
                                set.Add(range.Begin);
                            }
                            else
                            {
                                ranges.Add(range);
                            }
                        }
                        else if (Uri.CheckHostName(entryWithoutComment) != UriHostNameType.Unknown)
                        {
                            try
                            {
                                // add entries for each ip address that matches the dns entry
                                IPAddress[] addresses = null;
                                ExtensionMethods.Retry(() => addresses = dns.GetHostAddressesAsync(entryWithoutComment).Sync());
                                foreach (IPAddress adr in addresses)
                                {
                                    set.Add(adr);
                                }
                            }
                            catch (Exception ex)
                            {
                                Logger.Error(ex, "Unable to resolve dns for {0}", entryWithoutComment);

                                // eat exception, nothing we can do
                                others.Add(entryWithoutComment);
                            }
                        }
                        else
                        {
                            others.Add(entryWithoutComment);
                        }
                    }
                }
            }

            if (!string.IsNullOrWhiteSpace(regexValue))
            {
                regex = ParseRegex(regexValue);
            }
        }
コード例 #7
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);
            }
        }
コード例 #8
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);
            }
        }
コード例 #9
0
ファイル: IPBanConfig.cs プロジェクト: iam006/IPBan
        private void PopulateList(HashSet <System.Net.IPAddress> set,
                                  HashSet <IPAddressRange> ranges,
                                  HashSet <string> others,
                                  ref Regex regex,
                                  string setValue,
                                  string regexValue)
        {
            setValue   = (setValue ?? string.Empty).Trim();
            regexValue = (regexValue ?? string.Empty).Replace("*", @"[0-9A-Fa-f]+?").Trim();
            set.Clear();
            regex = null;

            if (!string.IsNullOrWhiteSpace(setValue))
            {
                List <string> entries = new List <string>();
                foreach (string entry in setValue.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(e => e.Trim()))
                {
                    string entryWithoutComment = entry;
                    int    pos = entryWithoutComment.IndexOf('?');
                    if (pos >= 0)
                    {
                        entryWithoutComment = entryWithoutComment.Substring(0, pos);
                    }
                    entryWithoutComment = entryWithoutComment.Trim();
                    entries.Add(entryWithoutComment);
                }
                List <Task> entryTasks = new List <Task>();

                // iterate in parallel for performance
                foreach (string entry in entries)
                {
                    string entryWithoutComment = entry;
                    entryTasks.Add(Task.Run(async() =>
                    {
                        bool isUserName;
                        if (entryWithoutComment.StartsWith("user:"******"user:"******"Unable to resolve dns for {0}: {1}", entryWithoutComment, ex.Message);

                                    lock (others)
                                    {
                                        // eat exception, nothing we can do
                                        others.Add(entryWithoutComment);
                                    }
                                }
                            }
                            else
                            {
                                lock (others)
                                {
                                    others.Add(entryWithoutComment);
                                }
                            }
                        }
コード例 #10
0
ファイル: IPBanConfig.cs プロジェクト: Magnalle/IPBan
        private void PopulateList(HashSet <System.Net.IPAddress> set,
                                  HashSet <IPAddressRange> ranges,
                                  HashSet <string> others,
                                  ref Regex regex,
                                  string setValue,
                                  string regexValue)
        {
            setValue   = (setValue ?? string.Empty).Trim();
            regexValue = (regexValue ?? string.Empty).Replace("*", @"[0-9A-Fa-f]+?").Trim();
            set.Clear();
            regex = null;

            void AddIPAddressRange(IPAddressRange range)
            {
                if (range.Begin.Equals(range.End))
                {
                    lock (set)
                    {
                        set.Add(range.Begin);
                    }
                }
                else
                {
                    lock (ranges)
                    {
                        ranges.Add(range);
                    }
                }
            }

            if (!string.IsNullOrWhiteSpace(setValue))
            {
                List <string> entries = new List <string>();
                foreach (string entry in setValue.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(e => e.Trim()))
                {
                    string entryWithoutComment = entry;
                    int    pos = entryWithoutComment.IndexOf('?');
                    if (pos >= 0)
                    {
                        entryWithoutComment = entryWithoutComment.Substring(0, pos);
                    }
                    entryWithoutComment = entryWithoutComment.Trim();
                    entries.Add(entryWithoutComment);
                }
                List <Task> entryTasks = new List <Task>();

                // iterate in parallel for performance
                foreach (string entry in entries)
                {
                    string entryWithoutComment = entry;
                    entryTasks.Add(Task.Run(async() =>
                    {
                        bool isUserName;
                        if (entryWithoutComment.StartsWith("user:"******"user:"******"https://", StringComparison.OrdinalIgnoreCase) ||
                                      entryWithoutComment.StartsWith("http://", StringComparison.OrdinalIgnoreCase)))
                            {
                                try
                                {
                                    if (httpRequestMaker != null)
                                    {
                                        // assume url list of ips, newline delimited
                                        byte[] ipListBytes = null;
                                        Uri uri            = new Uri(entryWithoutComment);
                                        await ExtensionMethods.RetryAsync(async() => ipListBytes = await httpRequestMaker.MakeRequestAsync(uri, null, ipListHeaders));
                                        string ipList = Encoding.UTF8.GetString(ipListBytes);
                                        if (!string.IsNullOrWhiteSpace(ipList))
                                        {
                                            foreach (string item in ipList.Split('\n'))
                                            {
                                                if (IPAddressRange.TryParse(item.Trim(), out IPAddressRange ipRangeFromUrl))
                                                {
                                                    AddIPAddressRange(ipRangeFromUrl);
                                                }
                                            }
                                        }
                                    }
                                }
                                catch (Exception ex)
                                {
                                    Logger.Error(ex, "Failed to get ip list from url {0}", entryWithoutComment);
                                }
                            }
                            else if (!isUserName && Uri.CheckHostName(entryWithoutComment) != UriHostNameType.Unknown)
                            {
                                try
                                {
                                    // add entries for each ip address that matches the dns entry
                                    IPAddress[] addresses = null;
                                    await ExtensionMethods.RetryAsync(async() => addresses = await dns.GetHostAddressesAsync(entryWithoutComment),
                                                                      exceptionRetry: _ex =>
                                    {
                                        // ignore host not found errors
                                        return(!(_ex is System.Net.Sockets.SocketException socketEx) ||
                                               socketEx.SocketErrorCode != System.Net.Sockets.SocketError.HostNotFound);
                                    });

                                    lock (set)
                                    {
                                        foreach (IPAddress adr in addresses)
                                        {
                                            set.Add(adr);
                                        }
                                    }
                                }
                                catch (Exception ex)
                                {
                                    Logger.Debug("Unable to resolve dns for {0}: {1}", entryWithoutComment, ex.Message);

                                    lock (others)
                                    {
                                        // eat exception, nothing we can do
                                        others.Add(entryWithoutComment);
                                    }
                                }
                            }
                            else
                            {
                                lock (others)
                                {
                                    others.Add(entryWithoutComment);
                                }
                            }
                        }
コード例 #11
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

            }
        }