๋น๋ฐ๋ฒํธ๋ ํค๋ฅผ ์ด์ฉํด ์๋ฒ์ ์ ์ํ์ง๋ง ์ด๊ฒ๋ง์ผ๋ก๋ ๋ณด์์ฑ์ด ๋์ง ์๋ค. ๊ทธ๋์ OTP๋ฅผ ์ค์ ํ๋ ค๊ณ ํ๋ค.
๋๋ ์ฌ๋ฌ ๋ ์๋ฒ์ ์ผ๊ด์ ์ผ๋ก ์ ์ฉํ๊ธฐ ์ํด Shell Script๋ Ansible์ ์ด์ฉํ๋ ค๊ณ ํ๋ค. ๋ด๊ฐ ์ฌ์ฉํ๋ OS๋ Rocky Linux 9.7์ด๋ค. Rocky 9๋ฒ์ ๊ณผ Rocky 8๋ฒ์ ์ google authenticator ์ค์ ๋ฐฉ๋ฒ์ ์กฐ๊ธ ์ฐจ์ด๊ฐ ์๊ธฐ ๋๋ฌธ์ 8๋ฒ์ ์ ๋ค๋ฅธ ์๋ฃ๋ฅผ ์ฐธ๊ณ ํ๊ธธ ๋ฐ๋๋ค.
๋จผ์ ๋จ๊ณ๋ณ๋ก ์ค๋ช ํ๊ณ ๋ง์ง๋ง์ Shell Script์ Ansible playbook์ ์์ฑํ๊ฒ ๋ค.
1๏ธโฃํจํค์ง ์ค์น
google authenticator๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํด ํ์ํ ํจํค์ง๋ฅผ ์ค์นํ๋ฉด ๋๋ค.
sudo dnf insatll epel-release google-authenticator qrencode-libs -y
2๏ธโฃGoogle Authenticator ๊ตฌ์ฑ
ํจํค์ง๋ฅผ ์ค์นํ๋ค๋ฉด ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํด์ QR์ฝ๋๋ฅผ ์ค์บํด ์ฑ์ ๋ฑ๋กํ๋ฉด ๋๋ค.
google-authenticator -t -d -f -r 3 -R 30 -W -s .ssh/google
QR์ฝ๋๋ฅผ ์ค์บํ๋ฉด OTP์ฝ๋๋ฅผ ์ ๋ ฅํ๋ผ๋ ๋ฌธ๊ตฌ๊ฐ ๋์ค๋ฏ๋ก ์ ๋ ฅํ๋ฉด ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ ๋ช ๋ น์ ์คํ ์ .ssh ํด๋๊ฐ ์๋ค๋ฉด ์์ฑํ ํ ์คํํ๋ฉด ๋๋ค.
3๏ธโฃSSH ๊ตฌ์ฑ
/etc/pam.d/sshd๋ฅผ ์์ ํด์ผ ํ๋ฏ๋ก ๋ฐฑ์ ๋ณธ์ ๋ง๋ค์ด ๋๋ ๊ฒ์ด ์ข๋ค.
cp /etc/pam.d/sshd /etc/pam.d/sshd.$HOSTNAME
๊ทธ๋ฆฌ๊ณ /etc/pam.d/sshd์ auth required pam_google_authenticator.so secret=${HOME}/.ssh/google์ ์ถ๊ฐํ๋ฉด ๋๋ค. ๋๋ OTP ์ธ์ฆ์ ํ ํ ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋ค์๊ณผ ๊ฐ์ ์์๋ก ์์ฑํ๋ค.

๋น๋ฐ๋ฒํธ ์ ๋ ฅ ํ OTP ์ธ์ฆ์ ํ๊ณ ์ถ๋ค๋ฉด auth include postlogin ๋ค์ ๋์ผ๋ฉด ๋ ๊ฒ์ด๋ค.
๊ทธ๋ฆฌ๊ณ ์ด๋ฒ์๋ /etc/ssh/sshd_config.d ๊ฒฝ๋ก์ 10.gauth.conf๋ฅผ ์์ฑํด ChallengeResponseAuthentication yes๋ฅผ ์ถ๊ฐํ๋ฉด ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ฐ์ ๊ฒฝ๋ก์ 50-redhat.conf์์ ChallengeResponseAuthentication no๋ ์ฃผ์ ์ฒ๋ฆฌํ๋ค.
๋ง์ง๋ง์ผ๋ก sudo systemctl restart sshd๋ฅผ ํ๋ฉด ์ค์ ์ด ๋๋๋ค. ๊ทธ๋ฌ๋ฉด ์ ์ ์ ๋ค์๊ณผ ๊ฐ์ด ํ๋ฉด์ด ๋์์ OTP๋ฅผ ์ ๋ ฅํ๊ณ ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํด์ ์ ์ํ๋ฉด ๋๋ค.

4๏ธโฃShell Script
#!/bin/bash
set -e
# ํจํค์ง ์ค์น
sudo dnf install -y epel-release
sudo dnf makecache
sudo dnf install -y google-authenticator qrencode qrencode-libs
# Google Authenticator ์ด๊ธฐํ (TOTP, ์ฌ์ฌ์ฉ ๊ธ์ง, ์๋ ์ ํ, ๋ํํ ์์ด)
# -f : yes to all questions
# -t : TOTP ์ฌ์ฉ
# -d : ๋๋ ํ ๋ฆฌ ๋ฐฑ์
# -r 3 : ์ฌ์๋ 3ํ
# -R 30 : ์ฌ์๋ ๊ฐ๊ฒฉ 30์ด
# -W : ์๋ ์ ํ
google-authenticator -t -d -f -r 3 -R 30 -W -s .ssh/google
# PAM ์ค์ : ์์ผ๋ฉด ์ถ๊ฐ
if ! grep -q "^auth required pam_google_authenticator.so" /etc/pam.d/sshd
then
# password-auth ์ด์ ์ ์ฝ์
sudo sed -i '/^auth\s\+substack\s\+password-auth/i auth required pam_google_authenticator.so secret=${HOME}/.ssh/google' /etc/pam.d/sshd
fi
sudo tee /etc/ssh/sshd_config.d/10.gauth.conf > /dev/null <<'EOF'
ChallengeResponseAuthentication yes
EOF
# SSH ์ค์ ์ ์ฉ
sudo sed -i -E 's|^(\s*)ChallengeResponseAuthentication(.*)|\1#ChallengeResponseAuthentication\2|' /etc/ssh/sshd_config.d/50-redhat.conf
# SSHD ์ฌ์์
sudo systemctl restart sshd
echo "Google Authenticator ๋ฐ SSH ์ค์ ์๋ฃ."
5๏ธโฃAnsible Playbook
- name: Set Multi Factor Authentication
hosts: inventory๋ก ์ ์ํ ํธ์คํธ ๋ฆฌ์คํธ
become: true
become_method: sudo
tasks:
- name: Install epel-release package
dnf:
name: epel-release
state: present
- name: Update dnf cache after enabling EPEL
dnf:
update_cache: yes
- name: Install google authentication
dnf:
name: google-authenticator
state: present
- name: Install qrencode
dnf:
name: qrencode
state: present
- name: Crete ~/.ssh directory (Optional)
file:
path: ~/.ssh
state: directory
mode: "0700"
- name: Create /etc/ssh/sshd_config.d/10.gauth.conf
copy:
dest: /etc/ssh/sshd_config.d/10.gauth.conf
content: |
ChallengeResponseAuthentication yes
mode: '0644'
- name: Configure Google Authenticator
command:
cmd: google-authenticator -t -d -f -r 3 -R 30 -W -s .ssh/google
stdin: -1
become: true
become_user: lucy
- name: Update /etc/pam.d/sshd
lineinfile:
path: /etc/pam.d/sshd
regexp: '^auth\s+required\s+pam_google_authenticator\.so'
line: "auth required pam_google_authenticator.so secret=${HOME}/.ssh/google"
insertbefore: '^auth\s+substack\s+password-auth'
state: present
backup: true
- name: Update /etc/ssh/sshd_config.d/50-redhat.conf
lineinfile:
path: /etc/ssh/sshd_config.d/50-redhat.conf
regexp: "^#?ChallengeResponseAuthentication"
backup: true
line: "#ChallengeResponseAuthentication no"
state: present
- name: restart sshd
service:
name: sshd
state: restarted
์ด๋ ๊ฒ Shell Script์ Ansible playbook์ ์์ฑํด๋ณด์๋ค. ๋ ์คํฌ๋ฆฝํธ๋ฅผ ๋ชจ๋ ์์ฑํ์ง๋ง ์ด ๊ฒฝ์ฐ์๋ Shell Script๋ก ์์ฑํ๋ ๊ฒ์ด ๋ ๋์ ๊ฒ ๊ฐ๋ค.
๊ทธ๋๋ Ansible๋ก ํ๊ณ ์ถ๋ค๋ฉด google-authenticator ๋ช ๋ น์ด๋ฅผ ansible๋ก ์คํํ๋ ๊ฒ์ ์ถ์ฒํ์ง ์๋๋ค. ์ฑ์ ๋ฑ๋ก์ ํด์ผ ํ๋๋ฐ ์ด ๊ฒฝ์ฐ์๋ qrcode๊ฐ ๋์ค์ง ์์์ ์๋ฒ์์ ํ์ผ์ ์ฐพ์ secret code๋ฅผ ์ง์ ์ ๋ ฅํด ์ฑ์ ๋ฑ๋กํด์ผ ํ๋ค. ๊ทธ๋ฌ๋ฏ๋ก google-authenticator ๋ช ๋ น์ด๋ ๋ฐ๋ก ์ํํด์ sshd.service๋ฅผ ์ฌ์์ํ๋ ๊ฒ์ด ์ข์ ๊ฒ ๊ฐ๋ค.
'OS&Server > Linux' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [Linux] Rocky Linux ์ค์น (0) | 2025.12.08 |
|---|---|
| [Linux] Shell Script๋ฅผ ์ด์ฉํ์ฌ ๋คํธ์ํฌ IP ์ค์ (0) | 2025.06.25 |
| [Linux] Shell Script๋ฅผ ์ด์ฉํ์ฌ ํจํค์ง ๋ฆฌํฌ์งํ ๋ฆฌ ๋ค์ด๋ก๋ (0) | 2025.06.23 |
| [Linux] Shell Script๋ฅผ ์ด์ฉํ์ฌ Timezone ์ค์ (0) | 2025.06.22 |
| [Linux] Shell Script์ ํ์ฉํ์ฌ SSH ํค ๋ณต์ฌ (1) | 2025.06.18 |