Help us understand the problem. What is going on with this article?

ssh password authentication + Google Authenticator

More than 3 years have passed since last update.

sshのパスワード認証(公開鍵認証ではない) + MFAtoken によるログインの設定方法です。
やりたいことは、クラメソさんのこの記事のパスワード認証版です。

  • 検証には、AWSさんから、Amazon Linux AMI 2017.03.1 (HVM), SSD Volume Type (ami-3bd3c45c) を利用しました。
  • MFAtoken は Google Authenticator です。

[Note] 本ドキュメントの command枠 のコピペ作業で、動作できるように作っています。(ミスを避けるため vi による編集を避けた)

1. pre-conditions

1.1 Login to the server

AWSの操作は省略します。下記のAMIをつかってサーバを起動しました。

  • Amazon Linux AMI 2017.03.1 (ami-3bd3c45c) をつかってEC2を起動します。
  • 起動後、サーバーへログインします。

1.2 Chenge timezone (追記: たぶん変更しなくても大丈夫)

Timezoneの設定はこちらを参考にしました。

timezoneファイル差し替え

command
sudo cp /etc/localtime /etc/localtime.org
sudo ln -sf  /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
&& cat /etc/localtime

reboot後変更したタイムゾーンがUTCにもどらないための設定

command
sudo cp /etc/sysconfig/clock /etc/sysconfig/clock.org
sudo sh -c "echo -e 'ZONE=\"Asia/Tokyo\"\nUTC=false' > /etc/sysconfig/clock" \
&& cat /etc/sysconfig/clock

1.3 Update packages

command
sudo yum update

1.4 Installing google/google-authenticator

command
sudo yum install google-authenticator qrencode-libs -y

2. How to setup

2.1 Editing sshd_config

/etc/ssh/sshd_config の編集

編集するsshd_configのバックアップをとります.

commnad
cp /etc/ssh/sshd_config ${HOME}/_bak_sshd_config

sshd_configが下記になるよう編集します。

PasswordAuthentication は yes でも no でもどちらでも大丈夫です。
/etc/pam.d/sshdpassword-auth を有効にすることでこの設定は関係なく上手く動くようです。

  • ChallengeResponseAuthentication yes
  • UsePAM yes

現状を確認します。

command
cat /etc/ssh/sshd_config \
| grep -e ^PasswordAuthentication \
       -e ^ChallengeResponseAuthentication \
       -e ^UsePAM
response
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM yes

ここでは ChallengeResponseAuthenticationyes になるよう編集する必要があることがわかりましたので、修正します。

command
BEFORE="ChallengeResponseAuthentication no"
AFTER="ChallengeResponseAuthentication yes"
sudo sed -i s/"${BEFORE}"/"${AFTER}"/g /etc/ssh/sshd_config

再度内容を確認します。

command
cat /etc/ssh/sshd_config \
| grep -e ^ChallengeResponseAuthentication
response
ChallengeResponseAuthentication yes

ec2-userは今まで通り公開鍵認証のログインのままとします。

command
sudo sh -c "cat << EOF >> /etc/ssh/sshd_config

# -- EC2 USER Setting --
Match User ec2-user
   AuthenticationMethods publickey
   PubkeyAuthentication yes
   PasswordAuthentication no
EOF" && tail /etc/ssh/sshd_config
response
#   X11Forwarding no
#   AllowTcpForwarding no
#   PermitTTY no
#   ForceCommand cvs serverMatch User ec2-user

# -- EC2 USER Setting --
Match User ec2-user
   AuthenticationMethods publickey
   PubkeyAuthentication yes
   PasswordAuthentication no

sshdの再起動

sshdの再起動します。

command
sudo service sshd restart
response
Stopping sshd:                                             [  OK  ]
Starting sshd:                                             [  OK  ]

2.2 Editing PAM sshd

次にPAMの設定を修正し、sshログイン認証時にGoogle Authenticatorが使われるようにします。

/etc/pam.d/google-authの作成

同じファイル名のファイルがないことを確認します。

command
ls -l /etc/pam.d/google-auth
response
ls: cannot access /etc/pam.d/google-auth: No such file or directory

google-authという名前のファイルを作成します。これは /etc/pam.d/sshd から読み込みます。

command
sudo sh -c "cat << EOF > /etc/pam.d/google-auth
#%PAM-1.0
auth        required      pam_env.so
auth        sufficient    pam_google_authenticator.so nullok
auth        requisite     pam_succeed_if.so uid >= 500 quiet
auth        required      pam_deny.so
EOF" && cat /etc/pam.d/google-auth

/etc/pam.d/sshdの編集

編集する /etc/pam.d/sshd のバックアップをとります.

command
cp /etc/pam.d/sshd ${HOME}/_bak_pam_sshd

現在の変数の状況を確認します。

command
cat /etc/pam.d/sshd | grep ^auth
response
auth       required pam_sepermit.so
auth       substack     password-auth
auth       include      postlogi

google authentication を有効にするためこのファイルを編集します。

command
BEFORE="auth       substack     password-auth"
AFTER="auth       substack     password-auth\nauth       substack     google-auth"
sudo sed -i s/"${BEFORE}"/"${AFTER}"/g /etc/pam.d/sshd

もう一度ファイルを確認します。

command
cat /etc/pam.d/sshd | grep "^auth"
response
auth       required pam_sepermit.so
auth       substack     password-auth
auth       substack     google-auth
auth       include      postlogin

もう一度サービスを再起動します(いらないかも...)

command
sudo service sshd restart
Stopping sshd:                                             [  OK  ]
Starting sshd:                                             [  OK  ]

2.3 Creating ".google_authenticator" at first user's login

/etc/profile.d/google-authenticator.shを作成し、root と ec2-user以外のユーザがはじめてログインしたとき、google_authenticatorの初期設定がなされ、ユーザの ${HOME}/.google_authenticator が強制的に作成されるよう設定します。

同名のファイルがないかを確認します。

command
ls -l /etc/profile.d/google-authenticator.sh
response
ls: cannot access /etc/profile.d/google-authenticator.sh: No such file or directory

/etc/profile.d/google-authenticator.sh を作成します

command
cat << EOF > google-authenticator.sh
#!/bin/sh

trap 'exit' SIGINT

if [ "\$USER" != "root" -a "\$USER" != "ec2-user" ]; then
  if [ ! -f "\$HOME/.google_authenticator" ]; then
    echo "setup google-authenticator..."
    /usr/bin/google-authenticator -t -d -w 17 -u -f
  fi
fi
EOF
sudo cp google-authenticator.sh /etc/profile.d/google-authenticator.sh
sudo chmod +x /etc/profile.d/google-authenticator.sh
cat /etc/profile.d/google-authenticator.sh

-W 17 はもし、/usr/bin/google-authenticator を直だたきしたあと、4つめの "window" に関する質問 y で答えると、設定される値です。ここを調整しないとなぜかログインできなかったです。サーバとTokenデバイス間の Time-skew?

3. Test

3.1 Creating Test User

サーバー側へのログイン用のユーザを作ります。
/etc/pam.d/google-authの設定により、UIDは必ず500以上にする必要があります。

ユーザ名を決定します。

command
NEWUSER=<'任意のユーザ名'>

ユーザを作成します。

command
sudo useradd ${NEWUSER}

ユーザの状態を確認します。

command
id -a ${NEWUSER}
response
uid=501(<'任意のユーザ名'>) gid=501(<'任意のユーザ名'>) groups=501(<'任意のユーザ名'>)

初期パスワードを設定します。

command
sudo passwd ${NEWUSER}

3.2 Test

初回ログイン

テストを実施します。

command
ssh <'作成したユーザ'>@<'サーバー名'>

下記スクリーンショットの1行目の "Password" で Unixパスワードを入力しました。
1回目は、MFATokenの設定がされていないので、そのままログインできます。

Kobito.o4XnfV.png

2回目以降

サーバにログインします。

command
ssh <'作成したユーザ'>@<'サーバー名'>

PasswordでUnixパスワードを入力し、Verification code でMFATokenを入力します。

response
Password: 
Verification code: 
Last login: Mon Aug  7 22:18:47 2017 from aa20111001946f573a19.userreverse.dion.ne.jp

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2017.03-release-notes/

4. Refereces

5. Appendix

/etc/ssh/sshd_config
#   $OpenBSD: sshd_config,v 1.93 2014/01/10 05:59:19 djm Exp $

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

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

# 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.

# If you want to change the port on a SELinux system, you have to tell
# SELinux about this change.
# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER
#
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::

# The default requires explicit activation of protocol 1
#Protocol 2

# HostKey for protocol version 1
#HostKey /etc/ssh/ssh_host_key
# HostKeys for protocol version 2
HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key

# Lifetime and size of ephemeral version 1 server key
#KeyRegenerationInterval 1h
#ServerKeyBits 1024

# Ciphers and keying
#RekeyLimit default none

# Logging
# obsoletes QuietMode and FascistLogging
#SyslogFacility AUTH
SyslogFacility AUTHPRIV
#LogLevel INFO

# Authentication:

#LoginGraceTime 2m
#PermitRootLogin yes
# Only allow root to run commands over ssh, no shell
PermitRootLogin forced-commands-only
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

#RSAAuthentication yes
#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
#RhostsRSAAuthentication no
# similar for protocol version 2
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# RhostsRSAAuthentication and 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
# EC2 uses keys for remote access
PasswordAuthentication no

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

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

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no
#GSSAPIEnablek5users no

# 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'.
# WARNING: 'UsePAM no' is not supported in Amazon Linux AMI and may cause several
# problems.
# Leaving enabled as described so that account and session checks are run
UsePAM yes

#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
#PrintMotd yes
# Explicitly enable
PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
UsePrivilegeSeparation sandbox      # Default for new installations.
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#ShowPatchLevel no
#UseDNS yes
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none

# no default banner path
#Banner none

# Accept locale-related environment variables
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS

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

# Example of overriding settings on a per-user basis
#Match User anoncvs
#   X11Forwarding no
#   AllowTcpForwarding no
#   PermitTTY no
#   ForceCommand cvs serverMatch User ec2-user
Match User ec2-user
   AuthenticationMethods publickey
   PubkeyAuthentication yes
   PasswordAuthentication no
/etc/pam.d/google-auth
#%PAM-1.0
auth        required      pam_env.so
auth        sufficient    pam_google_authenticator.so nullok
auth        requisite     pam_succeed_if.so uid >= 500 quiet
auth        required      pam_deny.so
/ssh/pam.d/sshd
#%PAM-1.0
auth       required pam_sepermit.so
auth       substack     password-auth
auth       substack     google-auth
auth       include      postlogin
# Used with polkit to reauthorize users in remote sessions
-auth      optional     pam_reauthorize.so prepare
account    required     pam_nologin.so
account    include      password-auth
password   include      password-auth
# pam_selinux.so close should be the first session rule
session    required     pam_selinux.so close
session    required     pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session    required     pam_selinux.so open env_params
session    required     pam_namespace.so
session    optional     pam_keyinit.so force revoke
session    include      password-auth
session    include      postlogin
# Used with polkit to reauthorize users in remote sessions
-session   optional     pam_reauthorize.so prepare
/etc/profile.d/google-authenticator.sh
#!/bin/sh

trap 'exit' SIGINT

if [ "$USER" != "root" -a "$USER" != "ec2-user" ]; then
  if [ ! -f "$HOME/.google_authenticator" ]; then
    echo "setup google-authenticator..."
    /usr/bin/google-authenticator -t -d -w 17 -u -f
  fi
fi

Memo: 1回目はパスワード、2回目はMFATokenのみの動作

1回目はパスワード、2回目はMFATokenのみのログインにしたい場合、/etc/pam.d/sshd を下記のようにします。またgoogle-authは必要ありません。なぜかは分からないけど、いろいろ触っていたらできた。
ようわからん。。。

/etc/pam.d/sshd
#%PAM-1.0
auth       required pam_sepermit.so
#auth       substack     password-auth
auth       sufficient    pam_google_authenticator.so 
auth       requisite     pam_succeed_if.so uid >= 500 quiet
auth       substack     password-auth
#auth       substack     google-auth
auth       include      postlogin
# Used with polkit to reauthorize users in remote sessions
-auth      optional     pam_reauthorize.so prepare
account    required     pam_nologin.so
account    include      password-auth
password   include      password-auth
# pam_selinux.so close should be the first session rule
session    required     pam_selinux.so close
session    required     pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session    required     pam_selinux.so open env_params
session    required     pam_namespace.so
session    optional     pam_keyinit.so force revoke
session    include      password-auth
session    include      postlogin
# Used with polkit to reauthorize users in remote sessions
-session   optional     pam_reauthorize.so prepare
daikumatan
2002-2015: Fujixerox, Numerical simulation Engineer 2015-2016: NVIDIA Japan, BD Manager 2016-2020: Rescale Japan, Evangelist 2020-Present: XTREME-D, CTO
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away