Active Directory의 LDAP 서비스는 기본적으로 389번 포트를 사용한다.

그런데 CA를 설치하고 웹 서버 인증서만 발급 받아 설치하면 자동으로 SSL이 활성화된다.

(특별히 Active Directory Domain Service 서비스에 인증서를 설치하면 해당 인증서가 사용된다.)


>> 참조: https://msdn.microsoft.com/en-us/library/cc725767(v=ws.10).aspx




1. 들어가며...


이제 내 글 좀 읽어본 사람이면 숫자 1이 딱 보이는 순간,

아놔 또 졸~ 길게 늘어난 글이구나, 라는 것을 아셨으리라.

맞다. 그러니 긴 글 울렁증이 있는 분들은 "뒤로 가기(Back)" 클릭! 클릭, 클릭!!!




아무튼 본론으로 들어가면,


Active Directory LDAP over SSL은 기본적으로 636번 포트를 사용하며,


.NET Framework에서 DirectoryEntry를 사용할 경우에는

- 명시적으로 636번 포트를 지정하고,

- 인증 형태를 AuthenticationTypes.SecureSocketsLayer로 지정하는 이중 작업을 해야 한다.


Java에서 기본 JNDI를 사용해서 LDAP over SSL을 사용할 때는

Context.SECURITY_PROTOCOL을 "ssl"로만 지정해 주면 자동으로 사용 포트가 636번이 된다.




2. LDAP over SSL: 인증서


사설 인증서 기반의 LDAP over SSL은 몇 가지 설정이 더 필요하다.


요약하자면,


Java에서는 사설 인증서 CA 인증서를 keystore에 설치하고 cacerts 목록에 추가해야 하며,


.NET 또는 Windows에서는 신뢰할 수 있는 인증 기관 목록에 CA 인증서를 설치해야 하는 것은 기본이고

인증서 주체(Subject)나 주체 대체 이름(SAN)이 실제 호출하는 FQDN과 다른 경우에는

아래와 같이 연결이 되지 않는 문제가 여전히 발생한다.



Ldp.exe를 이용하여 연결을 해 봐도 안 되고,




이벤트 로그를 보면 위와 같이 Schannel 36884 오류가 발생하게 된다.


이 경우에는 인증서의 주체 혹은 주체 대체 이름을 확인해서

호출 가능한 FQDN이나 IP주소인 경우 클라이언트 측에서 그것으로 변경하여 호출해야 한다.

(또는 편법으로 클라이언트 PC에서 무시하도록 만드는 방법도 있다. 그건 조금 아래에...)


인증서는 보통 웹 서버 인증서를 설치한 경우, 인증서의 용도가 "서버 인증"이 되며

Active Directory는 서버에 설치된 인증서 중 우선 순위(알파벳?)에 따라 하나만 선택하여 사용한다.

따라서 설치된 웹 서버 인증서가 하나만 있는 경우에는 그것이 곧 LDAP SSL 인증서라 보면 된다.




3. 인증서 확인 방법


실제 인증서를 확인하는 방법은 아래와 같다.

먼저, OpenSSL 도구를 이용하는 방법.


>> 참조(Win32/64용 다운로드): http://slproweb.com/products/Win32OpenSSL.html



위 그림과 같이


openssl s_client -connect {ldap server}:636


의 형식으로 openssl 명령을 실행하면 Base64로 인코딩된 PEM 형식의 인증서가 나오고

그 아래로 주체(subject)가 표시된다. 맨 뒤의 "CN=" 뒤에 있는 것이 실제 이름이다.

(위 예시처럼 *.domain.com과 같은 와일드 카드 인증서인 경우에는 실제 호출이 불가능한 주체 이름이므로

인증서 자체를 바꾸는 편이 더 나을 수도 있다...)


또는, 아래에 다시 소개할 Java 도구 Portecle을 사용해서 

{ldap server}와 포트 636를 입력하면 인증서 정보가 바로 보이므로 유용하게 사용할 수 있다.


>> 참조: https://sourceforge.net/projects/portecle/files/latest/download





다른 편법으로,

아래와 같이 클라이언트에서 인증서 이름 대신 호스트 이름을 사용하도록 설정을 바꾸는 방법도 있다.


>> 참조: https://support.microsoft.com/ko-kr/kb/2275950



LDAP over SSL 연결할 때 인증서 주체나 주체 대체 이름 대신 실제 호스트 이름(FQDN)을 사용해도

오류를 발생하지 않고 정상 연결되도록 해 주는 팁이다.




레지스트리 위치는 아래와 같다:


HKLM\SYSTEM\CurrentControlSet\Services\ldap: UseHostnameAsAlias - REG_DWORD(32bit): 1



위 URL에서는 Windows 7 혹은 Windows Server 2008 R2만 해당된다고 나와 있는데

내 Windows 10에서도 잘 되는 것으로 보아 Windows 7 이상에서는 아무 환경에서나 다 되는 것 같다.


내 PC에서 위 편법 레지스트리 적용을 한 다음 재부팅 후 다시 Ldp로 접속해 봤다.




성공.



그렇지만, 어디까지나 이것은 편법으로,

정상적으로 되게 하려면 역시

서버의 인증서를 실제 접속이 가능한 FQDN이 주체 이름으로 된 것으로 교체하는 것이 낫다.

클라이언트마다 일일이 설정을 바꾸고 재부팅해야 하는 상황을 겪지 않으려면.




4. Java: Portecle


Java의 Portecle 도구를 사용하여 LDAP over SSL을 사용할 수 있도록

클라이언트에 CA 인증서를 설치하는 방법은 아래에 잘 나와 있다.


>> 참조: https://www.lesstif.com/pages/viewpage.action?pageId=12451848



위 URL에서 아래로 스크롤해서 내리면 나오는 "GUI 사용" 부분을 참조하면 되는데,

한 가지 잘못 나와 있는 것은, 저렇게 하면 안되고,

서버 인증서가 아닌, 아래에 쓴 것처럼 CA 인증서를 다운로드 받아야 한다는 점이다.




여기를 클릭해서,




여기까지... 접속하는 것까지는 똑같은데,




여기서부터 다르다. "PEM Encoding"을 바로 클릭하는 것이 아니라 "Extensions"를 클릭하고,




이런 창이 나타나면 아래에 있는 "CA issuers" 목록 중에서

위의 링크(정확히는 "AIA"가 포함되지 않은 것)를 클릭하면,




다시 위와 같은 인증서 창이 나타난다. 이것이 바로 다운로드해야 할 CA 인증서가 되겠다.

여기서 "PEM Encoding" 버튼을 클릭해서...




"Save"를 클릭하는 것 이후로는 위 URL에 있는 방법을 그대로 따르면 된다.




5. Active Directory: SetPassword


여기서부터는 LDAP over SSL과 크게 관계없는 부가 내용.


Active Directory에서 ChangePassword를 호출할 때는 별다른 제약이 없다.

그런데 SetPassword를 호출하려면 기본적으로 AuthenticationTypes.Secure 플래그가 필요하다.

즉, Kerberos 인증이 필요하다는 의미이다.


>> 참조: AuthenticationTypes 열거형




Kerberos 인증은 동일 도메인에 소속된 컴퓨터에서만 가능한 인증 메커니즘으로,

도메인에 소속되지 않은 컴퓨터에서는 설정 자체가 불가능한 옵션이다.


한 가지 더,

불행히도 도메인 컨트롤러 서버 로컬 ASP.NET 환경에서는 이 Kerberos 인증 옵션을 사용할 수 없다.

따라서 AuthenticationTypes.Secure 플래그는 도메인 컨트롤러 로컬 환경에서는 지정하면 안 된다.

(이게 Windows 버전에 따라 됐다 안됐다 하는데, 최신 Windows 2012 R2 환경에서는 확실히 안 된다.)




그렇다면 도메인 컨트롤러 로컬 ASP.NET에서 SetPassword를 정상적으로 실행하려면?


AuthenticationTypes.SecureSocketsLayer 옵션을 지정하거나(이것도 안될 수 있다... 안 해봤음),

그냥 AuthenticationTypes.Secure나 AuthenticationTypes.SecureSocketsLayer 등을 빼고

일반 LDAP 연결 옵션(AuthenticationTypes.ServerBind 등)으로 그냥 사용하면 된다.


엥? 그냥?


그렇다.

아마도 Windows 2012 R2 이상 도메인 컨트롤러 로컬에서 실행되는 경우(ApplicationPoolIdentity)에는

기본적으로 로컬 LDAP 연결 시 Kerberos 인증 이상의 보안 설정이 적용되도록 바뀐 모양이다...

확인되지 않았고, 확인할 방법도 없지만.

(알게 모르게 Windows 시스템도 내부적으로 이런 자질구레한 부분에서 변경이 자주 된다......)



물론, SetPassword를 원격에서 호출할 때 도메인에 소속되지 않은, 즉 Secure가 아닌 환경에서도

무리 없이 호출되도록 하는 편법은 있다. 바로 dsHeuristics 값을 조절하는 방법이다.

그것이 필요한 경우에는 아주 예전에 쓴 아래 글을 참조하면 되겠다.


>> 참조: http://thermidor.tistory.com/63




6. 이전 Password: 인증 캐시


Active Directory는 ChangePassword를 호출하여 Password가 변경된 이후에도

기본적으로 이전 Password를 사용해도 정상적으로 로그인이 된다.


이는 도메인 컨트롤러가 Offline인 경우, 또는 원격에서 도메인 컨트롤러에 연결되지 않은 경우에도

일시적으로 로컬 로그인이 가능하도록 하기 위한 보조 장치인데...


이 값은 기본적으로 50으로 정해져 있다.


즉, 최대 50회 인증을 하는 동안에는 기존 로그인된 기록이 기억되고 있기 때문에

이전 Password를 사용해도 인증이 되는 것이다.

(Active Directory가 LDAP에서 검색하기 전에 인증 캐시에 있으면 그것을 먼저 사용하기 때문이다.)


이 설정이 불필요한 경우에는 아래와 같이 정책을 조정해서 인증 캐시를 사용하지 않고

매번 LDAP에서 검색/인증되도록 할 수 있다.


>> 참조: https://technet.microsoft.com/en-us/library/cc755473(v=ws.10).aspx





위와 같이 그룹 정책 개체 편집기로 Default Domain Policy를 연 다음,

[컴퓨터 구성] - [Windows 설정] - [보안 설정] - [로컬 정책] - [보안 옵션]으로 이동하여

"대화형 로그온: 캐시할 로그온 횟수(도메인 컨트롤러를 사용할 수 없는 경우)" 값을 설정하면 된다.




이 값을 "0"으로 설정하면 인증 캐시가 사용되지 않게 되어 항상 최신 Password로만 인증된다.



위험: 이 값이 0이면, 항상 도메인 컨트롤러에서 LDAP 검색을 하게 되므로

도메인 컨트롤러와 연결이 되지 않는 환경에서는 인증이 불가능한 상태가 된다.




이상, 오늘의 Active Directory 검토 끝.





Posted by 떼르미
,


자바스크립트를 허용해주세요!
Please Enable JavaScript![ Enable JavaScript ]