본문 바로가기
서버구축 (WEB,DB)

LDAP 애플리케이션 Nginx Plus에서 사용자 인증하기

by 날으는물고기 2023. 10. 20.

LDAP 애플리케이션 Nginx Plus에서 사용자 인증하기

NGINX Plus 및 NGINX를 사용하여 요청한 사용자를 인증하여 보호된 리소스 또는 애플리케이션을 보호하는 방법을 자주 묻습니다. 이러한 인증 시스템의 참조 구현을 GitHub의 NGINX 리포지토리에서 사용할 수 있습니다.

 

LDAP의 구현 작동 방식, 설치 방법 및 자체 인증 시스템의 모델로 사용하는 방법에 대해 설명합니다.

참고: 이 참조 구현은 프로덕션 용도가 아니라 자체 구현을 위한 모델로만 사용됩니다.

읽기 쉽도록 이 포스트에서는 NGINX Plus를 사용하지만 해당 구현은 NGINX Open Source에서도 작동합니다.

목차

  1. 참조 구현에서 LDAP 인증이 작동하는 방식
  2. LDAP 구성 요소 설치
  3. 참조 구현 구성
    3-1. LDAP 서버 설정
    3-2. Backend Daemon의 IP 주소
    3-3. ldap-auth Daemon의 IP 주소
    3-4. NGINX가 Listen하는 IP 주소 및 포트
    3-5. Caching
  4. 인증 시스템 사용자 지정
  5. 보안에 대한 참고 사항

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

LDAP 인증을 위한 NGINX Plus 참조 구현에는 ldap-auth 데몬과 샘플 백엔드 데몬이 포함됩니다.

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

  1. 클라이언트는 NGINX Plus가 리버스 프록시로 작동하는 서버에서 호스팅되는 보호된 리소스에 대한 HTTP 요청을 보냅니다.
  2. NGINX Plus(구체적으로 http_auth_request 모듈)는 자격 증명이 제공되지 않았기 때문에 HTTP 코드 401로 응답하는 ldap-auth 데몬에 요청을 전달합니다.
  3. NGINX Plus는 백엔드 데몬에 해당하는 http://backend/login으로 요청을 전달합니다. 전달된 요청의 X-Target 헤더에 원래 요청 URI를 기록합니다.
  4. 백엔드 데몬은 클라이언트에게 로그인 양식을 보냅니다. 이 양식은 데몬의 Python 코드에 정의되어 있습니다. error_page 지시문에 의해 구성된 대로 NGINX는 로그인 양식의 HTTP 코드를 200으로 설정합니다.
  5. 사용자는 양식의 사용자 이름 및 비밀번호 필드를 채우고 로그인 버튼을 클릭합니다. 양식의 코드에 따라 클라이언트는 NGINX Plus가 백엔드 데몬으로 전달하는 /login으로 향하는 HTTP POST 요청을 생성합니다.
  6. 백엔드 데몬은 username:password 형식의 문자열을 구성하고 Base64 인코딩을 적용하고, 값이 인코딩된 문자열로 설정된 nginxauth라는 쿠키를 생성하고, 클라이언트에 쿠키를 보냅니다. 쿠키를 읽거나 조작하기 위해 JavaScript를 사용하지 못하도록 httponly 플래그를 설정합니다(cross-site scripting[XSS] 취약성으로부터 보호).
  7. 클라이언트는 이번에는 HTTP 헤더의 쿠키 필드에 있는 쿠키를 포함하여 원래 요청(1단계에서)을 재전송합니다. NGINX Plus는 요청을 ldap-auth 데몬으로 전달합니다(2단계에서와 같이).
  8. ldap-auth 데몬은 쿠키를 디코딩하고 인증 요청에서 사용자 이름과 암호를 LDAP 서버로 보냅니다.

다음 조치는 LDAP 서버가 사용자를 성공적으로 인증하는지 여부에 따라 다릅니다.

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

2. LDAP 구성 요소 설치

참조 구현과 함께 배포되는 NGINX Plus 구성 파일인 nginx-ldap-auth.conf는 LDAP 서버 이외의 모든 구성 요소(즉, NGINX Plus, 클라이언트, ldap-auth 데몬 및 백엔드 데몬)가 실행되도록 구성합니다. 동일한 호스트에서 테스트 목적으로 적합합니다. LDAP 서버는 테스트 중에 해당 호스트에서 실행할 수도 있습니다.

 

실제 배포에서 백엔드 애플리케이션과 인증 서버는 일반적으로 각각 별도의 호스트에서 실행되며 NGINX Plus는 세 번째 호스트에서 실행됩니다. ldap-auth 데몬은 대부분의 상황에서 많은 리소스를 소비하지 않으므로 NGINX Plus 호스트 또는 선택한 다른 호스트에서 실행할 수 있습니다.

실행 명령 및 스크립트 추가

  1. GitHub 리포지토리의 복제본을 만듭니다.
  2. NGINX Plus가 아직 실행되지 않은 경우 운영체제 지침에 따라 설치합니다.
  3. LDAP 서버가 아직 실행되고 있지 않으면 서버를 설치하고 구성하십시오. 기본적으로 ldap‑auth 데몬은 OpenLDAP와 통신하지만 Microsoft Windows Active Directory 2003 및 2012도 지원됩니다.기본 DN, 바인딩 DN 및 바인딩 암호에 대해 설정한 값을 기록해 둡니다. 참조 구현 구성에서 NGINX 구성 파일에 넣습니다.
  4. 참조 구현을 테스트하기 위해 LDAP 서버만 사용하는 경우 GitHub에서 제공되는 OpenLDAP 서버 Docker 이미지를 사용하거나 Ubuntu 16.04에서 OpenLDAP 및 phpLDAPadmin을 설치 및 구성 하는 방법과 같은 지침을 사용하여 서버를 설정할 수 있습니다.
  5. ldap-auth 데몬이 실행될 호스트에서 다음 추가 소프트웨어를 설치합니다. Open Source 리포지토리에서 소프트웨어를 다운로드하는 대신 운영체제와 함께 배포되는 버전을 사용하는 것이 좋습니다.
    • Python 버전 2. 버전 3은 지원되지 않습니다.
    • Python LDAP 모듈, python-ldap(python-ldap.org Open Source 프로젝트에서 생성).
  6. 리포지토리 복제본에서 다음 파일을 표시된 호스트로 복사합니다.
    • 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 코드입니다. 선택한 호스트에 설치합니다.
  7. 아래의 참조 구현 구성에 설명된 대로 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
  8. NGINX Plus를 시작합니다. NGINX Plus가 이미 실행 중인 경우 다음 명령을 실행하여 구성 파일을 다시 로드합니다.
    root# nginx -s reload
  9. 적절한 호스트에서 다음 명령을 실행하여 ldap‑auth 데몬 및 백엔드 데몬을 시작합니다.
    root# nginx-ldap-auth-daemon-ctl.sh start
    root# python backend-sample-app.py
  10. 웹 브라우저를 사용하여 http://nginx-server-address:8081에 액세스합니다. 브라우저가 인증 양식을 표시하는지 확인하십시오. 양식을 작성하고 제출한 후 서버가 유효한 자격 증명에 대한 예상 응답을 반환하는지 확인합니다. 위에서 언급한 대로 백엔드 데몬은 다음 텍스트를 반환합니다.
    Hello, world! Requested URL: URL

3. 참조 구현 구성

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

3-1. LDAP 서버 설정

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

 

다음 표는 매개변수와 헤더를 매핑합니다.

LDAP 매개변수 HTTP 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)";
  • (선택 사항) 영역 이름을 기본값(Restricted)에서 변경하려면 주석을 제거하고 다음 지시문을 변경합니다.
proxy_set_header X-Ldap-Realm "Restricted";

3-2. Backend Damon의 IP 주소

백엔드 데몬이 NGINX Plus와 동일한 호스트에서 실행되고 있지 않으면 upstream 구성 블록에서 IP 주소를 변경합니다.

upstream backend {
    server 127.0.0.1:9000;
}

3-3. ldap‑auth Daemon의 IP 주소

ldap‑auth 데몬이 NGINX Plus와 동일한 호스트에서 실행되고 있지 않으면 이 proxy_pass 지시문에서 IP 주소를 변경합니다.

location = /auth-proxy {
    proxy_pass http://127.0.0.1:8888;
    # ...
}

3-4. NGINX가 Listen하는 IP 주소 및 포트

클라이언트가 NGINX Plus와 동일한 호스트에서 실행되고 있지 않으면 이 listen 지시문에서 IP 주소를 변경하거나 클라이언트의 트래픽을 허용하도록 주소를 완전히 제거하십시오. 원하는 경우 NGINX가 수신(Listen)하는 포트를 8081에서 변경할 수도 있습니다.

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

3-5. Caching

nginx-ldap-auth.conf 파일을 사용하면 데이터와 자격 증명을 모두 캐싱할 수 있습니다. 선택적으로 다음 설정을 변경할 수 있습니다.

http 구성 블록의 proxy_cache_path 지시문은 캐시라는 로컬 디스크 디렉토리를 생성하고 메타데이터가 저장되는 auth_cache라는 영역의 공유 메모리에 10MB를 할당합니다.

proxy_cache_path cache/ keys_zone=auth_cache:10m;

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

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

proxy_cache_valid 지시문(proxy_cache와 동일한 location 블록에 있음)은 HTTP 코드 200 또는 403으로 표시된 캐시된 응답이 10분 동안 유효함을 지정합니다.

location = /auth-proxy {
    proxy_cache_valid 200 403 10m;
    # ...
}

캐싱을 비활성화하려면 이 세 가지 지시문과 proxy_cache_key 지시문을 주석 처리하십시오.

 

docker-compose.yml

version: '3.6'
services:

  openldap:
    env_file: .env
    image: osixia/openldap:latest
    restart: always
    container_name: openldap
    environment:
      TZ: Asia/Seoul
      LDAP_ORGANISATION: "${LDAP_ORGANISATION}"
      LDAP_DOMAIN: "${LDAP_DOMAIN}"
      LDAP_ADMIN_PASSWORD: "${LDAP_ADMIN_PASSWORD}"
    volumes:
      - ./slapd/config:/etc/ldap/slapd.d
      - ./slapd/database:/var/lib/ldap
      - ./slapd/ldifs:/container/service/slapd/assets/custome
    ports:
      - 389:389
      - 636:636
    networks:
      - ldapnetwork

  phpldapadmin:
    image: osixia/phpldapadmin:latest
    restart: always
    container_name: phpldapadmin
    environment:
      TZ: Asia/Seoul
      PHPLDAPADMIN_LDAP_HOSTS: "openldap"
      PHPLDAPADMIN_HTTPS: "false"
    #volumes:
    #  - ./pla/config:/container/service/phpldapadmin/assets/config
    #  - ./pla/phpldapadmin:/var/www/phpldapadmin
    ports:
      - 8080:80
      - 8443:443
    links:
      - "openldap:openldap"
    networks:
      - ldapnetwork

networks:
  ldapnetwork:

 

원문 : https://nginxstore.com/blog

728x90

댓글