private List <uint> LoadIPAddresses(string ruleName, string action, string hashType, int maxCount) { List <uint> ipAddresses = new List <uint>(); try { if (hashType != "ip") { throw new ArgumentException("Can only load hash of type 'ip'"); } CreateOrUpdateRule(ruleName, action, hashType, maxCount, null, default); // copy ip addresses from the rule to the set string fileName = GetSetFileName(ruleName); if (File.Exists(fileName)) { uint value; foreach (string line in File.ReadLines(fileName).Skip(1)) { string[] pieces = line.Split(' '); if (pieces.Length > 2 && pieces[0] == "add" && (value = IPBanFirewallUtility.ParseIPV4(pieces[2])) != 0) { ipAddresses.Add(value); } } } } catch (Exception ex) { IPBanLog.Error(ex); } return(ipAddresses); }
public bool IsIPAddressAllowed(string ipAddress) { return(allowedIPAddresses.Contains(IPBanFirewallUtility.ParseIPV4(ipAddress))); }
// 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 private List <uint> UpdateRule(string ruleName, string action, IEnumerable <string> ipAddresses, List <uint> existingIPAddresses, string hashType, int maxCount, bool deleteRule, IEnumerable <PortRange> allowPorts, CancellationToken cancelToken, out bool result) { string ipFile = GetSetFileName(ruleName); string ipFileTemp = ipFile + ".tmp"; List <uint> newIPAddressesUint = new List <uint>(); uint value = 0; // 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 (string ipAddress in ipAddresses) { if (cancelToken.IsCancellationRequested) { throw new OperationCanceledException(cancelToken); } // only allow ipv4 for now if (IPAddressRange.TryParse(ipAddress, out IPAddressRange range) && range.Begin.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && range.End.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && // if deleting the rule, don't track the uint value (!deleteRule || (value = IPBanFirewallUtility.ParseIPV4(ipAddress)) != 0)) { try { if (range.Begin.Equals(range.End)) { writer.WriteLine($"add {ruleName} {range.Begin} -exist"); } else { writer.WriteLine($"add {ruleName} {range.ToCidrString()} -exist"); } if (!deleteRule) { newIPAddressesUint.Add(value); } } catch { // ignore invalid cidr ranges } } } newIPAddressesUint.Sort(); // if the rule was deleted, no need to add del entries if (!deleteRule) { // for ip that dropped out, remove from firewall foreach (uint droppedIP in existingIPAddresses.Where(e => newIPAddressesUint.BinarySearch(e) < 0)) { writer.WriteLine($"del {ruleName} {IPBanFirewallUtility.IPV4ToString(droppedIP)} -exist"); } } } if (cancelToken.IsCancellationRequested) { throw new OperationCanceledException(cancelToken); } else { // TODO: Is there an easier way to move to a file that exists? if (File.Exists(ipFile)) { DeleteFile(ipFile); } File.Move(ipFileTemp, ipFile); if (deleteRule) { DeleteRule(ruleName); } // restore the file to get the set updated result = (RunProcess("ipset", true, $"restore < \"{ipFile}\"") == 0); // ensure rule exists for the set CreateOrUpdateRule(ruleName, action, hashType, maxCount, allowPorts, cancelToken); } return(newIPAddressesUint); }