OpenSSH Multi Factor Authentication

The following tutorial will set up two-factor authentication for OpenSSH on my OpenWrt x86 router (v19.07.06). It comes from a post in the OpenWrt forums

In this tutorial the router IP is the default 192.168.1.1.

Configure OpenWrt's built-in Dropbear SSH to work on LAN only and away from port 22 (e.g., 20022). This can be done in Luci at http://192.168.1.1/cgi-bin/luci/admin/system/admin/dropbear. If anything goes wrong with OpenSSH, you still should be able to log in from your local network using Dropbear: Luci Dropbear

Log into the router using Dropbear and install the openssh-server-pam and google-authenticator-libpam packages:

ssh -p 20022 root@192.168.1.1
opkg update
opkg install google-authenticator-libpam openssh-server-pam

Set up OpenSSH public/private key authentication. This is no different from a typical non-MFA scenario, I've just followed this excellent guide.

Restart the OpenSSH service (service sshd restart from the stil-open Dropbear session of step 2) and test that you can connect to OpenSSH as root on port 22, from some other host:

ssh root@192.168.1.1

Run google-authenticator (in the open Dropbear session) and enroll in MFA. Follow this guide precisely, starting from “Run the initialization app” and stopping at “Step 2 — Configuring OpenSSH”.
You can use Google Authenticator, Microsoft Authenticator or any other MFA app that implements the standard Time-based One-time Password Algorithm (TOTP - RFC 6238).

Edit /etc/ssh/sshd_config (with nano /etc/ssh/sshd_config) to make these scattered changes:

PermitRootLogin yes
PubkeyAuthentication yes
ChallengeResponseAuthentication yes
UsePAM yes
AuthenticationMethods publickey,keyboard-interactive

Here is a working version of /etc/ssh/sshd_config:

    #       $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $

    # This is the sshd server system-wide configuration file.  See
    # sshd_config(5) for more information.

    # This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin

    # The strategy used for options in the default sshd_config shipped with
    # OpenSSH is to specify options with their default value where
    # possible, but leave them commented.  Uncommented options override the
    # default value.

    Port 22
    #AddressFamily any
    #ListenAddress 0.0.0.0
    #ListenAddress ::

    HostKey /etc/ssh/ssh_host_rsa_key
    HostKey /etc/ssh/ssh_host_ecdsa_key
    HostKey /etc/ssh/ssh_host_ed25519_key

    # Ciphers and keying
    #RekeyLimit default none

    # Logging
    #SyslogFacility AUTH
    #LogLevel INFO

    # Authentication:

    #LoginGraceTime 2m
    PermitRootLogin yes
    #StrictModes yes
    #MaxAuthTries 6
    #MaxSessions 10

    PubkeyAuthentication yes

    # The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
    # but this is overridden so installations will only check .ssh/authorized_keys
    AuthorizedKeysFile      .ssh/authorized_keys

    #AuthorizedPrincipalsFile none

    #AuthorizedKeysCommand none
    #AuthorizedKeysCommandUser nobody

    # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
    #HostbasedAuthentication no
    # Change to yes if you don't trust ~/.ssh/known_hosts for
    # HostbasedAuthentication
    #IgnoreUserKnownHosts no
    # Don't read the user's ~/.rhosts and ~/.shosts files
    #IgnoreRhosts yes

    # To disable tunneled clear text passwords, change to no here!
    #PasswordAuthentication yes
    #PermitEmptyPasswords no

    # Change to no to disable s/key passwords
    ChallengeResponseAuthentication yes

    # Kerberos options
    #KerberosAuthentication no
    #KerberosOrLocalPasswd yes
    #KerberosTicketCleanup yes
    #KerberosGetAFSToken no

    # GSSAPI options
    #GSSAPIAuthentication no
    #GSSAPICleanupCredentials yes

    # Set this to 'yes' to enable PAM authentication, account processing,
    # and session processing. If this is enabled, PAM authentication will
    # be allowed through the ChallengeResponseAuthentication and
    # PasswordAuthentication.  Depending on your PAM configuration,
    # PAM authentication via ChallengeResponseAuthentication may bypass
    # the setting of "PermitRootLogin without-password".
    # If you just want the PAM account and session checks to run without
    # PAM authentication, then enable this but set PasswordAuthentication
    # and ChallengeResponseAuthentication to 'no'.
    UsePAM yes

    AuthenticationMethods publickey,keyboard-interactive

    #AllowAgentForwarding yes
    #AllowTcpForwarding yes
    #GatewayPorts no
    #X11Forwarding no
    #X11DisplayOffset 10
    #X11UseLocalhost yes
    #PermitTTY yes
    #PrintMotd yes
    #PrintLastLog yes
    #TCPKeepAlive yes
    #PermitUserEnvironment no
    #Compression delayed
    #ClientAliveInterval 0
    #ClientAliveCountMax 3
    #UseDNS no
    #PidFile /var/run/sshd.pid
    #MaxStartups 10:30:100
    #PermitTunnel no
    #ChrootDirectory none
    #VersionAddendum none

    # no default banner path
    #Banner none

    # override default of no subsystems
    Subsystem       sftp    /usr/lib/sftp-server

    # Example of overriding settings on a per-user basis
    #Match User anoncvs
    #       X11Forwarding no
    #       AllowTcpForwarding no
    #       PermitTTY no
    #       ForceCommand cvs server

Edit /etc/pam.d/sshd (with nano /etc/pam.d/sshd) to make these changes:
#auth include common-auth (must be commented out)
auth required /usr/lib/security/pam_google_authenticator.so (append at the very end of the file)

NOTE: The above two lines are very important and a difference from all the guides I've linked above. They were suggested using “auth required pam_google_authenticator.so”. However, at least in OpenWrt 19.07, pam.d tries to load this plugin from /lib/security and that fails, because the current google-authenticator-libpam package installs pam_google_authenticator.so into /usr/lib/security.

Here is a working version of /etc/pam.d/sshd:

    # PAM configuration for the Secure Shell service

    # Read environment variables from /etc/environment and
    # /etc/security/pam_env.conf.
    auth       required     pam_env.so

    # Skip Google Authenticator if logging in from the local network.
    # auth [success=1 default=ignore] pam_access.so accessfile=/etc/security/access-sshd-local.conf
    # Google Authenticator 2-step verification.
    #auth       requisite    pam_google_authenticator.so

    # Standard Un*x authentication.
    #auth       include      common-auth

    # Disallow non-root logins when /etc/nologin exists.
    account    required     pam_nologin.so

    # Uncomment and edit /etc/security/access.conf if you need to set complex
    # access limits that are hard to express in sshd_config.
    # account    required     pam_access.so

    # Standard Un*x authorization.
    account    include      common-account

    # Standard Un*x session setup and teardown.
    session    include      common-session

    # Print the message of the day upon successful login.
    session    optional     pam_motd.so

    # Print the status of the user's mailbox upon successful login.
    session    optional     pam_mail.so standard noenv

    # Set up user limits from /etc/security/limits.conf.
    session    required     pam_limits.so

    # Set up SELinux capabilities (need modified pam)
    # session    required     pam_selinux.so multiple

    # Standard Un*x password updating.
    password   include      common-password

    auth       required     /usr/lib/security/pam_google_authenticator.so

Restart sshd (service sshd restart) and try to connect to it from another machine. You should be prompted for a one-time MFA password.

Configure your Firewall trafic rules (http://192.168.1.1/cgi-bin/luci/admin/network/firewall/rules) if you want to be able to connect to OpenSSH from the Internet.

Congrats, you've hardened your OpenWrt OpenSSH root access with two-factor authentication.

NOTE: The OTP codes are time-based. My x86 router has an RTC clock, so the MFA should work even if the router is offline. OpenWrt automatically syncs time using NTP, so as long as the router is online, the MFA still should work. Otherwise, if the router is offline and there's no RTC, you should still have an option to connect from the LAN using Dropbear on port 20022.

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
  • Last modified: 2021/02/09 18:21
  • by bobafetthotmail