NGINX Plus와 NGINX를 사용하여 LDAP로 애플리케이션 사용자 인증하기

관리자
조회수 294

고객들은 NGINX Plus 및 NGINX를 사용하여 요청하는 사용자를 인증하여 보호된 리소스 또는 애플리케이션을 보호하는 방법에 대해 자주 문의합니다. 오늘 저희는 이러한 인증 시스템의 레퍼런스 구현을 발표하고, GitHub의 NGINX, Inc. 리포지토리에서 이를 사용할 수 있도록 공개합니다. 이 게시물에서는 구현의 작동 방식, 설치 방법 및 자체 인증 시스템의 모델로 사용하는 방법에 대해 설명합니다.
.

이 솔루션은 외부 서비스에 인증 요청을 전달하는 NGINX 및 NGINX의 ngx_http_auth_request_module 모듈을 활용합니다. 참조 구현에서 이 서비스는 ldap-auth라고 부르는 데몬입니다. 파이썬으로 작성되었으며 기본적으로 경량 디렉터리 액세스 프로토콜(LDAP) 인증 서버인 OpenLDAP와 통신하지만, Microsoft® Windows® Server Active Directory의 기본 구성(2003 및 2012 버전 모두)에 대해서도 ldap-auth 데몬을 테스트했습니다.

ldap-auth 디먼은 다른 언어로 작성하거나 다른 인증 시스템과 함께 배포하거나 둘 다 사용할 수 있는 자체 "커넥터" 앱의 모델 역할을 합니다. NGINX 전문 서비스 팀에서 이러한 적응을 지원합니다.

주:

  • 이 참조 구현은 프로덕션 용도가 아니라 자체 구현을 위한 모델로만 사용됩니다.
  • 읽기 쉽도록 이 글의 나머지 부분에서는 NGINX Plus를 참조하지만 참조 구현은 NGINX 오픈 소스에서도 작동합니다. 전제 조건인 http_auth_request 모듈은 NGINX Plus 패키지와 사전 빌드된 NGINX 바이너리 모두에 포함되어 있습니다.


참조 구현에서 인증이 작동하는 방식


인증을 수행하기 위해 http_auth_request 모듈은 중개자 역할을 하고 

LDAP 서버에 대한 하위 요청을 해석하는 ldap-auth 데몬에 HTTP 하위 요청을 생성합니다. 

이 모듈은 NGINX와의 통신을 위해 HTTP를 사용하고 LDAP 서버와의 통신을 위해 적절한 API를 사용합니다.

참조 구현에 관심이 있는 경우 인증을 요구하여 보호하려는 애플리케이션이나 기타 리소스가 이미 있다고 가정합니다. 

그러나 참조 구현을 더 쉽게 테스트할 수 있도록 포트 9000에서 수신 대기하는 Python으로 작성된 샘플 백엔드 데몬을 제공합니다. 

이 데몬은 사용자 자격 증명을 묻고 이를 기반으로 쿠키를 생성하여 테스트 중에 실제 HTTP 애플리케이션을 대신할 수 있습니다.


The NGINX Plus reference implementation for LDAP authentication includes the ldap-auth daemon and a sample backend daemon


다음은 참조 구현의 인증 프로세스에 대한 단계별 설명입니다. 

자세한 내용은 nginx-ldap-auth.conf 구성 파일의 설정에 따라 결정됩니다. 

아래 참조 구현 구성하기를 참조하세요. 아래 단계별 순서도에 프로세스가 요약되어 있습니다.

클라이언트가 NGINX Plus가 역방향 프록시 역할을 하는 서버에서 호스팅되는 보호된 리소스에 대한 HTTP 요청을 보냅니다.

NGINX Plus(특히 http_auth_request 모듈)는 자격 증명이 제공되지 않았기 때문에 


HTTP 코드 401로 응답하는 ldap-auth 데몬으로 요청을 전달합니다.

  1. NGINX Plus는 백엔드 데몬에 해당하는 http://backend/login 으로 요청을 전달합니다. 백엔드 데몬은 전달된 요청의 X-Target 헤더에 원본 요청 URI를 씁니다.

  2. 백엔드 데몬은 클라이언트에 로그인 양식을 보냅니다(양식은 데몬의 Python 코드에 정의되어 있음). error_page 지시어에 의해 구성된 대로 NGINX는 로그인 양식의 HTTP 코드를 200으로 설정합니다.

  3. 사용자는 양식의 사용자 이름 및 비밀번호 필드를 채우고 로그인 버튼을 클릭합니다. 양식의 코드에 따라 클라이언트는 /login으로 향하는 HTTP POST 요청을 생성하고, NGINX Plus는 이를 백엔드 데몬으로 전달합니다.

  4. 백엔드 데몬은 사용자 이름:비밀번호 형식의 문자열을 생성하고 Base64 인코딩을 적용하고 인코딩된 문자열로 값이 설정된 nginxauth라는 쿠키를 생성하여 클라이언트로 쿠키를 보냅니다. 쿠키를 읽거나 조작하기 위해 JavaScript를 사용하지 못하도록 httponly 플래그를 설정합니다(크로스 사이트 스크립팅[XSS] 취약점으로부터 보호).

  5. 클라이언트는 원래 요청(1단계에서)을 재전송하며, 이번에는 HTTP 헤더의 쿠키 필드에 쿠키를 포함합니다. NGINX Plus는 요청을 ldap-auth 디먼으로 전달합니다(2단계에서와 같이).

  6. ldap-auth 디먼은 쿠키를 디코딩하고 사용자 이름과 비밀번호를 인증 요청으로 LDAP 서버에 보냅니다.

  7. 다음 작업은 LDAP 서버가 사용자를 성공적으로 인증했는지 여부에 따라 달라집니다:  

  1. 인증에 성공하면 ldap-auth 디먼이 HTTP 코드 200을 NGINX Plus로 전송합니다. 
  2. NGINX Plus는 백엔드 데몬에서 리소스를 요청합니다. 참조 구현에서 백엔드 데몬은 다음 텍스트를 반환합니다:
Hello, world! Requested URL: URL


레퍼런스 구현 구성

nginx-ldap-auth.conf 파일에서 다음을 변경합니다. 표시된 대로 일부는 필수 항목이고 일부는 선택 항목입니다.

인증 시도 결과를 캐싱하기 위한 지시어가 nginx-ldap-auth.conf 파일에 포함되어 있습니다. 캐싱을 사용하지 않으려면 아래 캐싱을 참조하십시오.

  • 인증에 실패하면 ldap-auth 데몬은 HTTP 코드 401을 NGINX Plus로 보냅니다. NGINX Plus는 요청을 다시 백엔드 데몬으로 전달하고(3단계에서와 같이), 프로세스가 반복됩니다.

  1. In the NGINX Plus reference implementation for LDAP authentication, the ldap-auth daemon is the intermediary between NGINX Plus and the LDAP server

구성 요소 설치
  • 참조 구현과 함께 배포된 NGINX Plus 구성 파일인 nginx-ldap-auth.conf는 테스트 목적에 적합한 동일한 호스트에서 실행되도록 LDAP 서버를 제외한 모든 구성 요소(즉, NGINX Plus, 클라이언트, ldap-auth 데몬 및 백엔드 데몬)를 구성합니다. 테스트 중에 해당 호스트에서 LDAP 서버를 실행할 수도 있습니다.
  • 실제 배포에서는 일반적으로 백엔드 애플리케이션과 인증 서버가 각각 별도의 호스트에서 실행되고 NGINX Plus는 세 번째 호스트에서 실행됩니다. ldap-auth 데몬은 대부분의 상황에서 많은 리소스를 소비하지 않으므로 NGINX Plus 호스트 또는 사용자가 선택한 다른 호스트에서 실행할 수 있습니다.

  • GitHub 리포지토리의 복제본을 생성합니다.

  • NGINX Plus가 아직 실행 중이 아니라면 운영 체제별 지침에 따라 설치합니다.

  • LDAP 서버가 아직 실행 중이 아니라면 설치 및 구성합니다. 기본적으로 ldap-auth 디먼은 OpenLDAP와 통신하지만 Microsoft Windows Active Directory 2003 및 2012도 지원됩니다.

    참조 구현을 테스트하기 위해서만 LDAP 서버를 사용하는 경우에는 GitHub에서 제공되는 OpenLDAP 서버 Docker 이미지를 사용하거나 Ubuntu 16.04에서 OpenLDAP 설치 및 구성 방법 및 phpLDAPadmin과 같은 지침을 사용하여 서버를 설정할 수 있습니다.

    기본 DN, 바인드 DN, 바인드 비밀번호에 설정한 값을 메모해 두세요. 참조 구현 구성하기의 NGINX 구성 파일에 해당 값을 입력합니다.

  • ldap-auth 디먼을 실행할 호스트에 다음 추가 소프트웨어를 설치합니다. 오픈 소스 리포지토리에서 소프트웨어를 다운로드하는 대신 운영 체제와 함께 배포되는 버전을 사용하는 것이 좋습니다.

    • Python 버전 2. 버전 3은 지원되지 않습니다.
    • Python LDAP 모듈인 python-ldap(python-ldap.org 오픈 소스 프로젝트에서 생성).
  • 리포지토리 복제본에서 지정된 호스트로 다음 파일을 복사합니다:

  • nginx-ldap-auth.conf - 참조 구현 테스트를 위한 최소한의 지시어 집합을 포함하는 NGINX Plus 구성 파일. NGINX Plus 호스트(기존 구성 체계를 사용하는 경우 /etc/nginx/conf.d 디렉토리에)에 설치합니다. 구성 충돌을 방지하려면 NGINX Plus와 함께 설치된 기본 구성 파일을 이동하거나 이름을 변경해야 합니다.

    • nginx-ldap-auth-daemon.py - ldap-auth 데몬을 위한 Python 코드. 원하는 호스트에 설치하세요.
    • nginx-ldap-auth-daemon-ctl.sh - 데몬을 시작 및 중지하기 위한 샘플 셸 스크립트. ldap-auth 데몬과 동일한 호스트에 설치합니다.
    • backend-sample-app.py - 테스트 중에 백엔드 애플리케이션 서버를 대신하는 데몬용 Python 코드입니다. 원하는 호스트에 설치합니다.
  • 아래의 참조 구현 구성에 설명된 대로 NGINX Plus 구성 파일을 수정합니다. 변경한 후 nginx -t 명령을 실행하여 파일이 구문적으로 유효한지 확인합니다.

root# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful

NGINX Plus를 시작합니다. NGINX Plus가 이미 실행 중인 경우 다음 명령을 실행하여 구성 파일을 다시 로드합니다:

root# nginx -s reload

적절한 호스트에서 다음 명령을 실행하여 ldap-auth 데몬과 백엔드 데몬을 시작합니다.

root# nginx-ldap-auth-daemon-ctl.sh start
root# python backend-sample-app.py

웹 브라우저를 사용하여 http://nginx-server-address:8081 에 접속합니다. 브라우저에 인증 양식이 표시되는지 확인합니다. 양식을 작성하고 제출한 후 서버에서 유효한 자격 증명에 대한 예상 응답이 반환되는지 확인합니다. 위에서 언급했듯이 백엔드 데몬은 다음 텍스트를 반환합니다:

Hello, world! Requested URL: URL

참조 구현 구성

nginx-ldap-auth.conf 파일을 다음과 같이 변경합니다. 표시된 대로 일부는 필수이고 일부는 선택 사항입니다.

LDAP 서버 설정
nginx-ldap-auth-daemon.py에 구현된 대로, 
ldap-auth 데몬은 인증할 사용자 계정을 지정하는 파라미터를 전달하여 
OpenLDAP 서버와 통신합니다. Python 코드를 수정할 필요가 없도록 
nginx-ldap-auth.conf 파일에는 매개 변수를 설정하는 데 
사용되는 HTTP 헤더의 값을 설정하는 proxy_set_header 지시어가 포함되어 있습니다. 
다음 표는 파라미터와 헤더를 매핑합니다.

LDAP ParameterHTTP Header
  • basedn
  • X-Ldap-BaseDN
  • binddn
  • X-Ldap-BindDN
  • bindpasswd
  • X-Ldap-BindPass
  • cookiename
  • X-CookieName
  • realm
  • X-Ldap-Realm
  • template
  • X-Ldap-Template
  • url
  • X-Ldap-URL

(필수) 다음 지시어에서 굵게 표시된 값을 LDAP 서버 배포에 맞는 올바른 값으로 바꿉니다. 특히 nginx-ldap-auth.conf 파일은 LDAPS에 잘 알려진 포트인 636을 사용한다는 점에 유의하세요. 포트를 389(LDAP에 잘 알려진 포트) 또는 다른 LDAP 포트로 변경하는 경우 프로토콜 이름도 ldaps에서 ldap으로 변경해야 합니다.

# URL and port for connecting to the LDAP server proxy_set_header X-Ldap-URL "ldaps://example.com:636"; # Base DN proxy_set_header X-Ldap-BaseDN "cn=Users,dc=test,dc=local"; # Bind DN proxy_set_header X-Ldap-BindDN "cn=root,dc=test,dc=local"; # Bind password proxy_set_header X-Ldap-BindPass "secret";

(OpenLDAP 대신 Active Directory를 사용하는 경우 필수) 그림과 같이 다음 지시문을 주석 처리합니다:

proxy_set_header X-Ldap-Template "(SAMAccountName=%(username)s)";

(선택 사항) 참조 구현은 쿠키 기반 인증을 사용합니다. 대신 HTTP 기본 인증을 사용하는 경우 다음 지시어를 다음과 같이 주석 처리하세요:

#proxy_set_header X-CookieName "nginxauth";
#proxy_set_header Cookie nginxauth=$cookie_nginxauth;

(선택 사항) ldap-auth 디먼이 기본적으로 OpenLDAP 서버에 전달하는 템플릿 파라미터의 값을 변경하려면 그림과 같이 다음 지시어의 주석 처리를 해제하고 값을 변경합니다:

proxy_set_header X-Ldap-Template "(cn=%(username)s)";

(선택 사항) 영역 이름을 기본값(제한됨)에서 변경하려면 다음 지시문의 주석 처리를 해제하고 변경합니다:

proxy_set_header X-Ldap-Realm "Restricted";

백엔드 데몬의 IP 주소

백엔드 데몬이 NGINX Plus와 동일한 호스트에서 실행되지 않는 경우, 업스트림 구성 블록에서 해당 데몬의 IP 주소를 변경합니다.
upstream backend {    server 127.0.0.1:9000; }

ldap-auth 데몬의 IP 주소

ldap-auth 디먼이 NGINX Plus와 동일한 호스트에서 실행되지 않는 경우, 이 proxy_pass 지시어에서 IP 주소를 변경합니다:
location = /auth-proxy {    proxy_pass http://127.0.0.1:8888;    # ... }

IP Address and Port on Which NGINX Listens

클라이언트가 NGINX와 동일한 호스트에서 실행되지 않는 경우 이 'listen '지시어에서 IP 주소를 변경하거나 주소를 완전히 제거하여 모든 클라이언트로부터 트래픽을 허용합니다. 원하는 경우 NGINX가 8081에서 수신 대기하는 포트를 변경할 수도 있습니다:

server {    listen 127.0.0.1:8081;    # ... }

Caching

nginx-ldap-auth.conf 파일을 사용하면 데이터와 자격 증명을 모두 캐싱할 수 있습니다. 

선택적으로 다음 설정을 변경할 수 있습니다:

http 구성 블록의 proxy_cache_path 지시어는 캐시라는 로컬 디스크 디렉토리를 생성하고 


메타데이터가 저장되는 auth_cache라는 영역에 공유 메모리에 10MB를 할당합니다.

proxy_cache_path cache/ keys_zone=auth_cache:10m;

공유 메모리 영역의 이름을 변경하는 경우, (트래픽을 ldap-auth 데몬으로 보내는 위치 블록에 있는) proxy_cache 지시어에서도 변경해야 합니다.

location = /auth-proxy {    proxy_cache auth_cache;    # ... }

proxy_cache_valid 지시어(proxy_cache와 동일한 위치 블록에 있음)는 HTTP 코드 200 또는 403으로 

표시된 캐시된 응답이 10분 동안 유효하도록 지정합니다.

location = /auth-proxy {    proxy_cache_valid 200 403 10m;    # ... }
캐싱을 사용하지 않으려면 이 세 가지 지시어와 proxy_cache_key 지시어를 주석 처리합니다.

인증 시스템 사용자 정의

위에서 언급했듯이 ldap-auth 데몬을 http_auth_request 모듈의 요청을 수락하는 자체 애플리케이션의 모델로 사용할 수 있습니다. 다른(LDAP가 아닌) 유형의 인증 서버와 통신하기 위해 Python으로 앱을 작성하는 경우 nginx-ldap-auth-daemon.py 스크립트에서 LDAPAuthHandler를 대체할 새 인증 핸들러 클래스를 작성하세요.

보안에 대한 참고 사항

백엔드 데몬은 쿠키의 사용자 아이디와 비밀번호에 Base64 인코딩을 사용합니다. Base64는 매우 약한 형태의 스크램블링으로, 자격 증명을 추출하고 오용하기 쉽습니다. 인증이 실제 목적을 달성하려면 백엔드 애플리케이션에서 보다 정교한 암호화를 사용해야 합니다.



위 내용와 같이 NGINX Plus를 활용하여 Demo 가 필요하시면 하단의 전문가에게 상담받기 버튼을 클릭해주세요