# SSL 사설 인증서 설정 가이드 (RedHat 9.6) ## 개요 이 문서는 RedHat 9.6 환경에서 `https://api.train-kamco.com` 및 `https://train-kamco.com` 도메인을 위한 100년 유효한 사설 SSL 인증서 설정 방법을 설명합니다. ## 디렉토리 구조 ``` nginx/ ├── nginx.conf # Nginx 설정 파일 ├── ssl/ │ ├── openssl.cnf # OpenSSL 설정 파일 (SAN 포함) │ ├── train-kamco.com.crt # 사설 SSL 인증서 (멀티 도메인) │ └── train-kamco.com.key # 개인 키 (비공개) └── SSL_SETUP.md # 이 문서 ``` ## 인증서 정보 - **도메인**: api.train-kamco.com, train-kamco.com (멀티 도메인) - **유효 기간**: 100년 (36500일) - **알고리즘**: RSA 4096-bit - **CN (Common Name)**: api.train-kamco.com - **SAN (Subject Alternative Names)**: api.train-kamco.com, train-kamco.com ## 사설 SSL 인증서 생성 (이미 생성됨) 인증서가 이미 생성되어 있습니다. 재생성이 필요한 경우 아래 단계를 따르세요. ### 1. OpenSSL 설정 파일 생성 ```bash cd /path/to/kamco-train-api cat > nginx/ssl/openssl.cnf << 'EOF' [req] default_bits = 4096 prompt = no default_md = sha256 distinguished_name = dn req_extensions = v3_req [dn] C=KR ST=Seoul L=Seoul O=KAMCO OU=Training CN=api.train-kamco.com [v3_req] subjectAltName = @alt_names [alt_names] DNS.1 = api.train-kamco.com DNS.2 = train-kamco.com EOF ``` ### 2. SSL 인증서 및 개인 키 생성 ```bash # nginx/ssl 디렉토리 생성 (없는 경우) mkdir -p nginx/ssl chmod 700 nginx/ssl # 인증서 및 개인 키 생성 (100년 유효) openssl req -new -x509 -newkey rsa:4096 -sha256 -nodes \ -keyout nginx/ssl/train-kamco.com.key \ -out nginx/ssl/train-kamco.com.crt \ -days 36500 \ -config nginx/ssl/openssl.cnf \ -extensions v3_req # 파일 권한 설정 chmod 600 nginx/ssl/train-kamco.com.key chmod 644 nginx/ssl/train-kamco.com.crt ``` ### 3. 인증서 검증 ```bash # 인증서 정보 확인 openssl x509 -in nginx/ssl/train-kamco.com.crt -text -noout # 유효 기간 확인 openssl x509 -in nginx/ssl/train-kamco.com.crt -text -noout | grep -A2 "Validity" # SAN (멀티 도메인) 확인 openssl x509 -in nginx/ssl/train-kamco.com.crt -text -noout | grep -A1 "Subject Alternative Name" # CN 확인 openssl x509 -in nginx/ssl/train-kamco.com.crt -noout -subject # 개인 키 확인 openssl rsa -in nginx/ssl/train-kamco.com.key -check ``` **예상 결과**: ``` X509v3 Subject Alternative Name: DNS:api.train-kamco.com, DNS:train-kamco.com Validity Not Before: Mar 2 23:39:XX 2026 GMT Not After : Feb 6 23:39:XX 2126 GMT ``` ## /etc/hosts 설정 (RedHat 9.6) ### 1. hosts 파일에 도메인 추가 ```bash # root 권한으로 실행 echo "127.0.0.1 api.train-kamco.com train-kamco.com" | sudo tee -a /etc/hosts # 확인 cat /etc/hosts | grep train-kamco ``` **예상 결과**: ``` 127.0.0.1 api.train-kamco.com train-kamco.com ``` ### 2. 도메인 확인 ```bash # ping 테스트 ping -c 2 api.train-kamco.com ping -c 2 train-kamco.com ``` ## Docker Compose 배포 ### 1. 기존 컨테이너 중지 (실행 중인 경우) ```bash cd /path/to/kamco-train-api docker-compose -f docker-compose-prod.yml down ``` ### 2. Production 환경 실행 ```bash # IMAGE_TAG 환경 변수 설정 (선택사항) export IMAGE_TAG=latest # Docker Compose 실행 docker-compose -f docker-compose-prod.yml up -d # 컨테이너 상태 확인 docker-compose -f docker-compose-prod.yml ps ``` ### 3. 로그 확인 ```bash # Nginx 로그 docker logs kamco-cd-nginx # API 로그 docker logs kamco-cd-training-api # 실시간 로그 확인 docker-compose -f docker-compose-prod.yml logs -f ``` ## HTTPS 접속 테스트 ### 1. HTTP → HTTPS 리다이렉트 테스트 ```bash # api.train-kamco.com curl -I http://api.train-kamco.com # train-kamco.com curl -I http://train-kamco.com # 예상 결과: 301 Moved Permanently # Location: https://api.train-kamco.com/ 또는 https://train-kamco.com/ ``` ### 2. HTTPS 헬스체크 (-k: 사설 인증서 경고 무시) ```bash # api.train-kamco.com curl -k https://api.train-kamco.com/monitor/health # train-kamco.com curl -k https://train-kamco.com/monitor/health # 예상 결과: {"status":"UP","components":{...}} ``` ### 3. SSL 인증서 확인 ```bash # api.train-kamco.com openssl s_client -connect api.train-kamco.com:443 -showcerts # train-kamco.com openssl s_client -connect train-kamco.com:443 -showcerts # CN 및 SAN 확인 ``` ### 4. 브라우저 테스트 브라우저에서 다음 URL에 접속: - `https://api.train-kamco.com/monitor/health` - `https://train-kamco.com/monitor/health` **주의**: 사설 인증서이므로 "안전하지 않음" 경고가 표시됩니다. - **Chrome/Edge**: "고급" → "계속 진행" 클릭 - **Firefox**: "위험 감수 및 계속" 클릭 ## 브라우저에서 사설 인증서 신뢰 설정 (선택사항) 사설 인증서를 브라우저에 등록하면 경고 없이 접속 가능합니다. ### Chrome/Edge (RedHat Desktop) 1. `chrome://settings/certificates` 접속 2. **Authorities** 탭 선택 3. **Import** 클릭 4. `nginx/ssl/train-kamco.com.crt` 선택 5. **Trust this certificate for identifying websites** 체크 6. **OK** 클릭 ### Firefox 1. `about:preferences#privacy` 접속 2. **Certificates** → **View Certificates** 클릭 3. **Authorities** 탭 선택 4. **Import** 클릭 5. `nginx/ssl/train-kamco.com.crt` 선택 6. **Trust this CA to identify websites** 체크 7. **OK** 클릭 ## 방화벽 설정 (RedHat 9.6) ### 1. 방화벽 상태 확인 ```bash sudo firewall-cmd --state ``` ### 2. HTTP (80) 및 HTTPS (443) 포트 개방 ```bash # HTTP 포트 개방 sudo firewall-cmd --permanent --add-port=80/tcp # HTTPS 포트 개방 sudo firewall-cmd --permanent --add-port=443/tcp # 방화벽 재로드 sudo firewall-cmd --reload # 확인 sudo firewall-cmd --list-ports ``` **예상 결과**: ``` 80/tcp 443/tcp ``` ## 보안 체크리스트 - [x] `train-kamco.com.key` 파일 권한이 600으로 설정됨 - [x] ssl 디렉토리가 버전 관리에서 제외됨 (.gitignore 확인) - [x] 두 도메인(api.train-kamco.com, train-kamco.com) 모두 SAN에 포함됨 - [ ] 방화벽에서 80, 443 포트 개방 확인 - [x] HSTS 헤더 활성화 확인 - [x] TLS 1.2 이상만 허용 확인 - [ ] /etc/hosts에 도메인 매핑 확인 ## 트러블슈팅 ### 인증서 관련 오류 **"certificate verify failed"** ```bash # 해결: -k 플래그 사용 (사설 인증서 경고 무시) curl -k https://api.train-kamco.com/monitor/health ``` **"NET::ERR_CERT_AUTHORITY_INVALID" (브라우저)** - 정상 동작: 사설 인증서이므로 브라우저 경고는 예상된 동작입니다 - 해결: 브라우저에 인증서 등록 (위 "브라우저에서 사설 인증서 신뢰 설정" 참조) ### 연결 오류 **"Connection refused"** ```bash # 컨테이너 상태 확인 docker ps | grep kamco-cd # 포트 바인딩 확인 docker port kamco-cd-nginx # 예상 결과: # 80/tcp -> 0.0.0.0:80 # 443/tcp -> 0.0.0.0:443 ``` **"502 Bad Gateway"** ```bash # API 컨테이너 상태 확인 docker logs kamco-cd-training-api # nginx → API 연결 확인 docker exec kamco-cd-nginx wget -qO- http://kamco-changedetection-api:8080/monitor/health ``` **"Name or service not known" (도메인 해석 실패)** ```bash # /etc/hosts 확인 cat /etc/hosts | grep train-kamco # 없으면 추가 echo "127.0.0.1 api.train-kamco.com train-kamco.com" | sudo tee -a /etc/hosts ``` ### 방화벽 관련 오류 **외부에서 접속 안 됨** ```bash # 방화벽 확인 sudo firewall-cmd --list-ports # 포트 개방 sudo firewall-cmd --permanent --add-port=80/tcp sudo firewall-cmd --permanent --add-port=443/tcp sudo firewall-cmd --reload ``` ## 인증서 만료 및 갱신 ### 만료 확인 ```bash # 인증서 만료일 확인 openssl x509 -in nginx/ssl/train-kamco.com.crt -noout -enddate # 예상 결과: notAfter=Feb 6 23:39:XX 2126 GMT (100년 후) ``` ### 갱신 방법 (필요시) 100년 유효한 인증서이므로 갱신이 필요하지 않지만, 재생성이 필요한 경우: ```bash # 기존 인증서 백업 cp nginx/ssl/train-kamco.com.crt nginx/ssl/train-kamco.com.crt.bak cp nginx/ssl/train-kamco.com.key nginx/ssl/train-kamco.com.key.bak # 위의 "사설 SSL 인증서 생성" 단계 재실행 # nginx 재시작 docker-compose -f docker-compose-prod.yml restart nginx ``` ## 주의사항 1. **사설 인증서 경고**: 브라우저에서 "안전하지 않음" 경고가 표시됩니다. 프로덕션 환경에서는 **공인 인증서(Let's Encrypt, GlobalSign 등) 사용을 권장**합니다. 2. **포트 80/443**: Docker가 자동으로 처리하지만, 이미 사용 중인 프로세스가 있으면 충돌할 수 있습니다. ```bash # 포트 사용 확인 sudo lsof -i :80 sudo lsof -i :443 ``` 3. **대용량 파일 업로드**: `client_max_body_size`를 10GB로 설정했으므로, 서버 메모리 및 디스크 용량을 충분히 확보하세요. 4. **인증서 백업**: `train-kamco.com.key` 파일은 매우 중요합니다. 안전한 곳에 백업하세요. 5. **SELinux**: RedHat 9.6에서 SELinux가 활성화된 경우, Docker 볼륨 마운트 권한 문제가 발생할 수 있습니다. ```bash # SELinux 상태 확인 getenforce # 필요시 permissive 모드로 변경 sudo setenforce 0 ``` ### 2단계: 시스템 신뢰 폴더로 복사 터미널을 열고 관리자 권한(sudo)을 사용해 인증서를 시스템 폴더로 복사합니다. ``` sudo cp mycert.crt /etc/pki/ca-trust/source/anchors/ ``` ### 3단계: 시스템 신뢰 목록 업데이트 아래 명령어를 입력해 추가한 인증서를 시스템에 갱신시킵니다. ``` sudo update-ca-trust ``` ## 참고 자료 - [OpenSSL Documentation](https://www.openssl.org/docs/) - [Nginx SSL Configuration](https://nginx.org/en/docs/http/configuring_https_servers.html) - [Docker Compose Documentation](https://docs.docker.com/compose/) - [Let's Encrypt (공인 인증서)](https://letsencrypt.org/)