Set a Per-Application PAM Failure Delay with pam_faildelay
pam_faildelay adds a controlled pause after a failed login for one PAM service. This guide covers configuring, verifying and undoing it safely, using the installed Linux-PAM package version 1.5.3-5ubuntu5.7 and its pam_faildelay(8) manpage.
The route
Jump straight to the step you need, or tick off Done means at the end.
- 1. Identify the PAM service before editing
- 2. Back up the stack and inspect its authentication section
- 3. Add the module with an explicit delay
- 4. Understand the fallback to /etc/login.defs
- 5. Test a failed login without losing access
- 6. Recover by restoring the previous stack
- 7. Know what the module does not do
Allow about fifteen minutes, plus a maintenance window if the service is remote login. You need root access to edit a PAM configuration, and a second session or console to fall back on. The module is already installed as /lib/x86_64-linux-gnu/security/pam_faildelay.so on this machine.
1. Identify the PAM service before editing
PAM configuration is per service: a login path might be named sshd, login, or something an application supplies itself. Do not put this line into a random file or assume every authentication path shares one stack.
List the service files first, a read-only command that needs no elevated privileges:
$ ls /etc/pam.d/
Pick the file for the application whose failed logins should be delayed. In the examples below, SERVICE_FILE stands in for a real path such as /etc/pam.d/sshd. Check the application's documentation if its PAM service name is not obvious.
Checkpoint
Write down the exact service file, and keep an already authenticated root shell or local console available. A malformed PAM stack can shut out new logins.
2. Back up the stack and inspect its authentication section
Back up the file before making a security-sensitive change. This needs elevated privileges:
# SERVICE_FILE=/etc/pam.d/SERVICE_NAME
# cp --preserve=mode,ownership,timestamps "$SERVICE_FILE" "$SERVICE_FILE.bak.$(date +%Y%m%d-%H%M%S)"
# sed -n '/^[[:space:]]*auth[[:space:]]/p' "$SERVICE_FILE"
The backup name carries a timestamp, so it will not silently clobber an earlier one. Do not hand-edit a generated file if the application or distribution says another configuration tool owns it.
3. Add the module with an explicit delay
Add one auth line to the chosen file. The delay value is in microseconds, so ten seconds is 10000000. The module only provides the auth interface, and a straightforward entry looks like this:
auth optional pam_faildelay.so delay=10000000
That is a module name to add to the stack, not a shell command. The optional control flag matches the installed manpage's own example: the module adjusts PAM's failure delay and returns PAM_IGNORE once that succeeds, so it is not the module deciding whether the password is accepted. The rest of the stack still controls authentication.
Insert the line in the auth section, normally before the modules that can reject credentials. The delay is a PAM application setting, not a pause written into the file itself. Ten seconds is deliberately noticeable for testing; pick a value that suits the service and its users.
Edit with root privileges, or append carefully after checking the file and line:
# editor "$SERVICE_FILE"
# grep -nF 'pam_faildelay.so' "$SERVICE_FILE"
Expect one numbered line containing the module entry. Avoid duplicate entries while you troubleshoot: multiple modules can each contribute to PAM's failure-delay handling.
4. Understand the fallback to /etc/login.defs
Omit delay= and the module reads FAIL_DELAY from /etc/login.defs instead, expressed in seconds rather than the module argument's microseconds:
auth optional pam_faildelay.so
Do not assume a missing setting means any particular delay. On this machine FAIL_DELAY is commented out, so an omitted argument gives you nothing useful. Check it before relying on the fallback:
$ grep -nE '^[[:space:]]*FAIL_DELAY([[:space:]]|$)' /etc/login.defs || echo 'FAIL_DELAY is not set'
Prefer an explicit delay= in the service stack when the policy is meant for one application. Only touch /etc/login.defs when you actually want its value as the fallback for every service using this module.
5. Test a failed login without losing access
Keep the existing session open and test the affected service from a separate one. Use a test account if the service has one. Deliberately try one wrong password, then a correct one, and confirm the first attempt takes roughly the configured delay. Do not repeatedly guess passwords against a production account.
For an SSH service, an ordinary client command is:
$ time ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no TEST_USER@HOSTNAME
Client output and elapsed time vary with the service and network, since PAM applies the delay when the stack records a failure, and network latency and other modules affect what you see. A successful login does not prove every failed path uses the file you edited, so test the exact application and method you changed.
Checkpoint
Confirm the test session still works, and that the delay only appears on a failed authentication. If new logins fail entirely, stop testing and restore the backup from the preserved session.
6. Recover by restoring the previous stack
If the service rejects every login, remove the new line or restore the timestamped backup. This changes authentication behaviour immediately and needs elevated privileges:
# cp --preserve=mode,ownership,timestamps /etc/pam.d/SERVICE_NAME.bak.YYYYMMDD-HHMMSS /etc/pam.d/SERVICE_NAME
# grep -nF 'pam_faildelay.so' /etc/pam.d/SERVICE_NAME || echo 'pam_faildelay entry removed'
Recovery
Swap the placeholder for the exact backup you made in step 2, and do not delete it until a fresh login has succeeded. If a configuration management system owns the file, make the same fix there too, or the bad line will come back on the next run.
7. Know what the module does not do
pam_faildelay does not count failures, lock accounts, block IP addresses, or replace pam_faillock. It only asks PAM to delay the result of a failed authentication for the application stack, and it gives you no general shell command for changing a user's login policy.
The module also accepts debug, which sends debugging messages to syslog, alongside delay=N. An invalid delay is a configuration error: the installed manpage documents PAM_SYSTEM_ERR for that case. Warning: do not enable debugging on a busy authentication service without checking your logging policy first.
Done means
- Right service picked: you selected the correct PAM service rather than changing every login path by accident.
- Backup kept: a timestamped backup was made before editing and kept through testing.
- Entry is correct: it uses
auth, the installed module name, and microseconds for an explicit delay. - Fallback checked: you looked at the separate, seconds-based
FAIL_DELAYbefore relying on it. - Test succeeded: a failed test took roughly the intended extra time while a valid login still worked.
- Rollback confirmed: you can restore the previous stack from the backup without guessing its contents.