How can I get persistent authentication with ssh and dual-factor?

I am trying to make the inevitable transition to dual-factor authentication as painless as possible for admins and developers. One stumbling block is the need to enter the second factor each time the client opens a session. Is there a way to get dual-factor authentication for ssh in which the second factor only has to be entered once per day or some other reasonably long time period?

The idea is to set up jump hosts for ssh that require 2FA. A jump host can then be used to provide access to other servers (ssh -J JumpHost TargetHost) that will, in turn, be restricted to only accepting connections from the jump hosts.

Ideally for my environment, the first login on the jump host would require a public key, password, or Kerberos TGT plus the second factor. Subsequent logins on the same server in the time period specified would only require the first factor.

So far, I've checked out Duo and Okta. Duo has not gotten back to me yet on the persistence and it is not obvious from their documentation it can even be done. Okta can sort of do it, but I discovered a way to hijack credentials from one user to another -- even across client machines -- so it is a less attractive option.


Solution 1:

If the second factor is done through PAM (rather than through a forced post-auth command), then a custom PAM module can be inserted to track successful authentications and skip the 2fa-related PAM module. I'm not sure if such a PAM module already exists though (but it would probably be extremely similar to pam_faillock, with one module that does the checking and another that does the tracking).

(The "extended syntax" in PAM configuration allows a kind of forward goto, e.g. auth [success=1 default=ignore] pam_localuser.so is often used to skip the next 1 module for local users.)

However, that's likely not necessary because SSH already supports persistent authentication, in the form of long-lived multiplexed connections. After the initial authentication, the SSH client can just open as many channels/sessions as it wants – keeping the same connection alive through the entire day.

For example, in OpenSSH configuring ControlPath (and optionally ControlPersist) allows multiplexing to be enabled, and PuTTY has the same under "Connection→SSH→Sharing an SSH connection". The same connection can carry interactive shell sessions, batch commands, TCP tunnels, and SFTP transfers.

This doesn't only avoid the 2nd factor requirement, it even avoids the first factor (due to the connection being already authenticated). Most SSH servers allow this by default unless explicitly disabled – so in most cases this is already possible without the sysadmin's involvement, requiring only client-side configuration to enable it.