SSH 로그인 시 구글OTP를 사용하는 2차 인증 적용 (Ubuntu Linux)

리눅스 서버의 운영체제에 접속하기 위해 대부분은 SSH(Secure Shell)을 사용한다. 하지만 서버가 인터넷에 노출되어 있는 경우 이렇게 SSH서비스 접속을 허용하는 것은 꽤나 큰 위험이 된다. 더군다나 그 웹서버가 개인정보처리시스템이라면 이는 "위법"이 될 가능성이 매우 높다. 개인정보보호법에서는 개인정보처리시스템을 원격에서 접속할 때 대부분의 경우 안전한 접속수단과 안전한 인증수단의 적용을 요구하고 있기 때문이다.

 

이 때 가장 손쉽게 적용할 수 있는 것이 바로 개인정보보호법에서 요구하는 안전한 인증수단인 "OTP"다.  그래서 이 포스트에서는 리눅스 서버 운영체제에 안전한 인증수단인 OTP...그 중에서도 Free하게 사용해도 되는 구글OTP를 적용하는 과정을 포스팅한다.

우분투 리눅스에 구글OTP 모듈 설치하기

구글OTP는 워낙 유명한 솔루션이라 부연설명을 하진 않겠다. 오죽하면 CentOS와 RedHat리눅스 그리고 우분투 리눅스의 어플리케이션 리포지토리에 패키지로 등록되어 있을까.. 

 

다음과 같은 명령으로 우분투 리눅스에 구글 OTP의 서버모듈인 Google Authenticator를 설치한다.

root@www:~# 
root@www:~# apt install libpam-google-authenticator
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages were automatically installed and are no longer required:
  libccid libpcsclite1 opensc opensc-pkcs11 pcscd
<중간생략>
Preparing to unpack .../libpam-google-authenticator_20170702-2_amd64.deb ...
Unpacking libpam-google-authenticator (20170702-2) ...
Setting up libqrencode4:amd64 (4.0.2-2) ...
Setting up libpam-google-authenticator (20170702-2) ...
Processing triggers for man-db (2.9.1-1) ...
Processing triggers for libc-bin (2.31-0ubuntu9.1) ...

root@www:~# 

당연히 Google Authenticator는 root 계정의 권한으로 설치해야 한다. 현재 계정이 root가 아니라면 apt 명령 앞에 sudo를 붙어 실행하면 되겠다.

구글OTP를 사용하여 접속할 계정에서 Google Authenticator 설정하기

이 단계를 진행하기 전에 반드시 스마트폰에 Google OTP 앱을 설치하여야 한다.

 

Google OTP는 타임베이스의 1회용 비밀번호를 스마트폰에 설치한 Google OTP앱과 서버에 로그인할 때 서버에 설치된 Google Authenticator가 동시에 만들어 서로 비교하는 방식으로 인증을 수행하게 된다. 즉 1회용 비밀번호를 만들 때 서버와 스마트폰의 통신은 없다. 

다만 1회용 비밀번호를 만들 때 스마트폰과 서버가 서로 동일한 시크릿키(Secret Key)를 기준으로 만들어 보안을 유지하게 된다. 그래서 서버의 Google Authenticator를 설치할 때 가장 중요한 것이 바로 이 시크릿 키를 스마트폰의 구글 OTP앱과 서버가 나누어 공유하는 과정이다.

 

구글에서는 이 시크릿 키를 사용자 계정마다 만드는데 "서버의 구글OTP를 사용할 사용자 계정에서 Google Authenticator 초기화"를 수행하고 이 때 QR코드를 사용해 스마트폰의 구글OTP 앱에 시크릿키를 공유하는 방법을 사용한다.

OS 계정에 Google Authenticator 설정하기

다음과 같이 구글 OTP를 사용해 2차 인증을 적용할 계정으로 로그인하여 Google Authenticator 설정한다.


$ id
uid=1000(taeho) gid=33(www-data) groups=33(www-data)

$ google-authenticator

Do you want authentication tokens to be time-based (y/n) y
Warning: pasting the following URL into your browser exposes the OTP secret to Google:
  https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/taeho@www.homepage.kr%3Fsecret%3D****************H4%26issuer%3Dwww.homepage.kr

<QR코드 보임>
                                                                                          
Your new secret key is: ND*******************************H4
Your verification code is 7****4
Your emergency scratch codes are:
  8********6
  4********9
  4********2
  4********8
  7********5

Do you want me to update your "/home/taeho/.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) 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
$  

위의 내용을 보면 Secret Key와 이 시크릿 키 분실 시 복구할 수 있는 스크래치 코드를 보여준다. 최소한 스크래치 코드는 잘 보관하길 바란다.

 

그리고 중간에 <QR CODE>라고 되어 있는 부분에 실제 QR코드가 큼지막하게 나온다. 이 QR코드를 구글OTP 앱을 실행해 + 표시를 터치해 등록해 준다. 그러면 구글OTP에 해당 서버가 제목으로 되어 있는 1회용 비밀번호가 바로 표시되기 시작한다.

서버의 PAM 파일과 SSHD 설정 변경하기

로그인 과정에서 구글OTP 인증과정을 실행시키기 위해 다음과 같이 PAM 설정 파일 중 sshd 파일에 빨간색 설정 문구를 추가한다. 이 파일은 /etc/pam.d 디렉토리 sshd 라는 이름으로 위치해 있다.

<상단 생략>
# /etc/default/locale, so read that as well.
session    required     pam_env.so user_readenv=1 envfile=/etc/default/locale

# SELinux needs to intervene at login time to ensure that the process starts
# in the proper default security context.  Only sessions which are intended
# to run in the user's context should be run after this.
session [success=ok ignore=ignore module_unknown=ignore default=bad]        pam_selinux.so open

# Standard Un*x password updating.
@include common-password

# google otp
auth required pam_google_authenticator.so nullok
#

다음은 /etc/ssh/sshd_config 파일을 수정한다. 이 파일의 위치는 설치 방법에 따라, 운영체제 버전에 따라 조금 다를 수 있다. 다음의 4개의 옵션을 찾아 아래와 같이 수정한다.

UsePAM yes
ChallengeResponseAuthentication yes

Google OTP는 사실 Challenge-Response 방식의 인증은 아니지만 sshd가 운영체제 인증에 추가해 적용되는 2차 비밀번호를 입력받기 위해 ChallengeResponseAuthentication 옵션을 yes로 변경해야 하는 것으로 보인다. 

 

그리고 두 옵션외에 하나를 더 변경하라고 하는 경우가 있는데... 필자는 두 옵션만 위와 같이 변경하면 다른 옵션은 어떤 값이든 상관없이 잘 동작했다.

 

그리고 나서 sshd 서비스를 재구동 한다. 당연히 root 계정으로 실행해야 한다.

# service sshd stop
# service sshd start

구글 OTP로 로그인하기

해당 서버에 ssh 접속을 시도하고 Google Authenticator를 설정한 계정의 ID를 입력한다.

ssh 접속 시 id 입력

아래의 Keyboard Interactive 를 선택하고 "확인"을 누른다. Putty라면 자동으로 Keyboard Interactive 모드로 바뀌고 비밀번호를 입력받을 것이다.

keyboard interactive 모드 선택

계정의 비밀번호를 입력한다.

비밀번호 입력

다음으로 Verification Code 를 묻는데 바로 이 것이 OTP 비밀번호 6자리를 묻는 것이다. 스마트폰에 설치된 구글 OTP 앱에서 이 서버의 항목에 표시된 OTP 번호 6자리를 입력한다.

구글 OTP의 6자리 입력 (Verification Code)

로그인이 될 것이다.

 

#GoogleOTP  #ssh

댓글(0)

Designed by JB FACTORY