The quick and easy way would be to use the table command, adding an entry for the source IP once the client fails to log in. The drawback to this method is that if multiple clients come from the same IP this will mess with the lot of them. So, to begin with, add two iRule events to your Policy. You will find them under the General section in the Policy Editor.
The first should be between "Start" and "Login", in the ID field type something appropriate like "check_logon" (You'll get the context of this soon).
The second one should be between "AD Auth" and "Deny" on the Fallback branch. In my example I used "failed_logon" as the ID for this.
Then you create the following iRule and associate that with the Virtual Server:
when ACCESS_POLICY_AGENT_EVENT {
if { [ACCESS::policy agent_id] eq "failed_logon" }{
table set [IP::client_addr] 100 300
}
elseif { [ACCESS::policy agent_id] eq "check_logon" }{
if { !([table lookup -notouch [IP::client_addr]] eq "")}{
discard
}
}
}
The "agent_id" in above iRule corresponds to the ID:s in the Policy. This means that if the client fails to log in, the iRule creates an entry for that IP address in the session table with a timeout of 300 seconds. The value (100) in the table set command is just so that the value isn't empty.
Then when the client tries again, the iRule checks if there is an entry and if such is the case the iRule drops the traffic until the entry times out from the table after 300 seconds. There is of course the possibility to provide the users with a more helpful response if a discard is to harsh, but then again if you suspect that someone is brute-forcing your application there is no such thing as being too harsh is there.