Exemple #1
0
        /// <summary>
        /// Stop the service, dispose of all resources
        /// </summary>
        public void Dispose()
        {
            if (!IsRunning)
            {
                return;
            }

            try
            {
                cycleLock.WaitAsync().Sync();
                IsRunning = false;
                GetUrl(UrlType.Stop).Sync();
                cycleTimer?.Dispose();
                IPBanDelegate?.Dispose();
                IPBanDelegate = null;
                lock (updaters)
                {
                    foreach (IUpdater updater in updaters.ToArray())
                    {
                        updater.Dispose();
                    }
                    updaters.Clear();
                }
                ipDB?.Dispose();
                Logger.Warn("Stopped IPBan service");
            }
            finally
            {
                stopEvent.Release();
            }
        }
Exemple #2
0
        /// <summary>
        /// Stop the service, dispose of all resources
        /// </summary>
        public void Dispose()
        {
            if (!IsRunning)
            {
                return;
            }

            IsRunning = false;
            try
            {
                serviceCancelTokenSource.Cancel();
                GetUrl(UrlType.Stop).Sync();
                cycleTimer?.Dispose();
                IPBanDelegate?.Dispose();
                IPBanDelegate = null;
                lock (updaters)
                {
                    foreach (IUpdater updater in updaters.ToArray())
                    {
                        updater.Dispose();
                    }
                    updaters.Clear();
                }
                foreach (LogFileScanner file in logFilesToParse)
                {
                    file.Dispose();
                }
                ipDB?.Dispose();
                Logger.Warn("Stopped IPBan service");
            }
            finally
            {
                stopEvent.Release();
            }
        }
        private async Task UpdateExpiredIPAddressStates()
        {
            HashSet <string> unbanIPAddressesToNotifyDelegate = (IPBanDelegate is null ? null : new HashSet <string>());
            DateTime         now             = UtcNow;
            DateTime         failLoginCutOff = (now - Config.ExpireTime);
            DateTime         banCutOff       = now;
            object           transaction     = DB.BeginTransaction();

            try
            {
                HandleWhitelistChanged(transaction, unbanIPAddressesToNotifyDelegate);
                HandleExpiredLoginsAndBans(failLoginCutOff, banCutOff, transaction, unbanIPAddressesToNotifyDelegate);

                // notify delegate of all unbanned ip addresses
                if (IPBanDelegate != null)
                {
                    foreach (string ip in unbanIPAddressesToNotifyDelegate)
                    {
                        await IPBanDelegate.IPAddressBanned(ip, null, null, MachineGuid, OSName, OSVersion, UtcNow, false);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                DB.RollbackTransaction(transaction);
            }
            finally
            {
                DB.CommitTransaction(transaction);
            }
        }
        private Task ProcessPendingSuccessfulLogins(IEnumerable <IPAddressLogEvent> ipAddresses)
        {
            foreach (IPAddressLogEvent info in ipAddresses)
            {
                Logger.Warn("Login succeeded, address: {0}, user name: {1}, source: {2}", info.IPAddress, info.UserName, info.Source);
                if (Config.ClearFailedLoginsOnSuccessfulLogin)
                {
                    DB.DeleteIPAddress(info.IPAddress);
                    firewallNeedsBlockedIPAddressesUpdate = true;
                }
            }
            if (IPBanDelegate != null)
            {
                return(Task.Run(() =>
                {
                    try
                    {
                        foreach (IPAddressLogEvent info in ipAddresses)
                        {
                            // pass the success login on
                            IPBanDelegate.LoginAttemptSucceeded(info.IPAddress, info.Source, info.UserName, MachineGuid, OSName, OSVersion, info.Timestamp);
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Error(ex);
                    }
                }));
            }

            return(Task.CompletedTask);
        }
Exemple #5
0
        /// <summary>
        /// Stop the service, dispose of all resources
        /// </summary>
        public void Dispose()
        {
            if (!IsRunning)
            {
                return;
            }

            IsRunning = false;
            try
            {
                firewallQueueCancel.Cancel();
                GetUrl(UrlType.Stop).Sync();
                cycleTimer?.Dispose();
                IPBanDelegate?.Dispose();
                IPBanDelegate = null;
                lock (updaters)
                {
                    foreach (IUpdater updater in updaters.ToArray())
                    {
                        updater.Dispose();
                    }
                    updaters.Clear();
                }
                foreach (IPBanLogFileScanner file in logFilesToParse)
                {
                    file.Dispose();
                }
                ipDB?.Dispose();
                IPBanLog.Warn("Stopped IPBan service");
            }
            catch
            {
            }
            stopEvent.Set();
        }
Exemple #6
0
        /// <summary>
        /// Initialize and start the service
        /// </summary>
        /// <param name="cancelToken">Cancel token</param>
        public async Task RunAsync(CancellationToken cancelToken)
        {
            CancelToken = cancelToken;

            if (!IsRunning)
            {
                try
                {
                    IsRunning = true;

                    // set version
                    AssemblyVersion = IPBanService.IPBanAssembly.GetName().Version.ToString();

                    // create db
                    ipDB = new IPBanDB(DatabasePath ?? "ipban.sqlite");

                    // add some services
                    AddUpdater(new IPBanUnblockIPAddressesUpdater(this, Path.Combine(AppContext.BaseDirectory, "unban.txt")));
                    AddUpdater(new IPBanBlockIPAddressesUpdater(this, Path.Combine(AppContext.BaseDirectory, "ban.txt")));
                    AddUpdater(DnsList);

                    // start delegate if we have one
                    IPBanDelegate?.Start(this);

                    Logger.Warn("IPBan service started and initialized. Operating System: {0}",
                                OSUtility.Instance.OSString());
                    Logger.WriteLogLevels();

                    // setup cycle timer if needed
                    if (!ManualCycle)
                    {
                        // create a new timer that goes off in 1 second, this will change as the config is
                        // loaded and the cycle time becomes whatever is in the config
                        cycleTimer = new Timer(async(_state) =>
                        {
                            try
                            {
                                await CycleTimerElapsed();
                            }
                            catch
                            {
                            }
                        }, null, 1000, Timeout.Infinite);
                    }

                    if (!ManualCycle)
                    {
                        await Task.Delay(Timeout.Infinite, cancelToken);
                    }
                }
                catch (Exception ex)
                {
                    if (!(ex is OperationCanceledException))
                    {
                        Logger.Error($"Error in {nameof(IPBanService)}.{nameof(IPBanService.RunAsync)}", ex);
                    }
                }
            }
        }
Exemple #7
0
        /// <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();
                }
                Logger.Warn("IPBan {0} service started and initialized. Operating System: {1}", OSUtility.Name, OSUtility.OSString());
                Logger.WriteLogLevels();
            }
            catch (Exception ex)
            {
                Logger.Error("Critical error in IPBanService.Start", ex);
            }
        }
Exemple #8
0
 /// <summary>
 /// Check if an ip is whitelisted
 /// </summary>
 /// <param name="ipAddress">IP address</param>
 /// <returns>True if whitelisted, false otherwise</returns>
 public bool IsWhitelisted(string ipAddress)
 {
     return(Config.IsWhitelisted(ipAddress) || (IPBanDelegate != null && IPBanDelegate.IsIPAddressWhitelisted(ipAddress)));
 }
Exemple #9
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
                            {
                                maxFailedLoginAttempts = 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 == IPBanDB.IPAddressState.Active || state == 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.Count > 0)
                                    {
                                        await IPBanDelegate.LoginAttemptFailed(ipAddress, source, userName, MachineGuid, OSName, OSVersion, UtcNow);
                                    }
                                    AddBannedIPAddress(ipAddress, source, userName, bannedIpAddresses, now, configBlacklisted, newCount, string.Empty, transaction);
                                }
                            }
                            else
                            {
                                Logger.Debug("Failed login count {0} <= ban count {1}", newCount, maxFailedLoginAttempts);
                                if (OSUtility.Instance.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.Count > 0)
                                {
                                    await IPBanDelegate.LoginAttemptFailed(ipAddress, source, userName, MachineGuid, OSName, OSVersion, UtcNow);
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Error(ex);
                    }
                }
Exemple #10
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());
                }
            }
        }