You are not logged in.
I'd like to perform certain actions or run a script when a set number of failed user login attempts are recorded. I'd also like to make use of the actual number (count) of failed login attempts if possible.
I used to achieve this using pam_tally2, but as I discovered from this thread, pam_tally/pam_tally2 are obsolete.
How can this be achieved today? I know that the file /var/run/faillock/$USER contains some logging of failed attempts, but its format is unclear.
Thanks for any info.
Offline
Mod note: Moving to NC
Offline
There's a "faillock" binary to inspect the log.
Offline
V1del thanks for moving the thread.
Thank you for pointing out the faillock binary, seth.
faillock outputs the following:
faillock --user myuser
myuser:
When Type Source Valid
2020-12-08 15:01:16 TTY /dev/pts/12 V
2020-12-08 15:01:19 TTY /dev/pts/12 V
2020-12-08 15:01:21 TTY /dev/pts/12 V
2020-12-08 15:01:46 TTY tty2 VWhere the "V" under the "Valid" column actually signifies a failed login (not very intuitive).
So if I were to count the V's I could get the current number of failed logins.
What would be the most efficient way to know exactly when these failures occur? In other words, what would trigger my custom action/script upon login failure?
Here is a similar question and a hacky solution which points out faillock's shortcomings when compared to pam_tally2: https://unix.stackexchange.com/question … -get-count
Last edited by TheCoon (2020-12-08 17:24:06)
Offline
Monitor the directory /run/faillock or in /etc/pam.d/system-auth change
auth [default=die] pam_faillock.so authfailto something such as
auth [default=fail] pam_faillock.so authfail
auth [default=die] pam_exec.so /path/to/binary optionsEdit:
The pam based approach will not be triggered by logins rejected by
auth required pam_faillock.so preauthonly the failed attempts leading up to faillock being activated.
Last edited by loqs (2020-12-08 18:24:41)
Offline
Thanks for the suggestion, loqs.
I am currently working on a custom solution which makes use of inotifywait for monitoring changes to the log file, which in turn checks the log using faillock in order to get the number of failed attempts.
https://gist.github.com/nyancow/410e1de … 7a163a8f18
#!/usr/bin/env bash
# https://gist.github.com/nyancow/410e1dedc00d7d7dd237137a163a8f18
SCRIPTNAME=`basename "$0"`
REQS=(faillock inotifywait)
for REQ in "${REQS[@]}"
do
if ! command -v ${REQ} &> /dev/null
then
printf "${REQ} binary could not be found, exiting. \n"
exit 1
fi
done
if [ $# -eq 0 ]
then
printf "No arguments supplied. \n"
printf "Specify the username to watch and the maximum number \n"
printf "of failed attempts before triggering an action.\n\n"
printf "\t${SCRIPTNAME} <username> <limit> \n\n"
exit 0
fi
# User to watch
WATCHUSER="${1}"
# Fail limit
FAILLIMIT="${2}"
if [ -n "$FAILLIMIT" ] && [ "$FAILLIMIT" -eq "$FAILLIMIT" ] 2>/dev/null; then
printf "Fail limit set to ${FAILLIMIT} \n"
else
printf "Specified limit is not a number \n"
exit 0
fi
# Runs when the faillock file is modified
triggered() {
# Get faillock binary output
LOGOUTPUT=$(/usr/bin/faillock --user ${WATCHUSER})
# Count the number of "V" occurrences
FAILCOUNT=$(echo ${LOGOUTPUT} | grep -Eo "\bV\b" | wc -l)
# Check if fail limit reached
if [ "$FAILCOUNT" -gt "$FAILLIMIT" ]; then
MSG="Failed login for ${WATCHUSER} more than ${FAILLIMIT} times"
# /usr/bin/tgalert "${MSG}"
logger "${MSG}"
fi
}
# https://superuser.com/a/181543
# Monitor the faillock log file for the specified user
# Call triggered() when the file is modified
/usr/bin/inotifywait --quiet --monitor --event modify /var/run/faillock/${WATCHUSER} |
while read -r filename event; do
triggered
doneI will probably run this script using a systemd service on boot.
If anyone has thoughts or suggestions for improving this approach, I'd love to hear them.
EDIT:
Here's the systemd service file I'm using:
[Unit]
Description=Monitor faillock entries
[Service]
Type=simple
ExecStart=/usr/bin/failmon myuser 2
PIDFile=/run/failmon.pid
[Install]
WantedBy=multi-user.targetLast edited by TheCoon (2020-12-09 13:34:27)
Offline