TLS 보안 완벽 가이드: 취약점 제거부터 실전 설정까지
TL;DR: TLS 1.0/1.1과 약한 암호화 스위트를 완전히 제거하고, TLS 1.2/1.3만 사용하는 것이 2025년 현재 보안의 기본입니다. 이 가이드에서는 이론부터 실전 설정까지 모든 것을 다룹니다.
들어가며
최근 몇 년간 TLS 관련 보안 이슈가 지속적으로 발견되면서, 많은 조직에서 TLS 설정을 재검토하고 있습니다. 특히 Azure Application Gateway의 TLS 1.0/1.1 지원 종료(2025년 8월 31일) 발표는 많은 개발팀에게 시급한 과제가 되었죠.
오늘은 TLS가 무엇인지부터 시작해서, 어떤 버전과 설정이 취약한지, 그리고 실제 운영 환경에서 어떻게 보안을 강화할 수 있는지까지 체계적으로 알아보겠습니다.
TLS란 무엇인가?
**TLS(Transport Layer Security)**는 인터넷에서 클라이언트와 서버 간 통신을 보호하는 프로토콜입니다. 세 가지 핵심 기능을 제공합니다:
- 기밀성(Confidentiality): 데이터를 암호화하여 제3자가 볼 수 없게 함
- 무결성(Integrity): 데이터가 전송 중 변조되지 않았음을 보장
- 인증(Authentication): 서버(및 선택적으로 클라이언트)의 신원을 확인
현재 최신 버전은 TLS 1.3이며, 이전 버전 대비 설계가 단순해지고 보안이 크게 향상되었습니다.
TLS는 어디에 사용되나?
TLS는 우리가 매일 사용하는 거의 모든 인터넷 서비스에서 활용됩니다:
- 웹 브라우징: HTTPS (HTTP over TLS)
- 이메일: SMTP/IMAP/POP의 STARTTLS
- API 통신: REST API, GraphQL 등
- 데이터베이스: MySQL, PostgreSQL 등의 암호화 연결
- 메시징: Slack, Teams 등의 실시간 통신
TLS 버전별 현황: 무엇을 써야 하나?
🚫 폐기된 버전 (절대 사용 금지)
- SSLv2/SSLv3: 심각한 보안 취약점으로 완전 폐기
- TLS 1.0/1.1: RFC 8996에서 공식 폐기 선언
✅ 권장 버전
- TLS 1.2: 현재 가장 널리 사용되며 안전한 버전
- TLS 1.3: 최신 버전으로 성능과 보안이 크게 개선됨
미국 NIST 가이드라인에서도 TLS 1.2를 필수로, TLS 1.3 도입을 권장하고 있습니다.
암호화 스위트: 안전한 것과 위험한 것
TLS 1.3 권장 스위트
TLS 1.3에서는 스위트가 크게 단순화되었습니다:
- TLS_AES_128_GCM_SHA256
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
TLS 1.2 권장 조합
ECDHE + (AES-GCM 또는 ChaCha20-Poly1305) 조합을 사용하세요:
- ECDHE-ECDSA-AES128-GCM-SHA256
- ECDHE-RSA-CHACHA20-POLY1305
🔴 반드시 제거해야 할 취약 요소
프로토콜 레벨:
- SSLv2/3, TLS 1.0, TLS 1.1
암호화 스위트:
- RC4, 3DES/DES, NULL/aNULL/EXPORT/LOW
- 정적 RSA 키교환, 익명 DH
- MD5, SHA-1 서명
- 약한 DH (<2048비트)
- 구식 CBC 조합
키 길이 권장사항:
- RSA: 최소 2048비트 (가급적 3072비트)
- ECDSA: P-256/P-384
- DH 파라미터: 최소 2048비트
- 곡선: X25519 또는 secp256r1 우선
핵심 질문: 서버만 설정하면 될까, 양쪽 다 해야 할까?
완전히 안전·준수하려면 "양쪽 모두"에서 제거(차단)하는 게 정석입니다. 다만 "한쪽만" 바꿔도 그 쪽으로 들어오는 트래픽은 강제로 안전한 스펙으로 협상되거나 실패하므로, 해당 방향은 보호됩니다.
언제 한쪽만으로도 되나?
A 서버(수신자)만 TLS 1.2/1.3로 제한하면 B→A 연결은 약한 프로토콜/암호로는 협상이 안 됩니다(강한 걸로 올라가거나 실패). → A 쪽 수신 방향 보안은 확보됩니다.
왜 양쪽 다 해야 하나?
- 양방향 연동(서로 요청/응답을 보냄)이라면, A가 발신자가 되는 순간 A의 클라이언트 스택(JDK/SChannel/OpenSSL) 정책이 약하면, 다른 서버가 약한 걸 허용할 때 약한 걸로 내려가 협상할 수 있습니다.
- LB/프록시/게이트웨이가 TLS를 종료한다면 그 지점에서도 정책을 걸어야 합니다. (프런트단과 백엔드단이 분리되면 두 구간 모두 적용)
- 컴플라이언스(내부 규정/감사) 관점에선 "엔드투엔드"로 약한 스펙을 어디서도 허용하지 않음이 요구되는 경우가 많습니다.
🎯 빠른 결정표
- 단방향 호출(B→A만 호출) + A만 강화 ⇒ B→A는 안전(또는 실패)
- 양방향 호출 ⇒ A/B 둘 다 "수신(서버 설정)"과 "발신(클라이언트 정책)"에 동일 기준 적용
- LB/AGW/ALB 등 종단이 여러 개 ⇒ 종단마다 최소 TLS 1.2/1.3, 약한 스위트 차단
실전 설정: 플랫폼별 취약점 제거 방법
1. Linux 시스템 전역 정책 (RHEL 계열)
RHEL 8/9는 시스템 전역 암호화 정책으로 한 번에 설정할 수 있습니다:
# SHA-1까지 차단
sudo update-crypto-policies --set DEFAULT:NO-SHA1
# 더 엄격한 설정 (호환성 검토 후 적용)
sudo update-crypto-policies --set FUTURE
설정 후 재부팅이 필요하며, 개별 애플리케이션 설정도 함께 확인해야 합니다.
2. NGINX 설정
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:
ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:
ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_ecdh_curve X25519:P-256:P-384;
# 추가 보안 헤더
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
3. Apache httpd 설정
SSLProtocol TLSv1.2 TLSv1.3
SSLCipherSuite HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!RC4:!MD5:!SHA1:!PSK:!SRP:!DSS
TLS13CipherSuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
SSLHonorCipherOrder on
SSLOpenSSLConfCmd Curves X25519:P-256:P-384
4. Java/Tomcat 설정
Tomcat Connector 설정:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
SSLEnabled="true"
sslProtocol="TLS"
sslEnabledProtocols="TLSv1.3,TLSv1.2"
ciphers="TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"/>
Java 전역 차단 설정 (java.security):
jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, 3DES_EDE_CBC,
MD5withRSA, DH keySize < 2048, EC keySize < 224, SHA1 jdkCA, RSA keySize < 2048, ECDH
5. Windows/IIS 설정
레지스트리를 통해 TLS 1.0/1.1을 비활성화할 수 있습니다:
HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server
Enabled=0 (DWORD)
DisabledByDefault=1 (DWORD)
⚠️ 주의: 레지스트리 변경은 시스템 전체에 영향을 미치므로 충분한 테스트 후 적용하세요.
6. WildFly/JBoss 설정
Elytron 보안 컨텍스트에서 설정:
<server-ssl-context name="httpsSSC"
protocols="TLSv1.3 TLSv1.2"
cipher-suite-filter="TLS_ECDHE_.*_(AES|CHACHA20)_.*GCM_.*"
key-manager="serverKM" trust-manager="serverTM"/>
7. 클라우드 로드밸런서 설정
Azure Application Gateway:
az network application-gateway ssl-policy set \
-g <RG> --gateway-name <AGW> \
--policy-type Predefined --name AppGwSslPolicy20220101S \
--min-protocol-version TLSv1_2
중요한 변화: Azure Application Gateway는 2025년 8월 31일부터 TLS 1.0/1.1 지원을 완전히 중단합니다. 백엔드 서버도 최소 TLS 1.2 이상으로 준비해야 합니다.
AWS ALB: 보안 정책을 ELBSecurityPolicy-TLS-1-2-Ext-2018-06 또는 그 이상으로 설정하세요.
설정 검증: 제대로 적용되었는지 확인하기
외부 서비스 검증
SSL Labs 테스트 (가장 간편):
https://www.ssllabs.com/ssltest/
내부/사설망 검증
nmap 스크립트:
nmap -p 443 --script ssl-enum-ciphers <host>
testssl.sh (권장):
./testssl.sh -p 443 <host>
🔍 실무 검증 체크리스트
약한 연결 시도가 실패하는지 확인:
# TLS 1.0 시도 → 실패해야 정상
openssl s_client -connect host:443 -tls1_0
# TLS 1.1 시도 → 실패해야 정상
openssl s_client -connect host:443 -tls1_1
강한 연결 시도가 성공하는지 확인:
# TLS 1.2 시도 → 성공해야 정상
openssl s_client -connect host:443 -tls1_2
# TLS 1.3 시도 → 성공해야 정상
openssl s_client -connect host:443 -tls1_3
양방향 통신 환경에서는 상호 방향 모두 점검:
- A→B 방향과 B→A 방향 각각 테스트
- 클라이언트 정책과 서버 정책 모두 확인
실무 완전 체크리스트
📋 프로토콜 및 암호화 정책
- [ ] 프로토콜: 양쪽(및 LB) 모두 TLS 1.2/1.3만 허용, 1.0/1.1/SSLv3 끄기
- [ ] 암호 스위트: **ECDHE + (AES-GCM/ChaCha20)**만, RC4/3DES/CBC/MD5/SHA-1/익명DH/정적RSA 키교환 제거
- [ ] 클라이언트 정책: JDK라면 java.security의 jdk.tls.disabledAlgorithms에 약한 항목 추가(발신도 통제)
- [ ] LB/게이트웨이: 프런트/백엔드 두 구간 모두 최소버전과 스위트 정책 지정
🔄 양방향 통신 고려사항
- [ ] 서버 설정: 수신 연결에 대한 TLS 정책 적용
- [ ] 클라이언트 설정: 발신 연결에 대한 TLS 정책 적용
- [ ] 상호 연결 테스트: A↔B 양방향 모두 약한 프로토콜 차단 확인
- [ ] 프록시/LB 구간: 각 TLS 종료 지점마다 동일한 보안 기준 적용
🧪 테스트 및 검증
- [ ] 약한 시도 실패: openssl s_client -tls1_0/-tls1_1 실패 확인
- [ ] 강한 시도 성공: openssl s_client -tls1_2/-tls1_3 성공 확인
- [ ] 도구 활용: testssl.sh/nmap --script ssl-enum-ciphers로 종합 점검
- [ ] SSL Labs: A+ 등급 달성 (외부 노출 서비스)
적용 로드맵: 안전한 마이그레이션 전략
1단계: 현황 파악
- 모든 TLS 서비스 인벤토리 작성
- SSL Labs, nmap, testssl.sh로 현재 상태 스캔
- 레거시 클라이언트 식별
2단계: 스테이징 환경 적용
- 테스트 환경에서 새 설정 적용
- 주요 클라이언트(브라우저, 모바일 앱, API 클라이언트) 호환성 테스트
3단계: 점진적 프로덕션 적용
- 트래픽이 적은 시간대에 적용
- 모니터링 도구로 연결 실패율 추적
- 롤백 계획 준비
4단계: 레거시 지원 전략
- 구형 클라이언트를 위한 별도 엔드포인트 고려
- 단계적 지원 중단 일정 수립
빠른 체크리스트
설정 완료 후 다음 항목들을 확인해보세요:
- [ ] 프로토콜: TLS 1.2/1.3만 허용 (1.0/1.1/SSL 완전 차단)
- [ ] 암호화 스위트: TLS 1.3 기본 3종, TLS 1.2는 ECDHE + AEAD 조합만
- [ ] 키 및 서명: RSA≥2048, ECDSA P-256/384, SHA-256/384 이상
- [ ] 시스템 정책: OS 레벨 crypto-policies 적용
- [ ] 웹서버/앱서버: 각 플랫폼별 설정 완료
- [ ] 로드밸런서: 클라우드 LB 정책 업데이트
- [ ] 양방향 통신: 서버/클라이언트 정책 모두 적용
- [ ] 검증 완료: SSL Labs A+ 등급 또는 테스트 도구 PASS
환경별 맞춤 설정이 필요하신가요?
현재 환경(예: Java 17 / WildFly 27 / Azure Application Gateway)에 맞는 A↔B 양방향과 LB 프런트/백엔드에 적용할 구체적인 설정값이 필요하시다면, 댓글로 다음 정보를 알려주세요:
- 구성 정보: 누가 누구를 호출하는지 (단방향/양방향)
- TLS 종료 지점: 로드밸런서, 프록시, 서버 등
- OS/미들웨어 버전: RHEL 8, Java 17, WildFly 27 등
- 클라우드 환경: Azure AGW, AWS ALB 등
바로 복사해서 사용할 수 있는 설정 파일을 만들어드리겠습니다!
마치며
TLS 보안 강화는 한 번에 끝나는 작업이 아닙니다. 새로운 취약점이 발견되고 표준이 업데이트되면서 지속적인 관리가 필요합니다.
특히 2025년에는 여러 클라우드 제공업체와 브라우저에서 TLS 1.0/1.1 지원을 완전히 중단할 예정이므로, 지금이 바로 TLS 설정을 점검하고 업그레이드할 때입니다.
혹시 특정 환경(예: Java 17 + WildFly 27 + Azure Application Gateway)에 맞는 상세한 설정이 필요하시다면, 댓글로 알려주세요. 바로 복사해서 사용할 수 있는 설정 파일을 만들어드리겠습니다!
참고 자료
- RFC 8446 - TLS 1.3 Protocol
- RFC 8996 - Deprecating TLS 1.0 and TLS 1.1
- NIST SP 800-52 Rev. 2 - TLS Guidelines
- SSL Labs SSL Test
- testssl.sh GitHub Repository
이 포스트가 도움이 되셨다면 공유해주세요! 🔒
'IT와 과학' 카테고리의 다른 글
| Azure VPN 게이트웨이에 대한 OpeaAI의 충분한 설명 (0) | 2024.12.22 |
|---|---|
| mybatis 를 이용하여 altibase를 연결하여 사용하는 spring mvc모델 소스 (0) | 2023.08.14 |
| Fetch API 사용 (1) | 2023.02.18 |
| 어머 이건 알아야 해! ~ 애플 페이 레이터 출시임박!!! (0) | 2023.02.11 |
| 한국의 API 서비스 목록 (1) | 2023.02.04 |