/// <summary> /// Create a log file scanner /// </summary> /// <param name="failedLogin">Interface for handling failed logins</param> /// <param name="dns">Interface for dns lookup</param> /// <param name="source">The source, i.e. SSH or SMTP, etc.</param> /// <param name="pathAndMask">File path and mask (i.e. /var/log/auth*.log)</param> /// <param name="recursive">Whether to parse all sub directories of path and mask recursively</param> /// <param name="regex">Regex to parse file lines to pull out ipaddress and username</param> /// <param name="maxFileSize">Max size of file before it is deleted or 0 for unlimited</param> /// <param name="pingIntervalMilliseconds"></param> public IPBanLogFileScanner(IFailedLogin failedLogin, IDnsLookup dns, string source, string pathAndMask, bool recursive, string regex, long maxFileSize = 0, int pingIntervalMilliseconds = 10000) { failedLogin.ThrowIfNull(nameof(failedLogin)); dns.ThrowIfNull(nameof(dns)); Source = source; this.failedLogin = failedLogin; this.dns = dns; this.maxFileSize = maxFileSize; PathAndMask = pathAndMask; Regex = IPBanConfig.ParseRegex(regex); directoryToWatch = Path.GetDirectoryName(pathAndMask); fileMask = Path.GetFileName(pathAndMask); pingTimer = new System.Timers.Timer(pingIntervalMilliseconds); pingTimer.Elapsed += PingTimerElapsed; pingTimer.Start(); // add initial files SearchOption option = (recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); string dir = Path.GetDirectoryName(pathAndMask); if (Directory.Exists(dir)) { foreach (string existingFileName in Directory.GetFiles(dir, Path.GetFileName(pathAndMask), option)) { // start at end of existing files AddPingFile(existingFileName, new FileInfo(existingFileName).Length); } } }
public VotingController(IConferenceLoader conferenceLoader, IDataProvider dataProvider, IDnsLookup dnsLookup, IChartDataConverter chartDataConverter) { if (conferenceLoader == null) { throw new ArgumentNullException("conferenceLoader"); } if (dataProvider == null) { throw new ArgumentNullException("dataProvider"); } if (dnsLookup == null) { throw new ArgumentNullException("dnsLookup"); } if (chartDataConverter == null) { throw new ArgumentNullException("chartDataConverter"); } this.conferenceLoader = conferenceLoader; this.dataProvider = dataProvider; this.dnsLookup = dnsLookup; this.chartDataConverter = chartDataConverter; }
public VotingControllerBuilder() { conferenceLoader = Substitute.For <IConferenceLoader>(); dataProvider = Substitute.For <IDataProvider>(); dnsLookup = Substitute.For <IDnsLookup>(); chartDataConverter = Substitute.For <IChartDataConverter>(); }
public VotingControllerBuilder() { conferenceLoader = Substitute.For<IConferenceLoader>(); dataProvider = Substitute.For<IDataProvider>(); dnsLookup = Substitute.For<IDnsLookup>(); chartDataConverter = Substitute.For<IChartDataConverter>(); }
/// <summary> /// Get the local ip address of the local machine /// </summary> /// <param name="dns">Dns lookup</param> /// <param name="addressFamily">Desired address family</param> /// <returns>Local ip address or null if unable to determine. If no address family match, falls back to an ipv6 attempt.</returns> public static async Task <System.Net.IPAddress> GetLocalIPAddress(this IDnsLookup dns, System.Net.Sockets.AddressFamily addressFamily = System.Net.Sockets.AddressFamily.InterNetwork) { try { // append ipv4 first, then the ipv6 then the remote ip System.Net.IPAddress[] ips = await dns.GetHostAddressesAsync(Dns.GetHostName()); foreach (System.Net.IPAddress ip in ips) { if (ip.AddressFamily == addressFamily) { return(ip); } } foreach (System.Net.IPAddress ip in ips) { if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) { return(ip); } } } catch { } return(null); }
public Register(IUnitOfWork repo, IDnsLookup dnsLookup, IHashProvider hashProvider, IPublishEndpoint publisher, ILogger <Register> logger) { _repo = repo; _dnsLookup = dnsLookup; _hashProvider = hashProvider; _logger = logger; _publisher = publisher; }
/// <summary> /// Load IPBan config from file /// </summary> /// <param name="configFilePath">Config file path</param> /// <param name="service">Service</param> /// <param name="dns">Dns lookup for resolving ip addresses</param> /// <returns>IPBanConfig</returns> public static IPBanConfig LoadFromFile(string configFilePath, IDnsLookup dns) { configFilePath = (File.Exists(configFilePath) ? configFilePath : ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).FilePath); if (!File.Exists(configFilePath)) { throw new FileNotFoundException("Unable to find config file " + configFilePath); } return(LoadFromXml(File.ReadAllText(configFilePath), dns)); }
/// <summary> /// Get the local ip addresses of the local machine /// </summary> /// <param name="dns">Dns lookup</param> /// <param name="addressFamily">Desired address family or null for all</param> /// <returns>Local ip address or empty array if unable to determine. If no address family match, falls back to an ipv6 attempt.</returns> public static async Task <System.Net.IPAddress[]> GetLocalIPAddressesAsync(this IDnsLookup dns, System.Net.Sockets.AddressFamily?addressFamily = System.Net.Sockets.AddressFamily.InterNetwork) { try { // append ipv4 first, then the ipv6 then the remote ip return((await dns.GetHostAddressesAsync(dns.GetHostName())).Union(localHostIP).Where(i => addressFamily is null || i.AddressFamily == addressFamily).ToArray()); } catch { } return(new System.Net.IPAddress[0]); }
/// <summary> /// Create a log file scanner /// </summary> /// <param name="options">Options</param> public IPBanLogFileScanner(IPBanIPAddressLogFileScannerOptions options) : base(options.PathAndMask, options.MaxFileSizeBytes, options.PingIntervalMilliseconds) { options.ThrowIfNull(nameof(options)); options.LoginHandler.ThrowIfNull(nameof(options.LoginHandler)); options.Dns.ThrowIfNull(nameof(options.Dns)); Source = options.Source; this.loginHandler = options.LoginHandler; this.dns = options.Dns; this.regexFailure = IPBanConfig.ParseRegex(options.RegexFailure, true); this.regexFailureTimestampFormat = options.RegexFailureTimestampFormat; this.regexSuccess = IPBanConfig.ParseRegex(options.RegexSuccess, true); this.regexSuccessTimestampFormat = options.RegexSuccessTimestampFormat; }
/// <summary> /// Create a log file scanner /// </summary> /// <param name="options">Options</param> public IPBanLogFileScanner(IPBanIPAddressLogFileScannerOptions options) : base(options.PathAndMask, options.MaxFileSizeBytes, options.PingIntervalMilliseconds) { options.ThrowIfNull(nameof(options)); options.LoginHandler.ThrowIfNull(nameof(options.LoginHandler)); options.Dns.ThrowIfNull(nameof(options.Dns)); Source = options.Source; FailedLoginThreshold = options.FailedLoginThreshold; FailedLogLevel = options.FailedLogLevel; SuccessfulLogLevel = options.SuccessfulLogLevel; this.loginHandler = options.LoginHandler; this.dns = options.Dns; this.regexFailure = options.RegexFailure; this.regexFailureTimestampFormat = options.RegexFailureTimestampFormat; this.regexSuccess = options.RegexSuccess; this.regexSuccessTimestampFormat = options.RegexSuccessTimestampFormat; }
/// <summary> /// Get the ip addresses of the local machine /// </summary> /// <param name="dns">Dns lookup</param> /// <param name="allowLocal">Whether to return localhost ip</param> /// <param name="addressFamily">Desired address family or null for all</param> /// <returns>Local ip address or empty array if unable to determine. If no address family match, falls back to an ipv6 attempt.</returns> public static async Task <System.Net.IPAddress[]> GetLocalIPAddressesAsync(this IDnsLookup dns, bool allowLocal = true, System.Net.Sockets.AddressFamily?addressFamily = System.Net.Sockets.AddressFamily.InterNetwork) { try { // append ipv4 first, then the ipv6 then the remote ip List <IPAddress> ips = new List <IPAddress>(); ips.AddRange(await dns.GetHostAddressesAsync(dns.GetHostName())); if (allowLocal) { ips.AddRange(localHostIP); } return(ips.Where(ip => (allowLocal || ip.IsLocalHost()) || (addressFamily is null || ip.AddressFamily == addressFamily)).ToArray()); } catch { } return(new System.Net.IPAddress[0]); }
/// <summary> /// Create a log file scanner /// </summary> /// <param name="failedLogin">Interface for handling failed logins</param> /// <param name="dns">Interface for dns lookup</param> /// <param name="source">The source, i.e. SSH or SMTP, etc.</param> /// <param name="pathAndMask">File path and mask (i.e. /var/log/auth*.log)</param> /// <param name="recursive">Whether to parse all sub directories of path and mask recursively</param> /// <param name="regex">Regex to parse file lines to pull out ipaddress and username</param> /// <param name="maxFileSizeBytes">Max size of file (in bytes) before it is deleted or 0 for unlimited</param> /// <param name="pingIntervalMilliseconds">Ping interval in milliseconds, less than 1 for manual ping required</param> public IPBanIPAddressLogFileScanner ( IFailedLogin failedLogin, IDnsLookup dns, string source, string pathAndMask, bool recursive, string regex, long maxFileSizeBytes = 0, int pingIntervalMilliseconds = 0 ) : base(pathAndMask, recursive, maxFileSizeBytes, pingIntervalMilliseconds) { failedLogin.ThrowIfNull(nameof(failedLogin)); dns.ThrowIfNull(nameof(dns)); Source = source; this.failedLogin = failedLogin; this.dns = dns; this.regex = IPBanConfig.ParseRegex(regex); }
/// <summary> /// Create a log file scanner /// </summary> /// <param name="loginHandler">Interface for handling logins</param> /// <param name="dns">Interface for dns lookup</param> /// <param name="source">The source, i.e. SSH or SMTP, etc.</param> /// <param name="pathAndMask">File path and mask (i.e. /var/log/auth*.log)</param> /// <param name="recursive">Whether to parse all sub directories of path and mask recursively</param> /// <param name="regexFailure">Regex to parse file lines to pull out failed login ipaddress and username</param> /// <param name="regexSuccess">Regex to parse file lines to pull out successful login ipaddress and username</param> /// <param name="maxFileSizeBytes">Max size of file (in bytes) before it is deleted or 0 for unlimited</param> /// <param name="pingIntervalMilliseconds">Ping interval in milliseconds, less than 1 for manual ping required</param> public IPBanIPAddressLogFileScanner ( IIPAddressEventHandler loginHandler, IDnsLookup dns, string source, string pathAndMask, bool recursive, string regexFailure, string regexSuccess, long maxFileSizeBytes = 0, int pingIntervalMilliseconds = 0 ) : base(pathAndMask, recursive, maxFileSizeBytes, pingIntervalMilliseconds) { loginHandler.ThrowIfNull(nameof(loginHandler)); dns.ThrowIfNull(nameof(dns)); Source = source; this.loginHandler = loginHandler; this.dns = dns; this.regexFailure = IPBanConfig.ParseRegex(regexFailure); this.regexSuccess = IPBanConfig.ParseRegex(regexSuccess); }
/// <summary> /// Get the ip addresses of the local machine /// </summary> /// <param name="dns">Dns lookup</param> /// <param name="allowLocal">Whether to return localhost ip</param> /// <param name="addressFamily">Desired address family or null for all</param> /// <returns>Local ip address or empty array if unable to determine. If no address family match, falls back to an ipv6 attempt.</returns> public static async Task <System.Net.IPAddress[]> GetLocalIPAddressesAsync(this IDnsLookup dns, bool allowLocal = true, System.Net.Sockets.AddressFamily?addressFamily = System.Net.Sockets.AddressFamily.InterNetwork) { try { // append ipv4 first, then the ipv6 then the remote ip List <IPAddress> ips = new List <IPAddress>(); string hostName = await dns.GetHostNameAsync(); IPAddress[] hostAddresses = await dns.GetHostAddressesAsync(hostName); ips.AddRange(hostAddresses); // sort ipv4 first ips.Sort((ip1, ip2) => { int compare = ip1.AddressFamily.CompareTo(ip2.AddressFamily); if (compare == 0) { compare = ip1.CompareTo(ip2); } return(compare); }); if (allowLocal) { ips.AddRange(localHostIP); } return(ips.Where(ip => (allowLocal || !ip.IsLocalHost()) || (addressFamily is null || ip.AddressFamily == addressFamily)).ToArray()); } catch { // eat exception, delicious } return(new System.Net.IPAddress[0]); }
/// <summary> /// Load IPBan config from XML /// </summary> /// <param name="xml">XML string</param> /// <param name="dns">Dns lookup for resolving ip addresses, null for default</param> /// <param name="dnsList">Dns server list, null for none</param> /// <returns>IPBanConfig</returns> public static IPBanConfig LoadFromXml(string xml, IDnsLookup dns = null, IDnsServerList dnsList = null) { return(new IPBanConfig(xml, dns, dnsList)); }
public DnsLookupBuilder() { dnsLookup = Substitute.For<IDnsLookup>(); }
/// <summary> /// Get an ip address and user name out of text using regex. Regex may contain groups named source_[sourcename] to override the source. /// </summary> /// <param name="regex">Regex</param> /// <param name="text">Text</param> /// <param name="ipAddress">Found ip address or null if none</param> /// <param name="userName">Found user name or null if none</param> /// <param name="timestampFormat">Timestamp format</param> /// <param name="eventType">Event type</param> /// <param name="dns">Dns lookup to resolve ip addresses</param> /// <returns>Set of matches from text</returns> public static IEnumerable <IPAddressLogEvent> GetIPAddressEventsFromRegex(Regex regex, string text, string timestampFormat = null, IPAddressEventType eventType = IPAddressEventType.FailedLogin, IDnsLookup dns = null) { const string customSourcePrefix = "source_"; // if no regex or no text, we are done if (regex is null || string.IsNullOrWhiteSpace(text)) { yield break; } // remove control chars text = new string(text.Where(c => c == '\n' || c == '\t' || !char.IsControl(c)).ToArray()).Trim(); // go through all the matches and pull out event info foreach (Match match in regex.Matches(text)) { string userName = null; string ipAddress = null; string source = null; DateTime timestamp = default; // check for a user name Group userNameGroup = match.Groups["username"]; if (userNameGroup != null && userNameGroup.Success) { userName = (userName ?? userNameGroup.Value.Trim(regexTrimChars)); } // check for source Group sourceGroup = match.Groups["source"]; if (sourceGroup != null && sourceGroup.Success) { source = (source ?? sourceGroup.Value.Trim(regexTrimChars)); } // check for groups with a custom source name foreach (Group group in match.Groups) { if (group.Success && group.Name != null && string.IsNullOrWhiteSpace(source) && group.Name.StartsWith(customSourcePrefix)) { source = group.Name.Substring(customSourcePrefix.Length); } } // check for timestamp group Group timestampGroup = match.Groups["timestamp"]; if (timestampGroup != null && timestampGroup.Success) { string toParse = timestampGroup.Value.Trim(regexTrimChars); if (string.IsNullOrWhiteSpace(timestampFormat) || !DateTime.TryParseExact(toParse, timestampFormat.Trim(), CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal | DateTimeStyles.AdjustToUniversal, out timestamp)) { DateTime.TryParse(toParse, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal | DateTimeStyles.AdjustToUniversal, out timestamp); } } // check if the regex had an ipadddress group Group ipAddressGroup = match.Groups["ipaddress"]; if (ipAddressGroup is null) { ipAddressGroup = match.Groups["ipaddress_exact"]; } if (ipAddressGroup != null && ipAddressGroup.Success && !string.IsNullOrWhiteSpace(ipAddressGroup.Value)) { string tempIPAddress = ipAddressGroup.Value.Trim(); // in case of IP:PORT format, try a second time, stripping off the :PORT, saves having to do this in all // the different ip regex. int lastColon = tempIPAddress.LastIndexOf(':'); bool isValidIPAddress = IPAddress.TryParse(tempIPAddress, out IPAddress tmp); if (isValidIPAddress || (lastColon >= 0 && IPAddress.TryParse(tempIPAddress.Substring(0, lastColon), out tmp))) { ipAddress = tmp.ToString(); } // if we are parsing anything as ip address (including dns names) if (ipAddress is null && dns != null && ipAddressGroup.Name == "ipaddress" && tempIPAddress != Environment.MachineName && tempIPAddress != "-") { // Check Host by name Logger.Info("Parsing as IP failed, checking dns '{0}'", tempIPAddress); try { IPHostEntry entry = dns.GetHostEntryAsync(tempIPAddress).Sync(); if (entry != null && entry.AddressList != null && entry.AddressList.Length > 0) { ipAddress = entry.AddressList.FirstOrDefault().ToString(); Logger.Info("Dns result '{0}' = '{1}'", tempIPAddress, ipAddress); break; } } catch { Logger.Info("Parsing as dns failed '{0}'", tempIPAddress); } } } // see if there is a repeat indicator in the message int repeatCount = ExtractRepeatCount(match, text); // return an event for this match yield return(new IPAddressLogEvent(ipAddress, userName, source, repeatCount, eventType, timestamp)); } }
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); GetConfig <TimeSpan>("BanTime", ref banTime); GetConfig <bool>("ClearBannedIPAddressesOnRestart", ref clearBannedIPAddressesOnRestart); GetConfig <TimeSpan>("ExpireTime", ref expireTime); GetConfig <TimeSpan>("CycleTime", ref cycleTime); GetConfig <TimeSpan>("MinimumTimeBetweenFailedLoginAttempts", ref minimumTimeBetweenFailedLoginAttempts); GetConfig <string>("FirewallRulePrefix", ref firewallRulePrefix); GetConfig <bool>("CreateWhitelistFirewallRule", ref createWhitelistFirewallRule); 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, ref whiteListRegex, whiteListString, whiteListRegexString); PopulateList(blackList, ref blackListRegex, blacklistString, blacklistRegexString); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { expressions = new XmlSerializer(typeof(ExpressionsToBlock)).Deserialize(new XmlNodeReader(doc.SelectSingleNode("//ExpressionsToBlock"))) as ExpressionsToBlock; if (expressions != null) { foreach (ExpressionsToBlockGroup group in expressions.Groups) { foreach (ExpressionToBlock expression in group.Expressions) { expression.Regex = (expression.Regex ?? string.Empty).Trim(); } } } } else { expressions = new ExpressionsToBlock { Groups = new ExpressionsToBlockGroup[0] }; } try { LogFilesToParse logFilesToParse = new XmlSerializer(typeof(LogFilesToParse)).Deserialize(new XmlNodeReader(doc.SelectSingleNode("//LogFilesToParse"))) as LogFilesToParse; logFiles = (logFilesToParse == null ? new LogFileToParse[0] : logFilesToParse.LogFiles); } catch (Exception ex) { IPBanLog.Error(ex); logFiles = new LogFileToParse[0]; } GetConfig <string>("ProcessToRunOnBan", ref processToRunOnBan); // 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().Trim(); if (userNameTrimmed.Length > 0) { userNameWhitelist.Add(userNameTrimmed); } } 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); }
public DnsLookupBuilder() { dnsLookup = Substitute.For <IDnsLookup>(); }
internal VelvetService(IDnsLookup dnsLookup) { this.dnsLookup = dnsLookup; this.dnsServer = new DnsServer(IPAddress.Any, 10, 10, dnsLookup.ProcessQuery); }
public VotingControllerBuilder WithDnsLookup(IDnsLookup dnsLookup) { this.dnsLookup = dnsLookup; return(this); }
/// <summary> /// Get an ip address and user name out of text using regex. Regex may contain groups named source_[sourcename] to override the source. /// </summary> /// <param name="regex">Regex</param> /// <param name="text">Text</param> /// <param name="ipAddress">Found ip address or null if none</param> /// <param name="userName">Found user name or null if none</param> /// <param name="timestampFormat">Timestamp format</param> /// <param name="eventType">Event type</param> /// <param name="dns">Dns lookup to resolve ip addresses</param> /// <returns>Set of matches from text</returns> public static IEnumerable <IPAddressLogEvent> GetIPAddressEventsFromRegex(Regex regex, string text, string timestampFormat = null, IPAddressEventType eventType = IPAddressEventType.FailedLogin, IDnsLookup dns = null) { const string customSourcePrefix = "source_"; // if no regex or no text, we are done if (regex is null || string.IsNullOrWhiteSpace(text)) { yield break; } // remove control chars text = new string(text.Where(c => c == '\n' || c == '\t' || !char.IsControl(c)).ToArray()); // go through all the matches and pull out event info MatchCollection matches = regex.Matches(text); foreach (Match match in matches) { string userName = null; string ipAddress = null; string source = null; DateTime timestamp = default; // check for a user name Group userNameGroup = match.Groups["username"]; if (userNameGroup != null && userNameGroup.Success) { userName ??= userNameGroup.Value.Trim(regexTrimChars); } // check for source Group sourceGroup = match.Groups["source"]; if (sourceGroup != null && sourceGroup.Success) { source ??= sourceGroup.Value.Trim(regexTrimChars); } // check for groups with a custom source name foreach (Group group in match.Groups) { if (group.Success && group.Name != null && string.IsNullOrWhiteSpace(source) && group.Name.StartsWith(customSourcePrefix)) { source = group.Name[customSourcePrefix.Length..];
/// <summary> /// Load IPBan config from XML /// </summary> /// <param name="xml">XML string</param> /// <param name="service">Service</param> /// <param name="dns">Dns lookup for resolving ip addresses</param> /// <returns>IPBanConfig</returns> public static IPBanConfig LoadFromXml(string xml, IDnsLookup dns) { return(new IPBanConfig(xml, dns)); }
public VotingControllerBuilder WithDnsLookup(IDnsLookup dnsLookup) { this.dnsLookup = dnsLookup; return this; }
/// <summary> /// Get an ip address and user name out of text using regex. Regex may contain groups named source_[sourcename] to override the source. /// </summary> /// <param name="dns">Dns lookup to resolve ip addresses</param> /// <param name="regex">Regex</param> /// <param name="text">Text</param> /// <param name="ipAddress">Found ip address or null if none</param> /// <param name="userName">Found user name or null if none</param> /// <returns>True if a regex match was found, false otherwise</returns> public static IPAddressLogEvent GetIPAddressInfoFromRegex(IDnsLookup dns, Regex regex, string text) { const string customSourcePrefix = "source_"; bool foundMatch = false; string userName = null; string ipAddress = null; string source = null; int repeatCount = 1; Match repeater = Regex.Match(text, "message repeated (?<count>[0-9]+) times", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); if (repeater.Success) { repeatCount = int.Parse(repeater.Groups["count"].Value, CultureInfo.InvariantCulture); } foreach (Match m in regex.Matches(text)) { if (!m.Success) { continue; } // check for a user name Group userNameGroup = m.Groups["username"]; if (userNameGroup != null && userNameGroup.Success) { userName = (userName ?? userNameGroup.Value.Trim('\'', '\"', '(', ')', '[', ']', '{', '}', ' ', '\r', '\n')); } Group sourceGroup = m.Groups["source"]; if (sourceGroup != null && sourceGroup.Success) { source = (source ?? sourceGroup.Value.Trim('\'', '\"', '(', ')', '[', ']', '{', '}', ' ', '\r', '\n')); } if (string.IsNullOrWhiteSpace(source)) { foreach (Group group in m.Groups) { if (group.Success && group.Name != null && group.Name.StartsWith(customSourcePrefix)) { source = group.Name.Substring(customSourcePrefix.Length); } } } // check if the regex had an ipadddress group Group ipAddressGroup = m.Groups["ipaddress"]; if (ipAddressGroup is null) { ipAddressGroup = m.Groups["ipaddress_exact"]; } if (ipAddressGroup != null && ipAddressGroup.Success && !string.IsNullOrWhiteSpace(ipAddressGroup.Value)) { string tempIPAddress = ipAddressGroup.Value.Trim(); // in case of IP:PORT format, try a second time, stripping off the :PORT, saves having to do this in all // the different ip regex. int lastColon = tempIPAddress.LastIndexOf(':'); bool isValidIPAddress = IPAddress.TryParse(tempIPAddress, out IPAddress tmp); if (isValidIPAddress || (lastColon >= 0 && IPAddress.TryParse(tempIPAddress.Substring(0, lastColon), out tmp))) { ipAddress = tmp.ToString(); foundMatch = true; break; } // if we are parsing anything as ip address (including dns names) if (ipAddressGroup.Name == "ipaddress" && tempIPAddress != Environment.MachineName && tempIPAddress != "-") { // Check Host by name Logger.Info("Parsing as IP failed, checking dns '{0}'", tempIPAddress); try { IPHostEntry entry = dns.GetHostEntryAsync(tempIPAddress).Sync(); if (entry != null && entry.AddressList != null && entry.AddressList.Length > 0) { ipAddress = entry.AddressList.FirstOrDefault().ToString(); Logger.Info("Dns result '{0}' = '{1}'", tempIPAddress, ipAddress); foundMatch = true; break; } } catch { Logger.Info("Parsing as dns failed '{0}'", tempIPAddress); } } } else { // found a match but no ip address, that is OK. foundMatch = true; } } return(new IPAddressLogEvent(ipAddress, userName, source, repeatCount, IPAddressEventType.FailedLogin) { FoundMatch = foundMatch }); }
private IPBanConfig(string xml, IDnsLookup dns = null, IDnsServerList dnsList = null, IHttpRequestMaker httpRequestMaker = null) { this.dns = dns ?? DefaultDnsLookup.Instance; this.dnsList = dnsList; this.httpRequestMaker = httpRequestMaker; // deserialize with XmlDocument, the .net core Configuration class is quite buggy XmlDocument doc = new XmlDocument(); doc.LoadXml(xml); Xml = xml; foreach (XmlNode node in doc.SelectNodes("/configuration/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++) { // according to documentation, a ban time of 0 should become max ban time if (banTimes[i].Ticks <= 0) { banTimes[i] = maxBanTimeSpan; } else { banTimes[i] = banTimes[i].Clamp(TimeSpan.FromMinutes(1.0), maxBanTimeSpan); } } GetConfig <bool>("ClearBannedIPAddressesOnRestart", ref clearBannedIPAddressesOnRestart); GetConfig <bool>("ClearFailedLoginsOnSuccessfulLogin", ref clearFailedLoginsOnSuccessfulLogin); GetConfig <TimeSpan>("ExpireTime", ref expireTime, TimeSpan.Zero, maxBanTimeSpan); if (expireTime.TotalMinutes < 1.0) { expireTime = 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, whitelistOther, ref whitelistRegex, whitelistString, whitelistRegexString); PopulateList(blackList, blackListRanges, blackListOther, ref blackListRegex, blacklistString, blacklistRegexString); XmlNode node2 = doc.SelectSingleNode("/configuration/ExpressionsToBlock"); if (node2 != null) { try { expressionsFailure = new XmlSerializer(typeof(EventViewerExpressionsToBlock)).Deserialize(new XmlNodeReader(node2)) as EventViewerExpressionsToBlock; } catch (Exception ex) { expressionsFailure = new EventViewerExpressionsToBlock { Groups = new List <EventViewerExpressionGroup>() }; Logger.Error("Failed to load expressions to block", ex); } if (expressionsFailure != null) { foreach (EventViewerExpressionGroup group in expressionsFailure.Groups) { foreach (EventViewerExpression expression in group.Expressions) { expression.Regex = (expression.Regex?.ToString() ?? string.Empty).Trim(); } } } } node2 = doc.SelectSingleNode("/configuration/ExpressionsToNotify"); if (node2 != null) { try { expressionsSuccess = new XmlSerializer(typeof(EventViewerExpressionsToNotify)).Deserialize(new XmlNodeReader(node2)) as EventViewerExpressionsToNotify; } catch (Exception ex) { expressionsSuccess = new EventViewerExpressionsToNotify { Groups = new List <EventViewerExpressionGroup>() }; Logger.Error("Failed to load expressions to notify: {0}", ex); } 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(); } } } } try { XmlNode logFilesToParseNode = doc.SelectSingleNode("/configuration/LogFilesToParse"); if (logFilesToParseNode != null && new XmlSerializer(typeof(IPBanLogFilesToParse)).Deserialize(new XmlNodeReader(logFilesToParseNode)) is IPBanLogFilesToParse logFilesToParse) { logFiles = logFilesToParse.LogFiles; } else { logFiles = emptyLogFilesToParseArray; } } catch (Exception ex) { Logger.Error("Failed to load log files to parse", ex); logFiles = emptyLogFilesToParseArray; } GetConfig <string>("ProcessToRunOnBan", ref processToRunOnBan); GetConfig <bool>("UseDefaultBannedIPAddressHandler", ref useDefaultBannedIPAddressHandler); string userNameWhitelistString = GetConfig <string>("UserNameWhitelist", string.Empty); if (!string.IsNullOrEmpty(userNameWhitelistString)) { foreach (string userName in userNameWhitelistString.Split(',')) { string userNameTrimmed = userName.Normalize().ToUpperInvariant().Trim(); 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); GetConfig <string>("FirewallUriRules", ref firewallUriRules); if (string.IsNullOrWhiteSpace(firewallUriRules)) { // legacy GetConfig <string>("FirewallUriSources", ref firewallUriRules); } firewallUriRules = (firewallUriRules ?? string.Empty).Trim(); // parse firewall block rules, one per line ParseFirewallBlockRules(); }
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, whiteListOther, ref whiteListRegex, whiteListString, whiteListRegexString); PopulateList(blackList, blackListRanges, blackListOther, ref blackListRegex, blacklistString, blacklistRegexString); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { XmlNode node = doc.SelectSingleNode("//ExpressionsToBlock"); if (node != null) { expressionsFailure = new XmlSerializer(typeof(EventViewerExpressionsToBlock)).Deserialize(new XmlNodeReader(node)) 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(); } } } } node = doc.SelectSingleNode("//ExpressionsToNotify"); if (node != null) { expressionsSuccess = new XmlSerializer(typeof(EventViewerExpressionsToNotify)).Deserialize(new XmlNodeReader(node)) 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) { Logger.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); GetConfig <string>("FirewallUriRules", ref firewallUriRules); if (string.IsNullOrWhiteSpace(firewallUriRules)) { // legacy GetConfig <string>("FirewallUriSources", ref firewallUriRules); } firewallUriRules = (firewallUriRules ?? string.Empty).Trim(); // parse firewall block rules, one per line ParseFirewallBlockRules(); }