고객들은 NGINX Plus와 NGINX를 사용하여 요청한 사용자를 인증함으로써 보호된 리소스나 애플리케이션을 보호하는 방법에 대해 자주 묻습니다. 오늘 저희는 이러한 인증 시스템의 참조 구현을 발표하고, 이를 GitHub 의 NGINX, Inc. 저장소에서 사용할 수 있도록 공개합니다 . 이 게시물에서는 구현 방법, 설치 방법, 그리고 이를 자체 인증 시스템의 모델로 사용하는 방법을 설명합니다.
이 솔루션은 NGINX Plus 및 NGINX의 ngx_http_auth_request_module 모듈을 활용하여 인증 요청을 외부 서비스로 전달합니다. 참조 구현에서 해당 서비스는 ldap‑auth 라고 하는 데몬입니다. Python으로 작성되었으며 기본적으로 OpenLDAP 인 LDAP(Lightweight Directory Access Protocol) 인증 서버와 통신하지만, Microsoft® Windows® Server Active Directory의 기본 구성(2003 및 2012 버전 모두)에 대해서도 ldap‑auth 데몬을 테스트했습니다.
ldap‑auth 데몬은 다른 언어로 작성하거나, 다른 인증 시스템과 함께 배포하거나, 둘 다를 수행할 수 있는 자체 "커넥터" 앱의 모델 역할을 합니다. NGINX 전문 서비스 팀은 이러한 적응 작업을 도와드립니다.
참고사항:
인증을 수행하기 위해 http_auth_request 모듈은 ldap‑auth 데몬에 HTTP 하위 요청을 만들고, ldap‑auth 데몬은 중개자 역할을 하며 하위 요청을 LDAP 서버에 대한 해석을 담당합니다. NGINX Plus와 통신하려면 HTTP를 사용하고, LDAP 서버와 통신하려면 적절한 API를 사용합니다.
참조 구현에 관심이 있다면 인증을 요구하여 보호하려는 애플리케이션이나 기타 리소스가 이미 있다고 가정합니다. 그러나 참조 구현을 보다 쉽게 테스트할 수 있도록 Python으로 작성되어 포트 9000에서 수신하는 샘플 백엔드 데몬을 제공합니다. 테스트 중에 실제 HTTP 애플리케이션을 대신하여 사용자 자격 증명을 묻고 이를 기반으로 쿠키를 생성할 수 있습니다.
참조 구현의 인증 프로세스에 대한 단계별 설명은 다음과 같습니다. 세부 정보는 nginx-ldap-auth.conf 구성 파일의 설정에 따라 결정됩니다. 아래의 참조 구현 구성을 참조하세요. 각 단계 아래의 흐름도는 과정을 요약한 것입니다.
클라이언트는 NGINX Plus가 역방향 프록시 역할을 하는 서버에 호스팅된 보호된 리소스에 대한 HTTP 요청을 보냅니다.
NGINX Plus(특히 http_auth_request 모듈)는 요청을 ldap‑auth 데몬에 전달하고 ldap‑auth 데몬은 HTTP 코드로 응답합니다.401
자격 증명이 제공되지 않았기 때문입니다.
NGINX Plus는 백엔드 데몬에 해당하는 http://backend/login 으로 요청을 전달합니다. 전달된 요청의 X-Target
헤더에 원래 요청 URI를 작성합니다.
백엔드 데몬은 클라이언트에 로그인 양식을 보냅니다.(양식은 데몬의 Python 코드에 정의되어 있습니다.) error_page
지시문에서 구성된 대로 NGINX는 로그인 양식의 HTTP 코드를 다음과 같이 설정합니다.200
.
사용자는 양식에 사용자 이름과 비밀번호 필드를 입력하고 로그인 버튼을 클릭합니다. 폼의 코드에 따라 클라이언트는 /login 으로 전달되는 HTTP POST
요청을 생성하고, NGINX Plus는 이를 백엔드 데몬으로 전달합니다.
백엔드 데몬은 username : password
형식의 문자열을 구성하고, Base64 인코딩을 적용하고, 인코딩된 문자열로 값이 설정된 nginxauth 라는 쿠키를 생성한 후, 해당 쿠키를 클라이언트로 전송합니다. JavaScript를 사용하여 쿠키를 읽거나 조작하는 것을 방지하기 위해 httponly
플래그를 설정합니다( 교차 사이트 스크립팅[XSS] 취약성으로부터 보호).
클라이언트는 원래 요청(1단계)을 다시 전송하며, 이번에는 HTTP 헤더의 쿠키
필드에 쿠키를 포함합니다. NGINX Plus는 요청을 ldap‑auth 데몬에 전달합니다(2단계와 동일).
ldap‑auth 데몬은 쿠키를 디코딩하고 인증 요청으로 사용자 이름과 비밀번호를 LDAP 서버로 전송합니다.
다음 작업은 LDAP 서버가 사용자를 성공적으로 인증했는지 여부에 따라 달라집니다.
인증이 성공하면 ldap‑auth 데몬은 HTTP 코드를 보냅니다.200
NGINX Plus로. NGINX Plus는 백엔드 데몬에게 리소스를 요청합니다. 참조 구현에서 백엔드 데몬은 다음 텍스트를 반환합니다.
안녕하세요, 세상아! 요청된 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 호스트나 사용자가 선택한 다른 호스트에서 실행할 수 있습니다.
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 데몬을 실행할 호스트에서 다음 추가 소프트웨어를 설치합니다. 오픈 소스 저장소에서 소프트웨어를 다운로드하는 대신, 운영 체제와 함께 배포되는 버전을 사용하는 것이 좋습니다.
저장소 복제본에서 다음 파일을 지정된 호스트로 복사합니다.
아래 참조 구현 구성 에 설명된 대로 NGINX Plus 구성 파일을 수정합니다. 변경한 후 nginx
-t
명령을 실행하여 파일의 구문이 유효한지 확인하세요.
root# nginx -t nginx: 설정 파일 /etc/nginx/nginx.conf 구문은 정상입니다. nginx: 설정 파일 /etc/nginx/nginx.conf 테스트가 성공했습니다.
NGINX Plus를 시작합니다. NGINX Plus가 이미 실행 중이면 다음 명령을 실행하여 구성 파일을 다시 로드합니다.
root# nginx -s 다시 로드
적절한 호스트에서 다음 명령을 실행하여 ldap‑auth 데몬과 백엔드 데몬을 시작합니다.
root# nginx-ldap-auth-daemon-ctl.sh 시작 root# python backend-sample-app.py
웹 브라우저를 사용하여 http:// nginx-server-address :8081 에 접속합니다. 브라우저가 인증 양식을 표시하는지 확인하세요. 양식을 작성하여 제출한 후 서버가 유효한 자격 증명에 대해 예상된 응답을 반환하는지 확인하세요. 위에서 언급한 대로 백엔드 데몬은 다음 텍스트를 반환합니다.
안녕하세요, 세상아! 요청된 URL: 웹 주소
nginx-ldap-auth.conf 파일에서 다음과 같이 변경하세요. 표시된 대로 일부는 필수이고 일부는 선택 사항입니다.
nginx-ldap-auth-daemon.py 에 구현된 대로 ldap‑auth 데몬은 OpenLDAP 서버와 통신하여 매개변수를 전달하여 인증할 사용자 계정을 지정합니다. Python 코드를 수정할 필요성을 없애기 위해 nginx-ldap-auth.conf 파일에는 HTTP 헤더에 값을 설정하는 proxy_set_header
지시문이 포함되어 있으며, 이 값을 사용하여 매개변수를 설정합니다. 다음 표는 매개변수와 헤더를 매핑한 것입니다.
LDAP 매개변수 | HTTP 헤더 |
---|---|
기반 |
X-Ldap-BaseDN |
바인드디앤 |
X-Ldap-BindDN |
바인드패스워드 |
X-Ldap-바인드패스 |
쿠키 이름 |
X-쿠키이름 |
왕국 |
X-Ldap-영역 |
주형 |
X-Ldap-템플릿 |
url |
X-Ldap-URL |
(필수) 다음 지침에서 굵은 글씨로 표시된 값을 LDAP 서버 배포에 맞는 올바른 값으로 바꾸세요. 특히 nginx-ldap-auth.conf 파일은 LDAPS의 잘 알려진 포트인 636을 사용한다는 점에 유의하세요. 포트를 389(LDAP의 잘 알려진 포트) 또는 다른 LDAP 포트로 변경하는 경우 프로토콜 이름도 ldaps
에서 ldap
로 변경해야 합니다.
# LDAP 서버에 연결하기 위한 URL 및 포트 proxy_set_header X-Ldap-URL " ldaps :// example.com :636 "; # 기본 DN proxy_set_header X-Ldap-BaseDN " cn=Users,dc=test,dc=local "; # DN 바인딩 proxy_set_header X-Ldap-BindDN " cn=root,dc=test,dc=local "; # 비밀번호 바인딩 proxy_set_header X-Ldap-BindPass " secret ";
(OpenLDAP 대신 Active Directory를 사용하는 경우 필수) 다음 지시문의 주석 처리를 다음과 같이 제거합니다.
proxy_set_header X-Ldap-Template "(SAMAccountName=%(username)s)";
(선택 사항) 참조 구현은 쿠키 기반 인증을 사용합니다. 대신 HTTP 기본 인증을 사용하는 경우 다음 지침을 주석으로 처리합니다.
# proxy_set_header X-쿠키 이름 "nginxauth"; # 프록시_세트_헤더 쿠키 nginxauth=$cookie_nginxauth;
(선택 사항) ldap‑auth 데몬이 기본적으로 OpenLDAP 서버에 전달하는 템플릿
매개변수 값을 변경하려면 표시된 대로 다음 지시문의 주석 처리를 제거하고 값을 변경합니다.
proxy_set_header X-Ldap-Template " (cn=%(username)s) ";
(선택 사항) 기본값( Restricted )에서 영역 이름을 변경하려면 다음 지시문의 주석 처리를 제거하고 변경하세요.
proxy_set_header X-Ldap-Realm " 제한됨 ";
백엔드 데몬이 NGINX Plus와 동일한 호스트에서 실행되지 않는 경우 업스트림
구성 블록에서 해당 IP 주소를 변경합니다.
업스트림 백엔드 { 서버127.0.0.1 :9000; }
ldap‑auth 데몬이 NGINX Plus와 동일한 호스트에서 실행되지 않는 경우 이 proxy_pass
지시문에서 IP 주소를 변경하세요.
위치 = /auth-proxy { proxy_pass http://127.0.0.1 :8888; # ... }
클라이언트가 NGINX Plus와 동일한 호스트에서 실행되지 않는 경우 이 수신
지시문에서 IP 주소를 변경합니다(또는 모든 클라이언트의 트래픽을 허용하려면 주소를 완전히 제거합니다). 원하는 경우 NGINX가 수신하는 포트를 8081에서 변경할 수도 있습니다.
서버 { 듣기127.0.0.1 :8081 ; # ... }
nginx-ldap-auth.conf 파일은 데이터와 자격 증명을 모두 캐싱할 수 있도록 합니다. 선택적으로 다음 설정을 변경할 수 있습니다.
http
구성 블록의 proxy_cache_path
지시문은 cache 라는 로컬 디스크 디렉터리를 생성하고, 메타데이터가 저장되는 auth_cache 라는 영역에 대해 공유 메모리에 10MB를 할당합니다.
proxy_cache_path 캐시/ 키_존= auth_cache : 10m ;
공유 메모리 영역의 이름을 변경하는 경우 proxy_cache
지시문(트래픽을 ldap‑auth 데몬으로 전달하는 위치
블록)에서도 이름을 변경해야 합니다.
위치 = /auth-proxy { proxy_cache auth_cache ; # ... }
proxy_cache_valid
지시문( proxy_cache
와 동일한 위치
블록에 있음)은 HTTP 코드로 표시된 캐시된 응답을 지정합니다.200
또는403
10분간 유효합니다.
위치 = /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는 매우 취약한 형태의 스크램블링으로, 자격 증명이 추출되고 오용되기 쉽습니다. 인증이 실제적인 목적을 달성하려면 백엔드 애플리케이션에서 보다 정교한 암호화를 사용해야 합니다.
"이 블로그 게시물에는 더 이상 사용할 수 없거나 더 이상 지원되지 않는 제품이 참조될 수 있습니다. 사용 가능한 F5 NGINX 제품과 솔루션에 대한 최신 정보를 보려면 NGINX 제품군을 살펴보세요. NGINX는 이제 F5의 일부가 되었습니다. 이전의 모든 NGINX.com 링크는 F5.com의 유사한 NGINX 콘텐츠로 리디렉션됩니다."