415 lines
10 KiB
Markdown
415 lines
10 KiB
Markdown
# 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/)
|