고객들은 NGINX Plus와 NGINX를 사용하여 보호된 리소스나 애플리케이션에 접근을 요청하는 사용자를 인증하고 이를 안전하게 보호하는 방법을 자주 문의합니다. 오늘 이러한 인증 시스템의 참조 구현을 발표하고 NGINX, Inc.의 GitHub 리포지토리에서 공개합니다. 이 게시물에서는 이 구현의 작동 방식과 설치 방법, 그리고 자체 인증 시스템을 구축할 때 모델로 활용하는 방법을 설명합니다.
이 솔루션은 NGINX Plus와 NGINX의 ngx_http_auth_request_module 모듈을 활용하여 인증 요청을 외부 서비스로 전달합니다. 참조 구현에서 이 서비스는 ldap‑auth라고 하는 데몬입니다. 이 데몬은 Python으로 작성되었으며 LDAP(Lightweight Directory Access Protocol) 인증 서버와 통신합니다. 기본적으로 OpenLDAP을 사용하지만, Microsoft® Windows® Server Active Directory의 기본 구성(2003 및 2012 버전 모두)을 대상으로도 ldap‑auth 데몬을 테스트했습니다.
ldap‑auth 데몬은 자체 “커넥터” 앱을 개발할 때 참고할 수 있는 모델로, 다른 언어로 작성하거나 다른 인증 시스템과 함께 배포하거나 두 가지 모두를 적용할 수 있습니다. NGINX Professional Services 팀은 이러한 맞춤 적용을 지원합니다.
참고:
- 참조 구현은 프로덕션 환경에서 사용하기 위한 것이 아니라, 자체 구현을 위한 모델로만 제공됩니다.
- 읽기 쉽도록 이 글의 나머지 부분에서는 NGINX Plus를 기준으로 설명하지만, 참조 구현은 NGINX Open Source에서도 작동합니다. 필수 구성 요소인 http_auth_request 모듈은 NGINX Plus 패키지와 사전 빌드된 NGINX 바이너리에 모두 포함되어 있습니다.
참조 구현에서 인증이 작동하는 방식
인증을 수행하기 위해 http_auth_request 모듈은 ldap‑auth 데몬에 HTTP 하위 요청을 보냅니다. 이 데몬은 중개자 역할을 하며 LDAP 서버에 맞게 하위 요청을 해석합니다. NGINX Plus와 통신할 때는 HTTP를 사용하고, LDAP 서버와 통신할 때는 적절한 API를 사용합니다.
참조 구현에 관심이 있다면 인증을 요구하여 보호하려는 애플리케이션이나 기타 리소스가 이미 있다고 가정합니다. 하지만 참조 구현을 더 쉽게 테스트할 수 있도록 Python으로 작성되고 포트 9000에서 수신 대기하는 샘플 백엔드 데몬을 제공합니다. 이 데몬은 사용자에게 자격 증명을 입력하라는 메시지를 표시하고 이를 기반으로 쿠키를 생성하여 테스트 중에 실제 HTTP 애플리케이션을 대신할 수 있습니다.

다음은 참조 구현의 인증 프로세스를 단계별로 설명한 내용입니다. 세부 사항은 nginx-ldap-auth.conf 구성 파일의 설정에 따라 결정됩니다. 아래의 참조 구현 구성을 참조하세요. 단계 아래의 순서도에는 이 프로세스가 요약되어 있습니다.
- 클라이언트가 NGINX Plus가 리버스 프록시로 작동하는 서버에서 호스팅되는 보호된 리소스에 HTTP 요청을 보냅니다.
- NGINX Plus(구체적으로는 http_auth_request 모듈)는 요청을 ldap‑auth 데몬으로 전달하며, 이 데몬은 자격 증명이 제공되지 않았으므로 HTTP 코드
401로 응답합니다. - NGINX Plus는 요청을 http://backend/login으로 전달하며, 이 주소는 백엔드 데몬에 해당합니다. NGINX Plus는 원래 요청 URI를 전달된 요청의
X-Target헤더에 기록합니다. - 백엔드 데몬은 클라이언트에 로그인 양식을 전송합니다(이 양식은 데몬의 Python 코드에 정의되어 있습니다).
error_page지시문에 구성된 대로 NGINX는 로그인 양식의 HTTP 코드를200으로 설정합니다. - 사용자가 양식의 사용자 이름 및 비밀번호 필드를 입력하고 로그인 버튼을 클릭합니다. 양식의 코드에 따라 클라이언트는
POST방식의 HTTP 요청을 /login으로 전송하며, NGINX Plus는 이 요청을 백엔드 데몬으로 전달합니다. - 백엔드 데몬은 다음 형식의 문자열을 생성하고
username:password에 Base64 인코딩을 적용한 다음, nginxauth라는 쿠키를 생성하여 해당 값을 인코딩된 문자열로 설정하고 클라이언트에 전송합니다. 또한 JavaScript를 사용하여 쿠키를 읽거나 조작하지 못하도록httponly플래그를 설정합니다. 이를 통해 크로스 사이트 스크립팅[XSS] 취약점을 방지합니다. - 클라이언트는 원래 요청(1단계에서 보낸 요청)을 다시 전송하며, 이번에는 HTTP 헤더의
Cookie필드에 쿠키를 포함합니다. NGINX Plus는 요청을 ldap-auth 데몬으로 전달합니다(2단계와 동일). - ldap‑auth 데몬은 쿠키를 디코딩하고 인증 요청을 통해 사용자 이름과 비밀번호를 LDAP 서버로 전송합니다.
- 다음 작업은 LDAP 서버가 사용자를 성공적으로 인증했는지 여부에 따라 달라집니다:
- 인증에 성공하면 ldap‑auth 데몬이 HTTP 코드
200을 NGINX Plus로 전송합니다. NGINX Plus는 백엔드 데몬에 리소스를 요청합니다. 참조 구현에서 백엔드 데몬은 다음 텍스트를 반환합니다:
- 인증에 성공하면 ldap‑auth 데몬이 HTTP 코드
Hello, world! Requested URL: URL- nginx-ldap-auth.conf 파일에는 인증 시도 결과를 캐싱하기 위한 지시문이 포함되어 있습니다. 캐싱을 비활성화하려면 아래의 캐싱을 참조하세요.
- 인증에 실패하면 ldap‑auth 데몬은 HTTP 코드
401을 NGINX Plus로 전송합니다. NGINX Plus는 요청을 백엔드 데몬으로 다시 전달하며(3단계와 동일), 이 과정이 반복됩니다.

구성 요소 설치
참조 구현과 함께 배포되는 NGINX Plus 구성 파일인 nginx-ldap-auth.conf는 LDAP 서버를 제외한 모든 구성 요소(즉, NGINX Plus, 클라이언트, ldap‑auth 데몬 및 백엔드 데몬)가 동일한 호스트에서 실행되도록 구성하며, 이는 테스트 용도로 충분합니다. 테스트 중에는 LDAP 서버도 해당 호스트에서 실행할 수 있습니다.
실제 배포 환경에서는 일반적으로 백엔드 애플리케이션과 인증 서버가 각각 별도의 호스트에서 실행되고, NGINX Plus는 세 번째 호스트에서 실행됩니다. ldap-auth 데몬은 대부분의 경우 리소스를 많이 사용하지 않으므로 NGINX Plus 호스트나 원하는 다른 호스트에서 실행할 수 있습니다.
- Create a clone of the GitHub 리포지토리를 복제합니다.
- NGINX Plus가 아직 실행되고 있지 않다면 사용 중인 운영 체제에 대한 지침에 따라 설치합니다.
- LDAP 서버가 아직 실행되고 있지 않다면 설치하고 구성합니다. 기본적으로 ldap‑auth 데몬은 OpenLDAP과 통신하지만 Microsoft Windows Active Directory 2003 및 2012도 지원합니다. 참조 구현을 테스트하는 용도로만 LDAP 서버를 사용하는 경우 GitHub에서 제공되는 OpenLDAP 서버 Docker 이미지를 사용하거나 Ubuntu 16.04에서 OpenLDAP 및 phpLDAPadmin을 설치하고 구성하는 방법과 같은 지침에 따라 서버를 설정할 수 있습니다. 설정한 Base DN, Bind DN 및 Bind 암호 값을 기록해 두십시오. 이 값들은 참조 구현 구성에서 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참조 구현 구성
Make the following changes in the nginx-ldap-auth.conf 파일을 다음과 같이 변경합니다. 표시된 대로 일부 변경 사항은 필수이고 일부는 선택 사항입니다.
LDAP 서버 설정
As implemented in nginx-ldap-auth-daemon.py에 구현된 대로 ldap‑auth 데몬은 OpenLDAP 서버와 통신하면서 인증할 사용자 계정을 지정하는 매개변수를 전달합니다. Python 코드를 수정할 필요가 없도록 nginx-ldap-auth.conf 파일에는 매개변수 설정에 사용되는 HTTP 헤더 값을 지정하는 proxy_set_header 지시문이 포함되어 있습니다. 다음 표는 매개변수와 헤더의 대응 관계를 보여 줍니다.
LDAP 매개변수 HTTP 헤더basedn X-Ldap-BaseDNbinddn X-Ldap-BindDNbindpasswd X-Ldap-BindPasscookiename X-CookieNamerealm X-Ldap-Realmtemplate X-Ldap-Templateurl 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 서버에 전달하는
template매개변수의 값을 변경하려면 다음과 같이 해당 지시문의 주석을 해제하고 값을 변경합니다:
proxy_set_header X-Ldap-Template "(cn=%(username)s)";- (선택 사항) 영역 이름을 기본값(Restricted)에서 변경하려면 다음 지시문의 주석을 해제하고 값을 변경합니다:
proxy_set_header X-Ldap-Realm "Restricted";백엔드 데몬의 IP 주소
백엔드 데몬이 NGINX Plus와 동일한 호스트에서 실행되고 있지 않다면 upstream 구성 블록에서 백엔드 데몬의 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;
# ...
}NGINX가 수신 대기하는 IP 주소 및 포트
클라이언트가 NGINX Plus와 동일한 호스트에서 실행되고 있지 않다면 이 listen 지시문의 IP 주소를 변경하세요(또는 모든 클라이언트의 트래픽을 허용하려면 주소를 완전히 제거하세요). 원하는 경우 NGINX가 수신 대기하는 포트를 8081에서 다른 포트로 변경할 수도 있습니다:
server { listen 127.0.0.1:8081;
# ...
}캐싱
The nginx-ldap-auth.conf 파일을 사용하면 데이터와 자격 증명을 모두 캐시할 수 있습니다. 필요에 따라 다음 설정을 변경할 수 있습니다:
- The
proxy_cache_path지시문은http구성 블록에 cache라는 로컬 디스크 디렉터리를 만들고, 메타데이터가 저장되는 auth_cache라는 영역에 10MB의 공유 메모리를 할당합니다.
proxy_cache_path cache/ keys_zone=auth_cache:10m;- 공유 메모리 영역의 이름을 변경하는 경우,
proxy_cache지시문에서도 해당 이름을 변경해야 합니다(ldap‑auth 데몬으로 트래픽을 전달하는location블록 내).
location = /auth-proxy {
proxy_cache auth_cache;
# ...
}- The
proxy_cache_valid지시어는 (location블록 중proxy_cache와 동일한 블록에서) HTTP 코드가200또는403으로 표시된 캐시 응답이 10분 동안 유효하도록 지정합니다.
location = /auth-proxy { proxy_cache_valid 200 403 10m;
# ...
}캐싱을 비활성화하려면 이 세 지시문과 proxy_cache_key 지시문을 주석 처리하세요.
인증 시스템 사용자 지정
앞서 설명한 것처럼 ldap‑auth 데몬을 http_auth_request 모듈의 요청을 수락하는 자체 애플리케이션의 모델로 사용할 수 있습니다. Python으로 다른 유형의(LDAP이 아닌) 인증 서버와 통신하는 앱을 작성하는 경우, LDAPAuthHandler를 대체할 새 인증 처리기 클래스를 nginx-ldap-auth-daemon.py 스크립트에 작성합니다.
보안 관련 참고 사항
백엔드 데몬은 쿠키의 사용자 이름과 비밀번호를 Base64로 인코딩합니다. Base64는 매우 취약한 난독화 방식이므로 자격 증명이 추출되어 악용될 수 있습니다. 인증이 실질적인 역할을 하도록 하려면 백엔드 애플리케이션에서 더욱 정교한 암호화 방식을 사용해야 합니다.
작성자 소개

관련 블로그 게시물
시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric
이 영상에서는 KubeCon의 NGINX 부스를 찾아가, 저희가 공개한 Kubernetes Gateway API 구현을 살펴봅니다.
F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법
앱 보안을 강화하는 두 가지 방법을 소개합니다. NGINX Management Suite를 통해 WAF 운영에 대한 가시성을 높이고, NGINX App Protect WAF를 활용해 코드형 보안을 구현하는 것입니다.
Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션
개발 주체, 개발 철학, 프로덕션 환경 준비도, 보안 및 지원을 기준으로 어떤 NGINX Ingress 컨트롤러가 가장 적합한지 알아보세요.
진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법
NGINX App Protect Denial of Service(DoS)가 계층 7 DoS 공격을 방어하기 위해 완화 방법을 실시간으로 조정하는 방식을 설명합니다. 정상적인 사용자 행동과 서버 상태에 대한 모델을 생성하여 공격을 나타내는 이상 징후를 감지하고 맞춤형 완화 시그니처를 적용할 수 있습니다.
NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리
NGINX Instance Manager 버전 1.0에는 두 가지 새로운 기능이 도입되었습니다. NGINX 인스턴스에 태그와 사용자 역할을 지정하면 전체 그룹에 구성을 한 번에 적용할 수 있습니다. 인증서 검사는 만료 예정인 인증서를 감지하여 서비스 중단을 방지할 수 있도록 인증서를 교체할 수 있게 해줍니다.
Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유
Netflix가 글로벌 콘텐츠 전송 네트워크인 Open Connect의 스트리밍 미디어 기술로 NGINX를 선택한 이유를 NGINX 개발자 Gleb Smirnoff에게서 알아보세요.