Secure SSH to your instances with Multi-factor Authentication

A key component of the AWS shared security model is the capability to secure remote access to your Amazon EC2 instances. In the case of Linux servers, remote access usually means establishing a connection to the server by using the SSH protocol. Authentication typically happens either by providing a user name and password or by providing a private key that is checked against a public key on the server. By default, most Amazon EC2 instances use the latter approach for user authentication: when you first launch an EC2 instance, you are asked to optionally assign it a key pair. AWS uses the user name along with the PEM file that is associated with the key pair to authenticate with the server and open an SSH session.

When you create an EC2 instance you are prompted to create or select a previously-created key pair for the instance so that you can SSH into the box. That key pair is downloaded and stays on your local machine. The risk here is if your local machine is compromised. Then, any user who has this key pair and the username now has full access to your instances. In order to make access to the instances more secure to help prevent a breach, you should put additional controls. One of the best-recommended practices, when it comes to AWS console access, is to have multi-factor authentication (MFA) enabled for the root account and all user accounts.

Two-factor authentication, or multi-factor authentication (MFA), requires a user to provide multiple proofs of identity to get access to a resource. For example, you can configure access to the AWS Management Console to require users to enter a user name and password in addition to a rotating code from a hardware or software MFA device. This approach is also increasingly used to add an extra layer of security for access to servers and workstations, where a private key or a user name/password must be provided in addition to an authentication code from an MFA device before a session is opened on the operating system.

We recommend limiting the access to your instances to a bastion host, so that people can’t violate the security policy by logging directly into the instances. This can be done by creating an inbound rule of type SSH in the security group of those instances, with the source being either the IP or the security group of the bastion host. Once you have done that, you can focus on tightening the security on your bastion host and only putting your controls there. One other benefit is that you don’t need to have MFA enabled on each instance. You can enable MFA only on the bastion host, and if you want you can have another prompt for another one-time password (OTP) when you run SSH command to log into another instance from the bastion host.

Recommended Architecture


Google Authenticator implements the TOTP algorithm from RFC 6238. When you install the Google Authenticator application on your Amazon EC2 instance, AWS generates a secret key. This secret key is then shared with a second device of your choice, such as an application running on your mobile phone. The exchange of the secret key usually happens when you use the mobile application to scan a QR code generated by Google Authenticator.

Once the secret key is stored in the mobile application, it combines it with the current timestamp by using a cryptographic hash function to generate one-time passwords (OTPs). An OTP is the second authentication factor that you will be prompted to input after successfully authenticating by using a user name and password or PEM file. The OTP is difficult to compromise because it auto-rotates as time passes, usually every 30 seconds, and is generated by using a device that you usually keep with you at all times (such as your phone).

Two-factor authentication for Amazon Linux with Google Authentication and AWS  MFA

Linux uses PAM (Pluggable Authentication Module) to integrate the Google Authenticator MFA. So make sure that PAM and PAM-Devel packages are installed on your system. If not, please install them.

SSH into your EC2 instance the way you normally would and then switch into your root account or use sudo and run:

yum install pam.x86_64
yum install pam-devel.x86_64

Add the EPEL (Extra Packages for Enterprise Linux) repo.

sudo yum install

Install Google Authenticator:

# sudo yum install google-authenticator -y

Once the package is installed, run the initialization app to generate a key for the user you are logged in as (e.g. ec2-user) to add second-factor authentication to that user account.

Run the initialization app:

You will be asked if the authentication tokens used should be time-based. In this example, we will use time-based tokens.

[ec2-user@ip-172-31-87-234 ~]$ google-authenticator
Do you want authentication tokens to be time-based (y/n) y

This will generate a URL which will have a QR code that you should scan using your Google Authenticator app, or manually enter the secret key in your app to register your device. Add your account name in the app, and make sure that the time-based option is enabled. Save the secret key, verification code, and scratch codes generated on the instance in a secure place for use if you lose access to the app on the registered device. Each scratch code can be used only once.|0&cht=qr&chl=otpauth://totp/ec2-user@ip-172-31-87-234.ec2.internal%3Fsecret%3DTRDOPTQ7MGODJYIBFBCT6HVHUY%26issuer%3Dip-172-31-87-234.ec2.internal


Now download Google authenticator application on your Mobile phone and scan the QR code in URL link and register the token

Next, you will be asked if the google_authenticator file should be updated for user ‘ec2-user.’ Typing ‘y’ will save the secret key, scratch codes, and the other configuration options you select later on in the file. You will run the initialization app and go through the same procedure for each user account to enable MFA on each account.

Do you want me to update your "/home/ec2-user/.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

Configure SSH to use the Google Pluggable Authentication Module

Run the following command to make changes to the PAM configuration.

sudo vi /etc/pam.d/sshd

Add the following to the bottom of the file to use Google Authenticator. If there are service accounts or users who should be able to log in without MFA, add nullok at the end of the following statement. This will mean that users who don’t run Google Authenticator initialization won’t be asked for a second authentication.

auth required
auth required
auth required nullok

Comment out the password requirement. We just want to use the key pair and the verification code generated on the Google Authenticator app.

#auth substack password-auth

Save the file. Next, we need to change the SSH configuration to make it prompt for a second authentication.

sudo vi /etc/ssh/sshd_config

Comment out the line which says ChallengeResponseAuthentication ‘no’ and uncomment the line which says ‘yes’.

ChallengeResponseAuthentication yes 
#ChallengeResponseAuthentication no

Lastly, we need to let SSH know that it should ask for SSH key and a verification code to let us in. At the bottom of the file add:

AuthenticationMethods publickey,keyboard-interactive

Save the file. Restart the SSH to let the changes take effect.

sudo service sshd restart

To test if it’s working, open a new terminal window and SSH into the instance and you will be asked for a verification code.


Type the code that’s generated on your Google Authenticator app.

There are a few ways you can make multi-factor authentication possible for your users.

Log into the new user accounts after you create them, run the initialization app, and then share the generated keys and scratch codes specific to that user. This way you won’t have to share the same secret key with others. When the user leaves, all you have to do is delete that user account.

The most secure approach would be to force users to run the initialization app on their first log in and save the key and the scratch codes generated. This could be done by running a script on logins.

Automating copying SSH key to new user accounts and forcing users to enable MFA on the first login

When we create new users, the first thing we do is copy the authorized_key file to the new user account and change its permissions appropriately so that the user can use the same key pair and successfully SSH into the instance. The best practice is to create a separate key pair for each user.

Open the authorized_keys file cat ~/.ssh/authorized_keys and copy the public key. We will use this later to create a similar file in a new user account. The public key will look like:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQClKsfkNkuSevGj3eYhCe53pcjqP3maAhDFcvBS7O6Vhz2ItxCih+PnDS Uaw+WNQn/mZphTk/a/gU8jEzoOWbkM4yxyb/wB96xbiFveSFJuOp/d6RJhJOI0iBXrlsLnBItntckiJ7FbtxJM XLvvwJryDUilBMTjYtwB+QhYXUMOzce5Pjz5/i8SeJtjnV3iAoG/cQk+0FzZqaeJAAHco+CY/5WrUBkrHmFJr6 HcXkvJdWPkYQS3xqC0+FmUZofz221CBt5IMucxXPkX4rWi+z7wB3RbBQoQzd8v7yeb7OzlPnWOyN0qFU0XA246 RA8QFYiCNYwI3f05p6KLxEXAMPLE

Create a new user:

sudo adduser newuser
sudo su - newuser
mkdir .ssh
chmod 700 .ssh
touch .ssh/authorized_keys
chmod 600 .ssh/authorized_keys

Paste the public key copied before in:

vi ~/.ssh/authorized_keys

The above copying process can be automated for all users if you create the file and the directory structure .ssh/authorized_keys in /etc/skel/ directory. Once you do that, the new users created will automatically have these files available in their home directory with proper permissions.

You can also run the following command before creating the users to do what we did above, and the users will be able to log in using their key pair.

sudo su
mkdir-p -- "/etc/skel/.ssh" && sed -e 's/.*\(ssh-rsa.*\) .*/\1/' ~/.ssh/authorized_keys > "/etc/skel/.ssh/authorized_keys"

To force users to configure MFA on their first login, switch to the root user and create a file in /etc/profile.d/ directory and paste the following script in it.

if [ ! -e ~/.google_authenticator ]  &&  [ $USER != "root" ]; then
google-authenticator --time-based --disallow-reuse --force --rate-limit=3 --rate-time=30 --window-size=3
echo "Save the generated emergency scratch codes and use secret key or scan the QR code to
register your device for multifactor authentication."
echo "Login again using your ssh key pair and the generated One-Time Password on your registered

You can remove the condition for $USER != “root” if you want a prompt for a second-factor authentication when you switch to the root user.

At the bottom of the file /etc/pam.d/sshd, it should have the following statement for the above script to run when users log in.

auth       required nullok

Delete the old user account :

sudo userdel -r olduser

By correctly implementing two-factor authentication for your Amazon EC2 Linux hosts, you can reduce risk and significantly increase security.

Reference :


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Powered by

Up ↑

%d bloggers like this: