Example #1
0
        private void AddBannedIPAddress(string ipAddress, string source, string userName,
                                        List <IPAddressLogEvent> bannedIpAddresses, DateTime startBanDate, bool configBlacklisted,
                                        int counter, string extraInfo, object transaction, bool external)
        {
            // never ban whitelisted ip addresses
            if (IsWhitelisted(ipAddress))
            {
                Logger.Info("Ignoring ban request for whitelisted ip address {0}", ipAddress);
                return;
            }

            TimeSpan[] banTimes   = Config.BanTimes;
            TimeSpan   banTime    = banTimes.First();
            DateTime   banEndDate = startBanDate + banTime;

            // if we have an ip in the database, use the ban time to move to the next ban slot in the list of ban times
            // if ban times only has one entry, do not do this
            if (banTimes.Length > 1 &&
                ipDB.TryGetIPAddress(ipAddress, out IPBanDB.IPAddressEntry ipEntry, transaction) &&
                ipEntry.BanStartDate != null && ipEntry.BanEndDate != null)
            {
                // find the next ban time in the array
                banTime = ipEntry.BanEndDate.Value - ipEntry.BanStartDate.Value;
                for (int i = 0; i < banTimes.Length; i++)
                {
                    if (banTime < banTimes[i])
                    {
                        // ban for next timespan
                        banTime    = banTimes[i];
                        banEndDate = startBanDate + banTime;
                        Logger.Info("Moving to next ban duration {0} at index {1} for ip {1}", banTimes[i], i, ipAddress);
                        break;
                    }
                }
            }
            int adjustedCount = (counter <= 0 ? Config.FailedLoginAttemptsBeforeBan : counter);

            bannedIpAddresses?.Add(new IPAddressLogEvent(ipAddress, userName, source, adjustedCount, IPAddressEventType.Blocked));
            if (ipDB.SetBanDates(ipAddress, startBanDate, banEndDate, UtcNow, transaction))
            {
                firewallNeedsBlockedIPAddressesUpdate = true;
            }

            Logger.Warn(startBanDate, "Banning ip address: {0}, user name: {1}, config black listed: {2}, count: {3}, extra info: {4}, duration: {5}",
                        ipAddress, userName, configBlacklisted, counter, extraInfo, banTime);

            // if this is a delegate callback (counter of 0), exit out - we don't want to run handlers or processes for shared banned ip addresses
            if (counter <= 0)
            {
                return;
            }
            else if (BannedIPAddressHandler != null &&
                     System.Net.IPAddress.TryParse(ipAddress, out System.Net.IPAddress ipAddressObj) &&
                     !ipAddressObj.IsInternal())
            {
                try
                {
                    ExecuteTask(BannedIPAddressHandler.HandleBannedIPAddress(ipAddress, source, userName, OSName, OSVersion, AssemblyVersion, RequestMaker));
                }
                catch
                {
                    // eat exception, delicious
                }
            }

            if (IPBanDelegate != null && !external)
            {
                try
                {
                    ExecuteTask(IPBanDelegate.IPAddressBanned(ipAddress, source, userName, MachineGuid, OSName, OSVersion, UtcNow, true));
                }
                catch (Exception ex)
                {
                    Logger.Info("Error calling ipban delegate with banned ip address: " + ex.ToString());
                }
            }
        }
Example #2
0
        private async Task ProcessPendingFailedLogins(IReadOnlyList <IPAddressLogEvent> ipAddresses)
        {
            List <IPAddressLogEvent> bannedIpAddresses = new List <IPAddressLogEvent>();
            object transaction = BeginTransaction();

            try
            {
                foreach (IPAddressLogEvent failedLogin in ipAddresses)
                {
                    try
                    {
                        string ipAddress = failedLogin.IPAddress;
                        string userName  = failedLogin.UserName;
                        string source    = failedLogin.Source;
                        if (IsWhitelisted(ipAddress))
                        {
                            Logger.Warn("Login failure, ignoring whitelisted ip address {0}, {1}, {2}", ipAddress, userName, source);
                        }
                        else
                        {
                            int maxFailedLoginAttempts;
                            if (Config.IsWhitelisted(userName))
                            {
                                maxFailedLoginAttempts = Config.FailedLoginAttemptsBeforeBanUserNameWhitelist;
                            }
                            else
                            {
                                // see if there is an override for max failed login attempts
                                maxFailedLoginAttempts = (failedLogin.FailedLoginThreshold > 0 ? failedLogin.FailedLoginThreshold : Config.FailedLoginAttemptsBeforeBan);
                            }

                            DateTime now = failedLogin.Timestamp;

                            // check for the target user name for additional blacklisting checks
                            bool ipBlacklisted           = Config.IsBlackListed(ipAddress);
                            bool userBlacklisted         = (ipBlacklisted ? false : Config.IsBlackListed(userName));
                            bool userFailsWhitelistRegex = (userBlacklisted ? false : Config.UserNameFailsUserNameWhitelistRegex(userName));
                            bool editDistanceBlacklisted = (ipBlacklisted || userBlacklisted || userFailsWhitelistRegex ? false : !Config.IsUserNameWithinMaximumEditDistanceOfUserNameWhitelist(userName));
                            bool configBlacklisted       = ipBlacklisted || userBlacklisted || userFailsWhitelistRegex || editDistanceBlacklisted;

                            // if the event came in with a count of 0 that means it is an automatic ban
                            int incrementCount = (failedLogin.Count < 1 ? maxFailedLoginAttempts : failedLogin.Count);
                            int newCount       = ipDB.IncrementFailedLoginCount(ipAddress, userName, source, UtcNow, incrementCount, transaction);

                            Logger.Warn(now, "Login failure: {0}, {1}, {2}, {3}", ipAddress, userName, source, newCount);

                            // if the ip address is black listed or the ip address has reached the maximum failed login attempts before ban, ban the ip address
                            if (configBlacklisted || newCount >= maxFailedLoginAttempts)
                            {
                                Logger.Info("IP blacklisted: {0}, user name blacklisted: {1}, fails user name white list regex: {2}, user name edit distance blacklisted: {3}",
                                            ipBlacklisted, userBlacklisted, userFailsWhitelistRegex, editDistanceBlacklisted);

                                if (ipDB.TryGetIPAddressState(ipAddress, out IPBanDB.IPAddressState? state, transaction) &&
                                    (state.Value == IPBanDB.IPAddressState.Active || state.Value == IPBanDB.IPAddressState.AddPending))
                                {
                                    Logger.Warn(now, "IP {0}, {1}, {2} ban pending.", ipAddress, userName, source);
                                }
                                else
                                {
                                    Logger.Debug("Failed login count {0} >= ban count {1}{2}", newCount, maxFailedLoginAttempts, (configBlacklisted ? " config blacklisted" : string.Empty));

                                    // if delegate and non-zero count, forward on - count of 0 means it was from external source, like a delegate
                                    if (IPBanDelegate != null && !failedLogin.External)
                                    {
                                        await IPBanDelegate.LoginAttemptFailed(ipAddress, source, userName, MachineGuid, OSName, OSVersion, UtcNow);
                                    }
                                    AddBannedIPAddress(ipAddress, source, userName, bannedIpAddresses, now,
                                                       configBlacklisted, newCount, string.Empty, transaction, failedLogin.External);
                                }
                            }
                            else
                            {
                                Logger.Debug("Failed login count {0} <= ban count {1}", newCount, maxFailedLoginAttempts);
                                if (OSUtility.UserIsActive(userName))
                                {
                                    Logger.Warn("Login failed for known active user {0}", userName);
                                }

                                // if delegate and non-zero count, forward on - count of 0 means it was from external source, like a delegate
                                if (IPBanDelegate != null && !failedLogin.External)
                                {
                                    await IPBanDelegate.LoginAttemptFailed(ipAddress, source, userName, MachineGuid, OSName, OSVersion, UtcNow);
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Error(ex);
                    }
                }
                CommitTransaction(transaction);
                ExecuteExternalProcessForBannedIPAddresses(bannedIpAddresses);
            }
            catch (Exception ex)
            {
                RollbackTransaction(transaction);
                Logger.Error(ex);
            }
        }