Google Authenticator on Linux (Ubuntu, CentOS)

Linux SSH 로그인에 Google Authenticator OTP를 추가하는 절차입니다. PAM, sshd_config, 공개키+OTP 구성, 검증과 롤백 순서를 운영 기준으로 정리했습니다.

Linux SSH 로그인에 Google Authenticator 기반 OTP를 추가하는 절차입니다. 실습은 설치 명령과 설정 파일 수정 순서가 한 코드블록에 섞여 있었기 때문에, 실제 운영에서 잠기지 않도록 백업, PAM 설정, sshd 설정, 검증, 롤백 순서로 운영 순서로 정리합니다. SSH 인증 설정은 실수하면 원격 접속이 끊길 수 있으므로 기존 root 또는 sudo 세션을 닫지 않은 상태에서 새 세션으로 테스트해야 합니다.

구성 목표

  • Ubuntu 또는 CentOS/RHEL 계열 서버에 Google Authenticator PAM 모듈을 설치합니다.
  • 사용자별 OTP secret을 생성하고 OTP 앱에 등록합니다.
  • SSH 로그인 시 PAM keyboard-interactive 인증으로 OTP를 요구합니다.
  • 설정 전후 백업과 sshd -t 검증으로 원격 접속 장애를 줄입니다.

작업 전 주의사항

  • 현재 SSH 세션을 닫지 말고 유지합니다.
  • 콘솔 접속 경로가 있는 VM/서버라면 콘솔 접속도 준비합니다.
  • OTP는 사용자별로 생성됩니다. root에만 생성하고 일반 사용자로 로그인하면 적용되지 않습니다.
  • 시간이 크게 틀어져 있으면 OTP 검증이 실패하므로 NTP/chrony 상태를 먼저 확인합니다.

시간 동기화 확인

date
timedatectl status
chronyc tracking 2>/dev/null || true

chrony가 없다면 OS 계열에 맞게 설치하고 활성화합니다.

# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y chrony
sudo systemctl enable --now chrony

# CentOS/RHEL
sudo yum install -y chrony
sudo systemctl enable --now chronyd

패키지 설치

Ubuntu/Debian

sudo apt-get update
sudo apt-get install -y libpam-google-authenticator

CentOS/RHEL 계열

sudo yum install -y epel-release
sudo yum install -y google-authenticator

사용자별 OTP 초기화

OTP를 사용할 계정으로 로그인한 뒤 실행합니다. QR 코드와 secret key, emergency scratch code가 출력되므로 외부에 노출하지 말고 안전하게 보관합니다.

google-authenticator

일반적인 운영 기준에서는 다음과 같이 선택합니다. 정책에 따라 달라질 수 있지만, SSH 2FA 목적이라면 시간 기반 OTP를 사용하고, 같은 토큰 재사용을 막는 편이 안전합니다.

  • Time-based token: yes
  • Update ~/.google_authenticator: yes
  • Disallow multiple uses: yes
  • Increase time skew window: 시간 동기화가 안정적이면 no
  • Rate-limit login attempts: yes

설정 파일 백업

sudo cp -a /etc/pam.d/sshd /etc/pam.d/sshd.bak.$(date +%Y%m%d-%H%M%S)
sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%Y%m%d-%H%M%S)

PAM 설정

/etc/pam.d/sshd에 Google Authenticator PAM 모듈을 추가합니다. 강제 적용 전 일부 사용자만 단계적으로 테스트해야 한다면 임시로 nullok를 붙일 수 있지만, 최종 운영에서는 OTP secret이 없는 사용자가 우회하지 못하도록 nullok를 제거하는 것이 좋습니다.

sudo vi /etc/pam.d/sshd

파일 상단 또는 인증 흐름에 맞는 위치에 추가합니다.

auth required pam_google_authenticator.so

단계적 전환용 임시 설정은 다음과 같습니다.

auth required pam_google_authenticator.so nullok

sshd_config 설정

sudo vi /etc/ssh/sshd_config

OpenSSH 버전에 따라 keyboard-interactive 옵션 이름이 다를 수 있습니다. 최신 계열에서는 KbdInteractiveAuthentication을 사용하고, 구버전 호환이 필요한 경우 ChallengeResponseAuthentication도 같이 확인합니다.

UsePAM yes
KbdInteractiveAuthentication yes

# 구버전 OpenSSH에서 사용하는 이름인 경우
ChallengeResponseAuthentication yes

공개키 인증 후 OTP를 추가로 요구하려면 다음 구성을 사용할 수 있습니다.

PubkeyAuthentication yes
PasswordAuthentication no
AuthenticationMethods publickey,keyboard-interactive:pam

비밀번호와 OTP 조합으로 운영할지, 공개키와 OTP 조합으로 운영할지는 서버 정책에 맞춰 정해야 합니다. 공개 서버라면 비밀번호 로그인을 끄고 공개키+OTP로 가는 편이 일반적으로 더 안전합니다.

적용 전 검증과 reload

sudo sshd -t
sudo systemctl reload sshd || sudo systemctl reload ssh

sshd -t에서 에러가 나오면 절대 reload/restart하지 말고 설정 파일을 먼저 복구합니다. reload 후에는 기존 세션을 유지한 상태에서 새 터미널로 SSH 접속을 열어 OTP가 정상 동작하는지 확인합니다.

ssh -vvv user@server.example.com

롤백

OTP 인증 때문에 새 SSH 접속이 실패하면 기존 세션에서 백업 파일을 되돌립니다.

sudo cp -a /etc/pam.d/sshd.bak.YYYYMMDD-HHMMSS /etc/pam.d/sshd
sudo cp -a /etc/ssh/sshd_config.bak.YYYYMMDD-HHMMSS /etc/ssh/sshd_config
sudo sshd -t
sudo systemctl reload sshd || sudo systemctl reload ssh

운영 체크 포인트

  • OTP secret과 scratch code를 문서나 채팅에 평문으로 남기지 않습니다.
  • 사용자별 ~/.google_authenticator 권한이 너무 열려 있지 않은지 확인합니다.
  • 자동화 계정, 백업 계정, 모니터링 계정처럼 비대화형 SSH가 필요한 계정은 별도 정책을 정합니다.
  • 방화벽이나 fail2ban이 있다면 OTP 실패 반복 시 차단 정책도 같이 확인합니다.
  • 운영 반영 후 실제 새 SSH 세션, sudo 가능 여부, emergency rollback 경로를 확인합니다.
BGM EVER