google authenticator 는  Time-Based One-Time Password algorithm (TOTP) 를 구현한 프로젝트이다.

Unix 용 PAM(Pluggable authentication module) 라이브러리와 유틸리티, 모바일 app 으로 나뉘어져 있으며 인증이 필요한 서비스(Ex: ssh 서버)에 적용하여 two factor 인증 기반으로 보안을 강화할 수 있다.

설치

source 로 설치

소스를 컴파일 하려면 pam 개발 패키지와 컴파일을 하기 위한 gcc, authconf, automake, libtool 이 필요하다. 다음 명령어로 사전에 설치해 놓자.

yum install pam-devel gcc autoconf automake libtool
CODE


  1. git 소스 다운로드

    git clone  https://github.com/google/google-authenticator-libpam
    CODE
  2. 소스 폴더로 이동

    cd google-authenticator/libpam
    CODE
  3. Makefile 을 만들기 위해 ./configure 스크립트 생성

    ./bootstrap.sh 
    CODE
  4. Makefile 생성. 빌드된 pam_google_authenticator.so 모듈을 /lib64/security 에 설치하기 위해 --libdir 옵션 추가  (기본 --prefix=/usr/local 이므로 /usr/local/lib 에 설치됨)

    ./configure --libdir=/lib64
    CODE
  5. root 로 모듈 설치

    make install
    CODE


Package 로 설치

버전이 낮긴 하지만 EPEL 저장소에 google-authenticator 모듈이 등록되어 있으므로 yum 으로 바로 설치 가능하다.

  1. 패키지 설치

    yum install google-authenticator
    CODE

설정

google authenticator 설정

  1. two factor 인증을 사용하려는 계정으로 google-authenticator 명령어 실행

    google-authenticator -t -d  --label webserver --issuer example.com -r 3 -R 30 -s ~/.ssh/google_authenticator
    CODE

    https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/example.com%3Fsecret%3D36C2D4OAM05FK6BO%26issuer%3Dexample.com


    Your new secret key is: 36C4DTOAMO5FK6BO
    Your verification code is 539097
    Your emergency scratch codes are:
    14147128
    71983358
    59882764
    83512453
    29974969

    Do you want me to update your "/home/lesstif/.google_authenticator" file (y/n) y

    By default, tokens are good for 30 seconds and 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. If you experience problems with poor
    time synchronization, you can increase the window from its default
    size of 1:30min to about 4min. Do you want to do so (y/n) y

    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

    • -t, --time-based: 시간 기반 OTP 를 설정.

    • -d, --disallow-reuse: 이전에 사용한 TOTP 토큰의 재사용을 금지

    • -l, --label=<label>: 사용할 label 을 지정하며 구분할 수 있도록 해당 서버의 이름이나 도메인 이름등을 입력하며 여기서는 webserver 로 label 을 지정
    • -i, --issuer=<issuer>: 사용할 발급자를 지정하며 여기에서는 사이트의 메인 도메인 이름을 입력
    • -r, --rate-limit=N:  -R로 설정한 M초동안 허용할 로그인 횟수를 지정
    • -R, --rate-time=M: M 초동안 허용할 로그인 횟수를 지정하며 -r 3 -R 30 은 30초 이내에 최대 3번의 로그인 시도를 허용
    • -S, --step-size=S: OTP 토큰을 갱신할 시간을 지정하며 기본 값은 30이며 이경우 30초마다 토큰을 새로 생성
    • -w, --window-size=W: OTP 토큰은 -S 로 지정한 토큰 갱신 시간(예: 30초) 동안만 유효하지만 입력시 초 단위로 이를 맞추기는 쉽지 않음. 즉 31초에 입력할 경우 OTP 토큰이 갱신되므로 무효화되어 버리며 이런 불편함을 줄이이고 -w 로 지정한 시간만큼 앞위로 유효하게 되며 5로 지정할 경우 토큰 갱신 시간이 30초라면 35초까지 해당 OTP 토큰이 유효
    • -s, --secret=<file>: google otp 의 secret 을 저장할 파일 경로를 지정하며 기본 설정은 $HOME/.google_authenticator 이지만 SELinux를 사용하는 경우 ssh 데몬의 접근을 차단해서 제대로 동작하지 않으므로 SELinux 를 사용하는 경우 .ssh 폴더에 넣어야 제대로 동작함
  2. 설정이 완료되면 ~/.ssh/google_authenticator 파일에 설정이 저장된다.
  3. 진하게 표시한 URL 을 브라우저에 입력하면 QR Code 가 뜬다. google authenticator app 을 띄운후에 메뉴에서 "바코드 스캔" 을 선택후에 생성된 QR Code를 스캐너로 읽으면 자동으로 계정이 추가된다.
     


pam 설정

sshd 에서 google authenticator 를 사용하도록 설정 변경

  1. 설정 파일을 에디터로 오픈

    vi /etc/pam.d/sshd 
    CODE
  2. "#%PAM-1.0" 아래에 다음 내용 추가하고 저장. google_authenticator 는 설정 파일의 이름임.

    #%PAM-1.0
    auth       required     pam_google_authenticator.so secret=${HOME}/.ssh/google_authenticator
    auth       required     pam_sepermit.so
    CODE

    google authenticator 설정 파일의 기본 경로는 ${HOME}/google_authenticator 이지만 이 경로에 저장할 경우 SELinux 가 차단하므로 정상적으로 동작하지 않는다.

  3. 위와 같이 하면 모든 사용자가 google authenticator 를 사용해야 하며 설정한 사용자만 사용하도록 하려면 다음과 같이 nullok 를 추가

    #%PAM-1.0
    auth       required     pam_google_authenticator.so nullok secret=${HOME}/.ssh/google_authenticator
    auth       required     pam_sepermit.so
    CODE

     

    two factor 인증 사용 여부는 $HOME/.ssh/.google_authenticator  파일 존재 여부로 판단한다.

  4. 설정 파일 저장

ssh 서비스 설정

  1. /etc/ssh/sshd_config.내에 설정을 다음과 같이 수정

    PasswordAuthentication yes
    ChallengeResponseAuthentication yes
    UsePAM yes
    CODE

     

  2. sshd 재구동

    service sshd restart 
    CODE

SSH Client 설정

SecureCRT 

  1. 세션 Options 으로 들어간다.
  2. SSH2 -> Authentication 에 "Keyboard interactive" 가 가장 위에 올라 오도록 설정한다.
  3. "Keyboard interactive" 를 클릭하고 우측의 "Properties" 를 클릭한다.
     
  4. Store Password 를 체크 해제 한다. 
  5. 저장하고 세션에 연결하고 아래와 같이 "Verification code:" 창에 OTP 를 입력한다.
     

SSH client

  1. ssh 설정 파일인 ~/.ssh/config를 열어서 다음과 같이  PasswordAuthentication, ChallengeResponseAuthentication, PreferredAuthentications 항목 추가

    Host example.com
        HostName example.com
        PasswordAuthentication yes
        ChallengeResponseAuthentication yes
        PreferredAuthentications keyboard-interactive
    CODE

사용

  1. 서버에 ssh 로 연결한다.
  2. Verification code 프롬프트가 뜨면 google authenticator app 에 뜬 코드(558976)를 입력하고 Password: 에는 기존 암호를 입력한다.

     

    Verification code: 558976
    Password:
    CODE
  3. 정상적으로 로그인이 되지 않으면 아래의 Troubleshooting 참고하여 문제 해결

TroubleShooting

에러 로그는 /var/log/secure 에 남게 되므로 로그인이 되지 않을 경우 이 파일에 남는 로그를 확인해 보자.

Failed to update secret file "/home/lesstif/.google_authenticator"

다음과 같은 에러가 나고 로그인이 안 될 경우 

Invalid verification code

Failed to update secret file "/home/lesstif/.google_authenticator"

  1. SELinux 정책때문에 sshd 는 ~/.ssh 폴더 아래에 있고 context 가 ssh_home_t 인 파일만 읽고 쓸 수 있다. 설정 파일 기본 위치는 $HOME/.google_authenticator 이므로 pam 설정에 secret= 항목에 설정 파일 위치를 .ssh 아래로 변경했는지 확인한다.
  2. context 를 다시 조정해 본다.

    restorecon -R ~/.ssh 
    CODE

로그인이 안 될 경우

  • 다음 에러가 나고 로그인이 안 될 경우 서버와 client 의 시간을 확인해 본다. 

Invalid verification code

client 가 폰이라면 시간이 자동으로 맞으므로 서버 시간을 확인해 보고 다음 명령어로 시간 서버와 동기화한다.

ntpdate ntp.postech.ac.kr
CODE
  • google-authenticator 명령어로 설정 파일을 재생성했다면 새로 QRCode 를 스캔해서 등록해야 한다. 기존에 등록된 주소는 삭제하고(휴지통 아이콘이 비활성화되어 있지만 꾹 누르면 삭제 가능하다.) 새로 바코드를 스캔한다.

Ref