/// <summary> /// Get external ip address of the local machine. /// The url should the ip address in text format, and may contain comma separated ip addresses, in which case the last value will be used. /// </summary> /// <param name="requestMaker">Request maker</param> /// <param name="url">Url</param> /// <returns>IP address</returns> public async Task <System.Net.IPAddress> LookupExternalIPAddressAsync(IHttpRequestMaker requestMaker, string url) { byte[] bytes = await requestMaker.MakeRequestAsync(new Uri(url)); string ipString = Encoding.UTF8.GetString(bytes).Split(',').Last().Trim(); if (System.Net.IPAddress.TryParse(ipString, out System.Net.IPAddress ipAddress)) { if (ipAddress.IsIPv4MappedToIPv6) { ipAddress = ipAddress.MapToIPv4(); } } else { ipAddress = System.Net.IPAddress.Loopback; } return(ipAddress); }
/// <summary> /// Get external ip address of the local machine. /// The url should the ip address in text format, and may contain comma separated ip addresses, in which case the last value will be used. /// </summary> /// <param name="requestMaker">Request maker or null for default</param> /// <param name="url">Url or null for default</param> /// <returns>IP address</returns> public async Task <System.Net.IPAddress> LookupExternalIPAddressAsync(IHttpRequestMaker requestMaker = null, string url = null) { if (string.IsNullOrWhiteSpace(url)) { url = "https://checkip.amazonaws.com"; } byte[] bytes = null; Exception ex = null; // try up to 3 times to get external ip for (int i = 0; i < 3; i++) { try { bytes = await(requestMaker ?? this.requestMaker).MakeRequestAsync(new Uri(url)); break; } catch (Exception _ex) { ex = _ex; await Task.Delay(600); } } if (bytes is null) { throw new System.Net.WebException("Unable to get external ip address", ex); } string ipString = Encoding.UTF8.GetString(bytes).Split(',').Last().Trim(); if (System.Net.IPAddress.TryParse(ipString, out System.Net.IPAddress ipAddress)) { if (ipAddress.IsIPv4MappedToIPv6) { ipAddress = ipAddress.MapToIPv4(); } } else { ipAddress = System.Net.IPAddress.Loopback; } return(ipAddress); }
/// <summary> /// Get external ip address of the local machine. /// The url should the ip address in text format, and may contain comma separated ip addresses, in which case the last value will be used. /// </summary> /// <param name="requestMaker">Request maker or null for default</param> /// <param name="url">Url or null for default</param> /// <returns>IP address</returns> public async Task <System.Net.IPAddress> LookupExternalIPAddressAsync(IHttpRequestMaker requestMaker = null, string url = null) { if (string.IsNullOrWhiteSpace(url)) { url = "https://checkip.amazonaws.com"; } byte[] bytes = await(requestMaker ?? this.requestMaker).MakeRequestAsync(new Uri(url)); string ipString = Encoding.UTF8.GetString(bytes).Split(',').Last().Trim(); if (System.Net.IPAddress.TryParse(ipString, out System.Net.IPAddress ipAddress)) { if (ipAddress.IsIPv4MappedToIPv6) { ipAddress = ipAddress.MapToIPv4(); } } else { ipAddress = System.Net.IPAddress.Loopback; } return(ipAddress); }
/// <summary> /// Constructor /// </summary> /// <param name="firewall">The firewall to block with</param> /// <param name="whitelistChecker">Whitelist checker</param> /// <param name="httpRequestMaker">Http request maker for http uris, can leave null if uri is file</param> /// <param name="rulePrefix">Firewall rule prefix</param> /// <param name="interval">Interval to check uri for changes</param> /// <param name="uri">Uri, can be either file or http(s).</param> public IPBanUriFirewallRule(IIPBanFirewall firewall, IIsWhitelisted whitelistChecker, IHttpRequestMaker httpRequestMaker, string rulePrefix, TimeSpan interval, Uri uri) { this.firewall = firewall.ThrowIfNull(); this.whitelistChecker = whitelistChecker.ThrowIfNull(); this.httpRequestMaker = httpRequestMaker; RulePrefix = rulePrefix.ThrowIfNull(); Uri = uri.ThrowIfNull(); Interval = (interval.TotalSeconds < 5.0 ? fiveSeconds : interval); if (!uri.IsFile) { // ensure uri ends with slash if (!uri.ToString().EndsWith("/")) { uri = new Uri(uri.ToString() + "/"); } httpClient = new HttpClient { BaseAddress = uri, Timeout = thirtySeconds }; } }
/// <inheritdoc /> public async Task HandleBannedIPAddress(string ipAddress, string source, string userName, string osName, string osVersion, string assemblyVersion, IHttpRequestMaker requestMaker) { #if DEBUG if (!UnitTestDetector.Running) { return; } #endif if (requestMaker is null) { return; } try { if (!System.Net.IPAddress.TryParse(ipAddress, out System.Net.IPAddress ipAddressObj) || ipAddressObj.IsInternal()) { return; } // submit url to ipban public database so that everyone can benefit from an aggregated list of banned ip addresses DateTime now = IPBanService.UtcNow; string timestamp = now.ToString("o"); string url = $"/IPSubmitBanned?ip={ipAddress.UrlEncode()}&osname={osName.UrlEncode()}&osversion={osVersion.UrlEncode()}&source={source.UrlEncode()}×tamp={timestamp.UrlEncode()}&userName={userName.UrlEncode()}&version={assemblyVersion.UrlEncode()}"; using var hasher = SHA256.Create(); string hash = Convert.ToBase64String(hasher.ComputeHash(Encoding.UTF8.GetBytes(url + IPBanResources.IPBanKey1))); url += "&hash=" + hash.UrlEncode(); url = BaseUrl + url; string timestampUnix = now.ToUnixMillisecondsLong().ToString(CultureInfo.InvariantCulture); List <KeyValuePair <string, object> > headers; if (PublicAPIKey != null && PublicAPIKey.Length != 0) { // send api key and timestamp headers = new List <KeyValuePair <string, object> > { new KeyValuePair <string, object>("X-IPBAN-API-KEY", PublicAPIKey.ToUnsecureString()), new KeyValuePair <string, object>("X-IPBAN-TIMESTAMP", timestampUnix) }; } else { headers = null; } await requestMaker.MakeRequestAsync(new Uri(url), headers : headers); } catch { // don't care, this is not fatal } }
/// <summary> /// Does nothing /// </summary> /// <param name="ipAddress">N/A</param> /// <param name="source">N/A</param> /// <param name="userName">N/A</param> /// <param name="osName">N/A</param> /// <param name="osVersion">N/A</param> /// <param name="assemblyVersion">N/A</param> /// <param name="requestMaker">N/A</param> /// <returns>Completed task</returns> Task IBannedIPAddressHandler.HandleBannedIPAddress(string ipAddress, string source, string userName, string osName, string osVersion, string assemblyVersion, IHttpRequestMaker requestMaker) { // do nothing return(Task.CompletedTask); }
/// <summary> /// Constructor /// </summary> /// <param name="requestMaker">Request maker</param> public LocalMachineExternalIPAddressLookupDefault(IHttpRequestMaker requestMaker) { requestMaker.ThrowIfNull(); this.requestMaker = requestMaker; }
/// <summary> /// Just returns loopback ip /// </summary> /// <param name="requestMaker">N/A</param> /// <param name="url">N/A</param> /// <returns>Loopback ip</returns> public Task <IPAddress> LookupExternalIPAddressAsync(IHttpRequestMaker requestMaker = null, string url = null) { return(Task.FromResult(System.Net.IPAddress.Loopback)); }
/// <inheritdoc /> public Task HandleBannedIPAddress(string ipAddress, string source, string userName, string osName, string osVersion, string assemblyVersion, IHttpRequestMaker requestMaker) { if (requestMaker == null) { return(Task.CompletedTask); } try { if (!System.Net.IPAddress.TryParse(ipAddress, out System.Net.IPAddress ipAddressObj) || ipAddressObj.IsInternal()) { return(Task.CompletedTask); } // submit url to ipban public database so that everyone can benefit from an aggregated list of banned ip addresses string timestamp = IPBanService.UtcNow.ToString("o"); string url = $"/IPSubmitBanned?ip={ipAddress.UrlEncode()}&osname={osName.UrlEncode()}&osversion={osVersion.UrlEncode()}&source={source.UrlEncode()}×tamp={timestamp.UrlEncode()}&userName={userName.UrlEncode()}&version={assemblyVersion.UrlEncode()}"; string hash = Convert.ToBase64String(new SHA256Managed().ComputeHash(Encoding.UTF8.GetBytes(url + IPBanResources.IPBanKey1))); url += "&hash=" + hash.UrlEncode(); url = BaseUrl + url; return(requestMaker.MakeRequestAsync(new Uri(url))); } catch { // don't care, this is not fatal return(Task.CompletedTask); } }
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(); }