Securing a Linux server with two-factor authentication(2FA)

If you are running any Linux server that is accessible over the Internet, then as an administrator of the server, you must be careful about the security of the server. A few things that could be helpful are as follow:

  • Disable password-based authentication for SSH; only allow SSH key-based authentication.
  • Move the SSH default port to some other port in higher ranges. For example, move port 22 to port 60000.
  • Use firewall tools like UFW to block or allow safe IPs or CIDRs.
  • Use a Paraphrase while creating the SSH key; this would act as a 2nd line of defense. For example, if unauthorized persons access your private key, they still have to crack the paraphrase.
  • Enable a 2FA authentication.

    This post shows the steps to set up 2FA/OTP for SSH, and the Sever we would be enforcing 2FA is running Ubuntu. My authentication is already set to SSH keys.

    hostnameIP addressusernamepassword
    My Example Setup for this demo

    WARNING: Before performing the following steps, ensure the following:

    • Backup up /etc/ssh/sshd_config file
    • backup /etc/pam.d/sshd file
    • Keep at least two SSH sessions open on the server at all times; the 2nd session can be beneficial in reverting any incorrect changes. This would ensure configuration can be restored all the time.

    Step 0: Identify the IP Address that does not warrant 2FA

    Add the List of IP address that does not require the 2FA. For example, your home Router IP address. E.g., If I want to exclude 2FA for the source IP, then add it here. Similarly, you can add multiple IP addresses or CIDR. Although this step is optional, in most real-world cases, the server administrator would add a set of CIDRS to disable 2FA for those source IPs.

    vi /etc/security/access-local.conf
    #localhost doesn't need two step verification
    + : ALL :
    #All other hosts need two step verification
    - : ALL : ALL

    Step 1: Update and install the Google Authenticator PAM module on the server

    sudo apt update
    sudo apt install libpam-google-authenticator

    Step 2: Configure PAM to use the google authenticator PAM module.

    vi /etc/pam.d/sshd #file
    # PAM configuration for the Secure Shell service
    # Standard Un*x authentication.
    #@include common-auth                                   #Uncomment for enable default auth, I have NOT
    auth [success=done default=ignore] accessfile=/etc/security/access-local.conf #THIS IS IMP
    auth required                                                   #THIS IS IMP

    Step 3: Enable the SSH challenge response in /etc/ssh/sshd_config

    Ensure that the following parameters are set in /etc/ssh/sshd_config

    vi /etc/ssh/sshd_config #file
    UsePAM yes
    ChallengeResponseAuthentication yes
    PasswordAuthentication no
    AuthenticationMethods publickey,password publickey,keyboard-interactive

    Step 4: Restart the sshd

    sudo service sshd restart

    Step 5: Configure the google authenticator application

    technekey@my-secure-server:~$ google-authenticator
    Do you want authentication tokens to be time-based (y/n) y

    Scan this code in Google Authenticator mobile Application(This code is blurred out)

    A sample QR COODE will be generated

    Enter the One-time password in the prompt below; save this recovery code if needed for recovery purposes. I have replaced all the real values with dummy values.

    Your new secret key is: 12321431241412412DUMMY421QO12334453
    Enter code from app (-1 to skip): 123456
    Code confirmed
    Your emergency scratch codes are:
    Do you want me to update your "/home/technekey/.google_authenticator" file? (y/n) y
    Do you want to disallow multiple uses of the same authentication
    token? This restricts you to one login about every 30s, but it increases
    your chances to notice or even prevent man-in-the-middle attacks (y/n) y
    By default, a new token is generated every 30 seconds by the mobile app.
    In order to compensate for possible time-skew between the client and the server,
    we allow an extra token before and after the current time. This allows for a
    time skew of up to 30 seconds between authentication server and client. If you
    experience problems with poor time synchronization, you can increase the window
    from its default size of 3 permitted codes (one previous code, the current
    code, the next code) to 17 permitted codes (the 8 previous codes, the current
    code, and the 8 next codes). This will permit for a time skew of up to 4 minutes
    between client and server.
    Do you want to do so? (y/n) n
    If the computer that you are logging into isn't hardened against brute-force
    login attempts, you can enable rate-limiting for the authentication module.
    By default, this limits attackers to no more than 3 login attempts every 30s.
    Do you want to enable rate-limiting? (y/n) y

    Step 6: Test the configuration

    In the below prompt, provide the OTP from the Google Authenticator application from the phone. You can also tweak more by uncommenting line#7 of step#1.

    ssh [email protected]
    [email protected]'s password:<ENTER-OTP-FROM-MOBILE>
    Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-56-generic x86_64)
     * Documentation:
     * Management:
     * Support:
      System information as of Wed Jan 11 20:44:08 CST 2023
      System load:  0.00341796875     Processes:               115
      Usage of /:   6.0% of 38.58GB   Users logged in:         1
      Memory usage: 25%               IPv4 address for enp1s0:
      Swap usage:   0%
     * Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s
       just raised the bar for easy, resilient and secure K8s cluster deployment.
    0 updates can be applied immediately.
    *** System restart required ***
    Last login: Wed Jan 11 20:37:11 2023 from
    0 0 votes
    Please, Rate this post
    Notify of
    Inline Feedbacks
    View all comments
    Would love your thoughts, please comment.x
    Scroll to Top