여러 대의 서버를 운영하다 보면 맞닥뜨리는 어려움 중 하나가 바로 ID와 비밀번호의 관리다.
많은 엔지니어들과 많은 서버… 그리고 각 서버마다 접근권한을 어떻게 관리할 것인가하는 문제는 보안 관점에서 매우 골치아픈 문제다. 이 문제를 해결하기 위해 사용되는 여러 솔루션들이 있는데 그 중 하나가 바로 커버로스(Kerberos)다.
커버로스는 “티켓”을 기반으로 동작하는 컴퓨터 네트워크 인증 암호화 프로토콜로서 비보안 네트워크에서 통신하는 노드가 보안 방식으로 다른 노드에 대해 식별할 수 있게 허용한다. 클라이언트 서버 모델을 목적으로 개발되었으며 사용자와 서버가 서로 식별할 수 있는 상호 인증을 제공한다고 위키에서 설명하고 있다.
간단하게 부연 설명을 하자면…
커버로스 인증을 통해 서버에 로그인하는 과정
1. 사용자가 A라는 서버에 SSH를 통해 접속하고자 할 때 ID와 비밀번호를 입력한다.
2. 커버로스 인증을 수행하도록 설정된 SSH 대몬은 krb5.conf에 지정된 KDC(Key Distribution Center)의 AS(Authentication Server)에게 인증을 요청하도록 SSH 클라이언트에게 알리고 SSH 클라이언트는 AS에게 인증을 요청한다.
– ID와 비밀번호를 암호화하여 AS에게 전송함
3. AS는 LDAP 또는 자체 프린서플(principal) DB(커버로스 데이터베이스)에서 ID와 비밀번호를 검증한다.
4. AS는 검증이 완료될 경우 TGS에게 다음의 두 메시지 생성을 요청하여 수신받아 클라이언트에게 응답함
– 티켓발급용 티켓(TGT-Ticket Granting Ticket) : 클라이언트 ID, 주소, 유효기간, TGS 세션키를 TGS 비밀키로 암호화한 메시지
– 클라이언트에서 제공한 비밀번호(Password)기반의 비밀키로 암호화 한 TGS 세션키
* 클라이언트는 TGS의 비밀키를 알지 못하므로 티켓을 복호화할 수 없음
5. AS로 부터 2개의 메시지를 수신한 클라이언트는 KDC의 TGS에게 다음의 두가지 메시지를 전송
– Authenticator : 비밀번호 기반의 비밀키로 복호화한 TGS 세션키를 암호키로 암호화 한 클라이언트 ID와 타임스탬프
– AS로부터 제공받은 티켓발급용 티켓(TGT)
* 클라이언트는 TGS의 비밀키를 알지 못하므로 TGT를 복호화하거나 조작할 수 없음
6. TGS는 클라이언트로부터 받은 TGT와 Authenticator를 복호화하여 ID를 검증하고 2개의 메시지를 클라이언트에게 응답함
– 자신이 발급한 TGT와 TGS세션키를 검증
– SGT(Session Granting Ticket) : SS비밀키로 암호화한 클라이언트 ID, 주소, 유효기간 SS세션키가 포함된 메시지
– SS세션키를 TGS세션키로 암호화한 메시지
7. 클라이언트는 응용프로그램 서버(여기서는 SSHD)에게 다음의 두 메시지를 전달함
– Authenticator : TGS세션키로 복호화한 SS세션키로 클라이언트 ID와 타임스탬프를 암호화한 메시지
– SGT(Session Granting Ticket)
8. 응용프로그램 서버(여기서는 SSHD)는 SGT와 Authenticator를 복호화하여 ID 등이 일치할 경우 아래 메시지를 클라이언트에게 전달함
– SS 세션키로 암호화한 타임스탬프
9. 클라이언트는 타임스탬프가 일치할 경우 인증완료
사실 이 과정 중 응용프로그램 서버의 의미가 명확하지 않다.
이런 복잡한 과정을 모두 알아야 할 필요는 없다. 여기서는 커버로스 인증을 리눅스 시스템에 적용하기 위한 SW의 설치와 설정을 중심으로 포스팅한다.
커버로스(kerberos) KDC 설치 및 구성하기
커버로스 KDC는 Realm 이라고 하는 인증서비스를 제공하기 위한 서버와 클라이언트들의 네트워크를 식별해야 한다. 그리고 이 Realm은 도메인으로 구분된다고 이해하면 된다. 그래서 KDC를 구성하는 커버로스 인증서버(AS)와 티켓그랜팅서비스(TGS)를 설치하기 위해서는 서버운영체제가 도메인에 속해 있어야 한다.
그리고 인증서버(AS)가 외부 도메인 계정 관리를 수행하는 OpenLDAP이나 Active Directory 서버와 연동되도록 할 수 있지만 일단은 커버로스 자체의 DB를 사용하도록 한다.
따라서 서버의 호스트네임과 도메인이 설정되어 있어야 한다. /etc/hosts 파일에 KDC를 구성할 서버를 도메인에 가입시킨다. 그리고 이 서버는 Ubuntu Linux 20.04 버전이다.

호스트네임을 다음 명령을 통해 설정한다.

apt-get 명령으로 krb5-kdc와 krb5-admin-server 패키지를 설치한다.

패키지 설치가 완료되면 krb5-admin-server 설정 스크립트가 실행되는데….

이 창에서 OK를 눌러 실행하면 에러가 발생한다. 이렇게 말이다.

Kerberos 설치 중 다음과 같이 Database Open 에러가 발생한다.
“Cannot open DB2 database ‘var/lib/krb5kdc/principal’ : No such file or irectory – while initializing database for real BLOGGER.PE.KR”
이 DB2 데이터베이스는 principal 이라는 커버로스의 인증 주체에 대한 계정정보를 담고 있는 데이터베이스인데.. 이 DB를 만들지 못해서 KDC 서비스인 AS와 TGS가 실행되지 못하는 것으로 보인다. 이따금씩 이스터에그처럼 등장하는 에러.. 조금 짜증나기도 한다. ^^
수동으로 만들어주면 되지 않을까 싶어 방법을 찾아보니… 방법이 있다. 다음과 같이 에러가 발생한 상태에서 곧바로 kdb5_util 명령으로 커버로스의 Realm인 BLOGGER.PE.KR을 이름으로 하는 데이터베이스를 생성해주면 된다.

커버로스 DB를 수동으로 생성한 뒤 수동으로 krb5-kdc 패키지를 재설정하는 명령을 실행해주면 된다.

다음과 같이 재설정이 실행된다.

“Yes” 버튼을 누르면 아무런 에러도..아무런 메시지도 없이 완료된다. 커버로스 데이터베이스에 접속한 뒤 뭔가 추가적인 작업이 진행될 것도 같은데.. 화면엔 아무런 표시도 해주지 않는다.
데이터베이스를 찾을 수 없다던 디렉토리를 확인하면 커버로스 데이터베이스가 생성되어 있는 것을 볼 수 있다.

일단 커버로스 AS와 TGS를 설치하였으므로 kdc.conf 파일이 다음과 같이 생성되어 있는지 확인한다.

보안에 취약한 알고리즘을 사용하는 것을 확인할 수 있다. 커버로스 v4 까지는 DES 계열 알고리즘을 사용하지만 v5 부터는 안전한 알고리즘들을 지원한다. 변경할 수 있는지 확인이 필요하다.
클라이언트 설정인 krb5.conf 도 미리 확인해둔다. default_realm이 호스트의 도메인과 같은 BLOGGER.PE.KR로 설정되어 있음을 확인하자.

커버로스 KDC의 관리자 권한 접속을 제한할 수 있는 kadm5.acl 파일도 설정해준다. 일단 모든 계정이 어디서든 관리자로 등록될 수 있도록 열어둔다. 자세한 설정 방법은 공부를 좀 해야할 듯 싶다.

커버로스 서버에서 실행할 수 있는 관리자프로그램인 kadmin.local 명령을 실행한다. 기본적으로 root 계정은 관리자 권한으로 접속할 수 있는 것 같다.

그리고 host를 등록해 준다. (왜…??? -.-) 커버로스에 대한 이해가 부족하다보니 이런 작업이 왜 필요한지는 모르겠다. 다만 ktadd를 통해 키탭을 등록해주는 것을 보면 사용자가 비밀번호나 키체인이 아닌 키가 저장된 키탭파일을 통해 인증을 하지 않는다면 host와 키탭을 등록하는 과정은 필요하지 않을 것으로 예상된다.
관리자 계정을 등록하는 addprinc taeho/admin 명령과 비밀번호 등록만 해도 문제가 없지 않을까 생각된다.
마지막으로 커버로스 KDC를 재실행한다.

커버로스 KDC 서버의 설치는 완료되었다.
커버로스 클라이언트 설정하기
이제 커버로스 인증을 통해 접속할 클라이언트에 필요한 설정을 진행한다.
먼저 클라이언트의 /etc/hosts 파일에 자신과 커버로스 KDC 서버를 도메인이름과 함께 등록해준다.

클라이언트의 hostname도 설정해준 뒤 apt-get update 명령으로 설치 가능한 패키지 목록을 업데이트 한다.

커버로스 클라이언트 설정에 필요한 패키지를 설치한다.

설치 한 뒤 /etc/krb5.conf 파일을 다음과 같이 설정해준다.

[realm] 섹션에는 도메인 이름과 그 도메인 내의 KDC 구성요소의 호스트네임을 적어준다. 그리고 [domain_realm]은 도메인명만 적어주면 된다. 실제 도메인명을 커버로스 KDC에서 사용하는 도메인이름인 대문자로 지정해주면 된다.
여기까지 클라이언트 설정이 완료되었다.

클라이언트에서 kadmin 명령을 통해 서버 설치 중 관리자 계정으로 등록한 taeho 계정으로 커버로스 KDC에 접속해본다. 위 화면과 같이 정상적으로 접속된다면 KDC 연결에 문제가 없다고 보면 된다.
그리고 ssh 접속 시 클라이언트가 커버로스 인증을 받도록 하기 위해 /etc/ssh/sshd_config 파일에서 다음 두 라인을 yes 옵션으로 수정하고 주석(#)을 해제해준다.

이 GSSAPI 옵션 위에 보면 kerberos 관련 옵션들도 있는데… 정작 그 옵션들은 수정하지 않아도 된다. (왜지..??? @.@)
그리고 당연하겠지만 sshd 서비스를 재구동한다.

그리고 KDC 서버( == 커버로스 인증서버)에서 kadmin.local 명령을 실행하고 클라이언트인 ubuntu18 서버에 생성할 oracle 계정의 프린서플(principal)을 추가해준다. (프린씨펄..?? @.@)

그리고 테스트 결과 커버로스 인증서버에는 이 계정(oracle)을 만들지 않아도 된다. (확인 완료)
단, 실제로 커버로스 인증을 통해 접속할 클라이언트인 ubuntu18 서버에는 접속할 계정이 존재해야 한다.

useradd 명령으로 oracle 계정을 등록하고 생성한 계정으로 su 한 뒤 kinit 명령을 실행해준다. 이 과정에서 KDC 인증서버에 등록한 프린서플(principal)을 확인하고 커버로스 티켓을 발급받아본다. klist 명령으로 발급된 티켓을 확인할 수 있다. 이 상태가 되면 SSH 클라이언트 툴을 통해 서버에 커버로스 인증을 받아 접속할 수 있다.
생성한 oracle 계정에 운영체제 비밀번호는 만들어 주지 않아도 된다. 즉 /etc/shadow 파일에 oracle 계정의 비밀번호는 없어야 한다.

커버로스 인증을 통해 접속한 화면. 화면상으로는 커버로스 인증인지 아닌지 알기 어렵다.

그리고 계정의 비밀번호는 kpasswd 명령을 통해 변경할 수 있는데.. 먼저 비밀번호 관련 규칙도 다음과 같이 확인할 수 있다.

비밀번호 변경주기를 120일로…. 비밀번호 최소길이를 8자로 수정하고 비밀번호의 최소 캐릭터 클래스를 1로 수정하였다.
kpasswd 명령으로 변경한 화면이다. 만약 passwd 명령을 실행한다면 자동으로 커버로스의 비밀번호를 변경한다.

완료..!!
#커버로스 #커버로스인증 #커버로스인증서버구축