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); } }
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); } }
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); }
/// <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); } }
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); } }
private async Task RunConsoleService(string[] args) { try { await start.Invoke(args); } catch (Exception ex) { IPBanLog.Error(ex); } }
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)); } }
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)); } }
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)); } }
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)); } }
/// <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); } }
protected override void OnStart(string[] args) { base.OnStart(args); Task.Run(async() => { try { await runner.start.Invoke(args); } catch (Exception ex) { IPBanLog.Error(ex); } }); }
/// <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); } }
/// <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); } }
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); }
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); } } } }
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"); } }
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); } }
/// <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); } }
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); } }
/// <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 { } }
/// <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); }
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); } }
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(); }
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); } }