왜 LDAPS인가
LDAP 기본 포트(389)는 평문 통신입니다. 네트워크 어딘가에서 패킷을 캡처하면 로그인 비밀번호가 그대로 보입니다.
내부 네트워크라도 TLS 암호화는 필수입니다. 특히:
- Synology NAS가 LDAP 서버에 바인드할 때 비밀번호를 전송합니다
- 그룹웨어나 서비스가 사용자 인증을 위해 비밀번호를 LDAP으로 넘깁니다
- 사용자가 비밀번호를 변경할 때 새 비밀번호가 전송됩니다
LDAPS(LDAP over TLS, 포트 636)를 사용하면 이 통신이 모두 암호화됩니다.
인증서 구성
세 가지 파일이 필요합니다.
| 파일 | 역할 |
|---|---|
ca.key | CA 개인키 (서버에만 보관, 외부 노출 금지) |
ca.crt | CA 인증서 (클라이언트에 배포) |
ldap.key | LDAP 서버 개인키 |
ldap.crt | LDAP 서버 인증서 (CA가 서명) |
공인 CA(Let’s Encrypt 등) 인증서를 쓸 수도 있지만, 내부 서비스 전용이라면 자체 서명(Self-Signed) 인증서로 충분합니다. 클라이언트가 CA 인증서를 신뢰하도록 배포하면 됩니다.
인증서 생성 스크립트
아래 스크립트를 한 번 실행하면 필요한 파일이 모두 만들어집니다.
#!/bin/bash
set -e
CERT_DIR="/data/ldap-certs"
DOMAIN="ldap.example.com"
DAYS=3650 # 10년
COUNTRY="KR"
STATE="Seoul"
CITY="Seoul"
ORG="YourOrganization"
OU="IT"
mkdir -p $CERT_DIR
cd $CERT_DIR
# 1. CA 개인키 생성 (4096비트 RSA)
openssl genrsa -out ca.key 4096
# 2. CA 인증서 생성
openssl req -new -x509 -days $DAYS -key ca.key -out ca.crt \
-subj "/C=$COUNTRY/ST=$STATE/L=$CITY/O=$ORG/OU=$OU/CN=$ORG CA"
# 3. LDAP 서버 개인키 생성
openssl genrsa -out ldap.key 4096
# 4. CSR 생성
openssl req -new -key ldap.key -out ldap.csr \
-subj "/C=$COUNTRY/ST=$STATE/L=$CITY/O=$ORG/OU=$OU/CN=$DOMAIN"
# 5. SAN(Subject Alternative Name) 설정
cat > ldap.ext << EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = $DOMAIN
DNS.2 = openldap
DNS.3 = localhost
IP.1 = 127.0.0.1
EOF
# 6. CA로 서버 인증서 서명
openssl x509 -req -in ldap.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out ldap.crt -days $DAYS -sha256 \
-extfile ldap.ext
# 권한 설정 (개인키는 소유자만 읽기)
chmod 600 *.key
chmod 644 *.crt
# 임시 파일 정리
rm -f ldap.csr ldap.ext ca.srl
echo "=== 인증서 생성 완료 ==="
openssl x509 -in ldap.crt -noout -subject -dates
SAN이 반드시 필요한 이유
현대 TLS 구현(OpenSSL 1.1+, 브라우저, Python의 ssl 모듈 등)은 CN(Common Name)만으로 호스트를 검증하지 않습니다.
SAN(Subject Alternative Name)에 접속 호스트가 포함되어 있어야 인증서 검증이 통과됩니다.
DNS.1 = ldap.example.com # 외부 접속 도메인
DNS.2 = openldap # Docker 내부 컨테이너 이름
DNS.3 = localhost # 로컬 테스트
IP.1 = 127.0.0.1 # 루프백 IP
SAN 없이 CN만 있는 인증서를 Synology나 그룹웨어에서 쓰면 certificate verify failed 오류가 납니다.
osixia/openldap에 인증서 적용
인증서 파일을 컨테이너가 마운트하는 경로에 넣으면 됩니다.
docker-compose.yml에서 이미 설정해 둔 볼륨 마운트:
volumes:
- /data/ldap-certs:/container/service/slapd/assets/certs
스크립트로 /data/ldap-certs/에 파일을 생성했으므로 컨테이너가 자동으로 읽습니다..env에서 파일 이름을 맞춰 주세요.
LDAP_TLS_CRT_FILENAME=ldap.crt
LDAP_TLS_KEY_FILENAME=ldap.key
LDAP_TLS_CA_CRT_FILENAME=ca.crt
인증서를 새로 발급했다면 컨테이너를 재시작합니다.
./ldapserver.sh restart
TLS 동작 확인
LDAPS 연결 테스트
# 컨테이너 내부에서 (Self-Signed이므로 -Z 옵션으로 TLS 강제)
docker exec openldap ldapsearch -x \
-H ldaps://localhost:636 \
-D "cn=admin,dc=ldap,dc=example,dc=com" \
-w 'your_admin_password' \
-b "dc=ldap,dc=example,dc=com" \
"(objectClass=organizationalUnit)" dn
외부에서 테스트 (CA 인증서 지정)
# 호스트에서 CA 인증서를 명시하여 검증
LDAPTLS_CACERT=/data/ldap-certs/ca.crt \
ldapsearch -x \
-H ldaps://ldap.example.com:10636 \
-D "cn=readonly,dc=ldap,dc=example,dc=com" \
-w 'readonly_password' \
-b "ou=people,dc=ldap,dc=example,dc=com" \
"(objectClass=posixAccount)" uid
openssl로 인증서 내용 확인
# 인증서 상세 정보
openssl x509 -in /data/ldap-certs/ldap.crt -noout -text | grep -A5 "Subject Alternative"
# 유효 기간 확인
openssl x509 -in /data/ldap-certs/ldap.crt -noout -dates
# LDAPS 핸드셰이크 테스트
openssl s_client -connect ldap.example.com:10636 -CAfile /data/ldap-certs/ca.crt
TLS 강제 적용 여부 결정
.env에서 두 가지 옵션을 설정합니다.
LDAP_TLS_ENFORCE=false # true로 바꾸면 평문 LDAP 연결 거부
LDAP_TLS_VERIFY_CLIENT=never # 클라이언트 인증서 요구 안 함
LDAP_TLS_ENFORCE=false를 권장하는 이유가 있습니다.
true로 설정하면 컨테이너 내부의 ldapsearch도 TLS를 요구합니다.
운영·디버그용으로 컨테이너 내부에서 ldap://localhost:389로 직접 붙는 일이 많은데, 이때 불편합니다.
외부 연동은 모두 LDAPS 포트(10636)로만 열어두는 방식으로 TLS를 사실상 강제할 수 있습니다.
클라이언트에 CA 인증서 배포
Self-Signed 인증서를 쓰면 클라이언트 측에서 이 CA를 신뢰하도록 설정해야 합니다.
Synology NAS
DSM > 제어판 > 인증서 > 가져오기에서 ca.crt를 신뢰할 CA로 등록합니다.
또는 LDAP 클라이언트 설정에서 “SSL 인증서 검증 안 함” 옵션을 선택합니다.
내부 서비스라면 검증 안 함도 무방하지만, CA 등록이 더 안전합니다.
Linux 클라이언트
# Ubuntu/Debian
sudo cp /data/ldap-certs/ca.crt /usr/local/share/ca-certificates/ldap-ca.crt
sudo update-ca-certificates
# RHEL/CentOS
sudo cp /data/ldap-certs/ca.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust
ldaprc 파일로 지정
# ~/.ldaprc 또는 /etc/ldap/ldap.conf
TLS_CACERT /data/ldap-certs/ca.crt
인증서 갱신
10년짜리 인증서를 썼으므로 당장 걱정할 일은 없지만, 갱신 절차는 알아둡니다.
# 1. 새 인증서 생성 (스크립트 재실행)
./generate-certs.sh
# 2. 컨테이너 재시작 (볼륨 마운트이므로 재빌드 불필요)
./ldapserver.sh restart
# 3. 연동 클라이언트에 새 CA 인증서 재배포
기존 CA 키(ca.key)가 있다면 CA 인증서를 재발급하지 않고 서버 인증서만 갱신할 수도 있습니다.
이 경우 클라이언트에 CA 재배포가 필요 없습니다.
여기까지의 상태
이 편을 마치면:
- Self-Signed CA와 서버 인증서 발급 완료 (4096비트 RSA, 10년 유효)
- LDAPS(10636) 암호화 통신 활성화
- SAN 포함으로 클라이언트 TLS 검증 통과 확인
다음 편에서는 기본 LDAP 스키마로는 부족한 HR 관리 요구사항을 충족하기 위해 커스텀 스키마를 설계하고, groupOfNames와 posixGroup의 STRUCTURAL 충돌을 AUXILIARY 클래스로 해결하는 방법을 다룹니다.