Aldaviva / Fail2Ban4Win

🧱 Ban subnets using Windows Firewall rules after they make enough incorrect login attempts, as indicated by Windows Event Log records.
Apache License 2.0
40 stars 6 forks source link

Crash after creating firewall rule due to ArgumentOutOfRangeException in Task.Delay #10

Closed Aldaviva closed 1 year ago

Aldaviva commented 1 year ago

The crash is happening on line 127 of BanManager.cs:

Task.Delay(unbanDuration, cancellationTokenSource.Token)

Task.Delay(TimeSpan, CancellationToken) can crash with this exception if the unbanDuration was negative except -1 (unlikely), or if it was too long (max int32 on .NET Framework 4.8, which is ~ 24.86 days). Like most parts of .NET, this was improved in .NET 6, but only to about 50 days.

I can imagine users wanting bans of longer than 25 days, especially for repeated offenses. I originally tried other scheduling libraries (FluentScheduler, Chroniton, and Hangfire) which were more robust and could probably handle longer durations than Task.Delay, but they were impossible to test, so I went with Task.Delay instead. To continue with the current dependencies, maybe I could chain Task.Delay?

Error log with stack trace

Anwendung: Fail2Ban4Win.exe
Frameworkversion: v4.0.30319
Beschreibung: Der Prozess wurde aufgrund einer unbehandelten Ausnahme beendet.
Ausnahmeinformationen: System.ArgumentOutOfRangeException
   bei System.Threading.Tasks.Task.Delay(System.TimeSpan, System.Threading.CancellationToken)
   bei Fail2Ban4Win.Services.BanManagerImpl.ban(System.Net.IPNetwork, Fail2Ban4Win.Data.SubnetFailureHistory)
   bei Fail2Ban4Win.Services.BanManagerImpl.onFailure(System.Object, System.Net.IPAddress)
   bei Fail2Ban4Win.Services.EventLogListenerImpl.onEventRecordWritten(Fail2Ban4Win.Facades.EventLogRecordFacade, Fail2Ban4Win.Config.EventLogSelector)
   bei Fail2Ban4Win.Services.EventLogListenerImpl+<>c__DisplayClass6_1.<.ctor>b__1(System.Object, Fail2Ban4Win.Facades.EventRecordWrittenEventArgsFacade)
   bei Fail2Ban4Win.Facades.EventLogWatcherFacadeImpl.WatcherOnEventRecordWritten(System.Object, System.Diagnostics.Eventing.Reader.EventRecordWrittenEventArgs)
   bei System.Diagnostics.Eventing.Reader.EventLogWatcher.IssueCallback(System.Diagnostics.Eventing.Reader.EventRecordWrittenEventArgs)
   bei System.Diagnostics.Eventing.Reader.EventLogWatcher.HandleEventsRequestCompletion()
   bei System.Diagnostics.Eventing.Reader.EventLogWatcher.RequestEvents()
   bei System.Diagnostics.Eventing.Reader.EventLogWatcher.SubscribedEventsAvailableCallback(System.Object, Boolean)
   bei System.Threading._ThreadPoolWaitOrTimerCallback.WaitOrTimerCallback_Context(System.Object, Boolean)
   bei System.Threading._ThreadPoolWaitOrTimerCallback.WaitOrTimerCallback_Context_f(System.Object)
   bei System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   bei System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   bei System.Threading._ThreadPoolWaitOrTimerCallback.PerformWaitOrTimerCallback(System.Object, Boolean)
Aldaviva commented 1 year ago

When the ban duration exceeds 25 days, create multiple smaller chained Task.Delay continuations to avoid crashing.