2026년 7월
진행 중명령 한 줄로 HTTPS — 대학 전체 웹서비스의 공인 인증서 자동화
학과·연구실·동아리가 각자 웹서버를 운영하지만, TLS를 신경 쓰고 싶은 사람은 거의 없습니다. 공인 인증서(Let's Encrypt)를 스스로 발급·갱신하는 관리 포털과 명령 한 줄 설치 스크립트를 만들고, 전 서버 현황을 중앙에서 관측합니다. (진행 중)
- TLS
- Let's Encrypt
- ACME
- 자동화
- DevSecOps
개요
KAIST의 웹 서비스는 학과, 연구실, 동아리 등 소유한 주체가 각자 운영합니다. 담당자는 자주 바뀌고, 대부분 TLS를 직접 설정해 본 적이 없으며, 인증서 한 장마다 보안팀에 지원 요청이 들어옵니다. 결과는 늘 같습니다 — 인증서가 만료되고, 장애가 나서야 알아차립니다.
저는 서버 담당자가 명령을 한 줄, 한 번만 실행하면 이후로 인증서를 잊고 지낼 수 있는 체계를 만들고 있습니다. 관리 포털이 설치 스크립트를 발급하고, 서버는 개인키를 스스로 만들어 ACME로 공인 인증서(Let’s Encrypt) 를 받은 뒤, 그때부터 알아서 갱신합니다.
상태: KAIST 정보보안팀과 함께 설계·구축 진행 중.
왜 공인 인증서로 바꿨나
처음 설계는 반대 방향이었습니다 — 사설 ACME 인증기관(step-ca)을 두고 내부 인증서를 발급하는 구조였습니다. 동작은 했지만, 그 비용이 하필 이 프로젝트가 도우려던 사람들에게 떨어졌습니다.
- 모든 서버가 인증서를 받기 전에 Root CA를 받아 신뢰 등록해야 했습니다. 부트스트랩 경로와 신뢰 저장소 수정이 필요했고, 실패하면 담당자 혼자서는 원인을 짚을 수 없었습니다.
- 그 신뢰 저장소 밖의 클라이언트 — 셀룰러로 접속한 휴대폰, 외부 감사자, API 소비자 — 는 여전히 경고를 봤습니다. “안전함”이 중앙에서 통제할 수 없는 설정에 달려 있었습니다.
- CA 자체가 운영·모니터링하고 언젠가 키를 교체해야 하는 인프라가 됐습니다.
Let’s Encrypt로 바꾸면 이 셋이 전부 사라집니다. 공인 CA는 이미 모든 브라우저와 OS가 신뢰하므로 Root CA 배포와 신뢰 설정 단계가 통째로 없어지고, 지켜야 할 사설 신뢰 앵커가 없다는 점에서 보안 수준은 오히려 올라갑니다.
아키텍처

의도적으로 분리한 두 경로:
- 서비스 트래픽 — WAF 경유. 사용자 → 관문 WAF → 원본 웹서버
(Nginx / Apache / IIS), 각 구간에서 443으로 재암호화. 전산실 안에 있는 서버는 전산실 WAF를
한 번 더 거치고, 그 밖의 서버는 관문 WAF 직속입니다. WAF는 공인 와일드카드 인증서
(
*.kaist.ac.kr)를 보유하고, 각 원본 서버는 자기 인증서를 스스로 갱신합니다. - 인증서 발급 — 서버가 Let’s Encrypt와 직접 통신. 발급 주문은 아웃바운드 443입니다. 외부에서
들어오는 것은 소유 확인 하나뿐이고, 관문 WAF가
/.well-known/acme-challenge/경로를 80으로 원본에 그대로 통과시킵니다.
보조 구성요소: 설치 스크립트를 발급하고 현황을 수집하는 기관 SSO 연동 관리 포털, 그리고 각 서버에서 자신의 버전과 인증서 만료일을 보고하는 tracer.
발급 동작 방식

- 설치 스크립트 수신 — 담당자가 명령 한 줄을 실행하면, 포털이 스크립트와 등록 토큰을 내려줍니다.
- 개인키 생성 — 서버에서 만들어 서버에 둡니다. 호스트 밖으로 나가지 않으며, 포털도 볼 수 없습니다.
- 주문과 소유 확인 — 서버가 Let’s Encrypt에 주문하고
/.well-known/acme-challenge/경로에 토큰을 게시하면, Let’s Encrypt가 WAF를 거쳐 80으로 접속해 검증합니다. - 설치와 예약 — 인증서 설치, 서비스 reload, 갱신 타이머 등록.
12단계는 서버를 새로 만들 때만 수행합니다. 34단계는 만료 30일 전에 스스로 반복됩니다.
통신 포트
| 출발지 | 목적지 | 포트 | 용도 |
|---|---|---|---|
| 사용자 | 관문 WAF | 443 | 서비스 |
| 관문 WAF | 전산실 WAF | 443 | 전달 |
| WAF | 원본 웹서버 | 443 | 재암호화 |
| Let’s Encrypt | 관문 WAF | 80 | 소유 확인 |
| 관문 WAF | 원본 웹서버 | 80 | 챌린지 패스스루 |
| 웹서버 | Let’s Encrypt | 443 | 발급 · 갱신 |
| 웹서버 | 공용 DNS | 53 | 이름 해석 |
| 웹서버 | 관리 포털 | 443 | tracer 보고 |
| 웹서버 | NTP | 123 | 시각 동기 |
| 관리자 | 관리 포털 | 443 | SSO · 현황 조회 |
갱신하는 주체를 관측한다
조용히 멈춘 자동화는 자동화가 없는 것보다 나쁩니다. 다들 아직 돌아가고 있다고 믿기 때문입니다. 설치된 tracer는 자동으로 갱신되지 않는 고정 버전이라, 서버에 나가 있는 상태를 밖에서 볼 수 있어야 합니다.
- 보고마다 버전을 함께 보내, 어디에 무엇이 배포돼 있는지 포털이 파악합니다.
- 주간 실행 기준으로 10일 이상 보고가 없으면 해당 tracer를 stale로 표시합니다.
- 이 경고는 인증서가 아직 유효할 때 뜹니다. 인증서가 만료되기 몇 주 전에, 갱신하는 쪽이 멈췄다는 사실을 먼저 잡아냅니다.
설계 선택
- 기본은 DNS-01이 아닌 HTTP-01. 서버에 DNS 자격증명을 두지 않고 권한 위임도 필요 없어서, 설치 스크립트를 비전문가가 실행하고 읽을 수 있는 수준으로 유지합니다. 대가는 분명합니다 — 도메인이 인터넷에서 80으로 접근 가능해야 하고 와일드카드는 쓸 수 없습니다. 그래서 내부 전용 서비스는 기본이 아닌 예외로서 DNS-01로 처리합니다.
- 개인키는 서버에서 생성하고 전송하지 않습니다. 포털은 비밀이 아니라 상태를 관리하므로, 포털이 뚫려도 어떤 서비스의 키도 함께 뚫리지 않습니다.
- NTP는 가정이 아니라 의존성으로 다룹니다. ACME는 시각에 민감하고, 시계가 틀어지면 시계 문제만 빼고 온갖 것처럼 보이는 실패가 납니다.
다음은 Windows
Linux 서버는 certbot을 씁니다. Windows의 IIS는 win-acme로 확장하는 것이 다음 목표입니다. 같은 ACME 프로토콜을 쓰면서 Windows 인증서 저장소와 IIS 바인딩에 직접 기록할 수 있습니다. 포털, tracer 규약, 위의 포트 구성은 모두 클라이언트에 종속되지 않게 설계해서, Windows는 별도 흐름이 아니라 같은 흐름에 합류합니다.
기대 효과
- 서버당 명령 한 줄, 이후 무관리 — 보안팀·통신팀에 대한 반복 요청 제거.
- 만료로 인한 장애 없음 — 갱신이 자동이고, 갱신하는 주체까지 감시하기 때문입니다.
- 어디서나 신뢰되는 HTTPS — 어떤 클라이언트에서도 신뢰 저장소 설정이 필요 없습니다.