4편에서 WAN 절체로 OPNsense를 메인 방화벽으로 올렸습니다. 그런데 실제 작업 순서를 보면, 절체 전에 미리 깔아두는 보안 작업들이 있습니다. 통신을 끊을 위험이 없어서 운영 중에도 안전하게 할 수 있고, 절체 순간 바로 효과를 내는 것들입니다. 이번 편은 그 절체 전 보안 기반 네 가지 — NTP, 설정 백업, GeoIP 차단, ACME 인증서 — 를 다룹니다.
왜 “절체 전”에 하나
보안·운영 플러그인은 성격에 따라 두 묶음으로 나뉩니다.
- 절체 전 기반(이번 편): NTP, 백업, GeoIP, ACME — 위험이 없고, 절체 전에 준비해두면 절체 직후 바로 동작합니다.
- 절체 후 방어선(다음 편): Caddy, Suricata, TOTP, VPN — 외부에 노출되기 시작한 뒤 세우는 능동 방어입니다.
핵심 원칙은 변하지 않습니다. 위험 없는 것부터, 통신을 끊을 수 있는 것은 뒤로. 그래서 이번 편의 작업들도 “준비는 다 하되, 실제로 트래픽을 차단하는 WAN 룰만은 방화벽 정리 단계로 미루는” 식으로 진행합니다.
작업 순서:
- NTP — 시간 동기화 (모든 로그·인증서의 기준)
- Configuration Backup — 암호화 백업, 여러 곳 분산
- GeoIP 차단 — DB 등록 + Alias 생성 (차단 룰은 뒤로)
- ACME — Let’s Encrypt 와일드카드 인증서 자동 발급
1. NTP — 시간 동기화
시간이 안 맞으면 인증서 검증, 로그 타임스탬프, 2FA(TOTP) 코드까지 줄줄이 틀어집니다. 그래서 보안 작업의 가장 처음에 NTP를 맞춥니다.
Services → Network Time → General
설정 포인트는 세 가지입니다.
- NTP 서버:
kr.pool.ntp.org같은 지역 풀을 씁니다. 여러 개 넣으면 그중 가장 안정적인 하나가 자동으로 기준(Active Peer)이 됩니다. - Iburst 활성화: 켜두면 처음 동기화가 훨씬 빨리 잡힙니다. 안 켜면 첫 동기화까지 한참 걸립니다.
- 그래프(Statistics) 활성화: offset 추이를 볼 수 있어 동기화 상태 확인이 쉽습니다.
⚠️ WAN에는 NTP 서비스를 열지 말 것
가장 중요한 보안 포인트입니다. OPNsense의 NTP를 WAN 인터페이스에서 서비스로 제공(listen)하면 안 됩니다. 외부에 열린 NTP 서버는 NTP 증폭 DDoS에 악용됩니다(작은 요청으로 큰 응답을 끌어내 제3자를 공격). NTP는 내부 인터페이스(관리망·서버망 등)에서만 제공하고, OPNsense 자신이 외부 NTP로 나가서 시간을 받아오는 것(클라이언트 방향)만 허용합니다.
이 프로젝트에서는 NTP를 내부망(관리/서버망)에만 바인딩하고 WAN은 제외했습니다. Iburst와 그래프를 켜니 offset이 0.1ms 수준으로 빠르게 안정됐습니다. 풀 항목 중
.POOL.(Stratum 16)로 표시되는 줄은 “풀에서 실제 서버를 뽑아내는 관리용 항목”이라 항상 그대로 남습니다 — 정상입니다.
동기화 확인은 같은 화면의 상태 표시에서 Active Peer가 떴고 offset이 작으면 성공입니다. 나머지 서버가 Pending/Unreach로 보여도 백업 후보로 계속 측정 중인 것이라 문제 없습니다.
2. Configuration Backup — 설정 백업
방화벽 설정은 수십 시간을 들여 쌓은 자산입니다. 한 번의 실수나 디스크 고장으로 날아가면 복구가 막막합니다. 암호화 백업을 받아 여러 곳에 분산해 둡니다.
System → Configuration → Backups
수동 백업 절차:
- “Encrypt this configuration file” 체크 → 비밀번호 입력(두 번).
- Download configuration 클릭 →
config.xml이 암호화되어 내려받아집니다. - 파일명에 날짜를 붙입니다. 예:
opnsense-hq-2026-05-08-baseline.xml.
암호화가 중요한 이유는, config.xml 안에 VPN 키, 인증서, API 토큰, 해시된 비밀번호 등 민감 정보가 들어 있기 때문입니다. 평문으로 클라우드에 올리면 그 자체가 사고입니다.
보관은 최소 3곳에 분산합니다(예: 작업 PC + 개인 클라우드 + 비밀번호 관리자). 백업 파일의 암호도 비밀번호 관리자에 함께 저장합니다 — 암호를 잃으면 백업이 무용지물입니다.
자동 백업(API 사용자 + cron, 또는
os-google-drive플러그인)도 있지만, 클라우드 연동 플러그인은 WAN이 살아 있어야 설치됩니다. 그래서 절체 전에는 수동 암호화 백업으로 최소한의 안전망을 확보하고, 자동화는 절체 후로 미루는 게 현실적입니다.
작업 단계마다(특히 큰 변경 전후) 백업을 새로 받는 습관을 들이면, 언제든 직전 상태로 돌아갈 수 있습니다. 콘솔 메뉴의 13) Restore a backup으로 복원합니다.
3. GeoIP 차단 — 준비 단계
특정 국가에서 오는 트래픽을 통째로 막는 게 GeoIP 차단입니다. 외부 노출 서비스(웹·VPN·메일)에 대한 무차별 스캔·공격의 상당수가 소수 고위험 지역에서 오기 때문에, 사업상 관계없는 국가를 막으면 공격 표면이 크게 줄어듭니다.
GeoIP는 네 단계인데, 이번 편에서는 위험 없는 ①~③(DB 등록 + Alias 생성)까지만 하고, ④ WAN 차단 룰은 방화벽 정리 단계로 미룹니다. WAN 룰은 잘못 넣으면 정상 트래픽까지 막아 사고가 나기 때문입니다.
① MaxMind 라이선스 키 발급
OPNsense의 GeoIP는 MaxMind의 무료 GeoLite2 DB를 씁니다.
- MaxMind 가입 → 이메일 인증.
Account → Manage License Keys → Generate new license key.- “Will this key be used for GeoIP Update?”에서 반드시 Yes 선택.
- 발급된 키는 한 번만 표시되므로 즉시 비밀번호 관리자에 저장.
키 하나로 여러 장비(HQ·IDC 등)에서 재사용할 수 있습니다. 단, 키가 채팅·문서·백업 등에 노출됐다면 반드시 폐기 후 재발급하세요. 재발급 시에는 “새 키 발급 → OPNsense URL의
license_key=교체 → Apply → 기존 키 삭제” 순서를 지켜야 합니다. 순서를 거꾸로 하면 다음 자동 갱신에서 다운로드가 실패합니다.
② DB 등록 (자동 다운로드)
Firewall → Aliases → GeoIP settings 탭
Url 칸에 다음 형식을 넣습니다(키 부분만 교체).
https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country-CSV&license_key=발급받은키&suffix=zip
Save하면 OPNsense가 그 URL로 국가별 IP 대역 DB를 자동 다운로드합니다(수십 초~1분). 완료되면 화면에 Last updated 날짜와 Total number of ranges(약 120만 개)가 표시됩니다. 이 숫자가 보이면 DB가 정상적으로 받아진 것입니다.
③ 차단 Alias 생성
Firewall → Aliases → + (Add)
| 항목 | 값 |
|---|---|
| Type | GeoIP |
| Name | GEO_BLOCK_HIGH_RISK |
| Content | 차단할 국가 선택(사업 관계없는 고위험국) |
국가를 고르면 해당 국가들의 IP 대역(수만 개)이 이 Alias 하나로 묶입니다. 이 프로젝트에서는 고위험 5개국을 묶어 약 47,000개 대역의 Alias를 만들었습니다.
여기까지가 이번 편의 GeoIP 작업입니다. 이 Alias를 실제로 WAN에서 Block하는 룰은 방화벽 정리 단계에서 다른 WAN 인바운드 룰과 함께 신중히 추가합니다.
주의: GeoIP 차단은 강력하지만 거칠다는 점을 기억하세요. 막은 국가에서 정당한 접속(예: 해외 출장자, 해외 협력사)이 필요해질 수 있습니다. 그래서 “사업상 절대 관계없는 국가”부터 보수적으로 시작하고, VPN 등 우회 경로를 함께 설계합니다.
4. ACME — Let’s Encrypt 자동 인증서
외부 공개 서비스, 관리 GUI, VPN 등에 붙일 정식 SSL 인증서를 Let’s Encrypt에서 자동으로 발급·갱신합니다.
플러그인 설치
System → Firmware → Plugins → os-acme-client
os-acme-client는 커뮤니티 플러그인이라 기본 목록에 안 보일 수 있습니다. 플러그인 화면 우상단의 “Show community plugins” 체크박스를 켜야 검색에 나타납니다.
계정과 챌린지 방식
Services → ACME Client
- Settings: Enable Plugin ✅, Auto Renewal ✅.
- Accounts: Let’s Encrypt 계정 등록(이메일은 만료 알림용). 처음엔 Staging(Test CA)으로 테스트한 뒤 Production으로 전환하는 게 안전합니다 — LE는 발급 횟수 제한이 있습니다.
- Challenge Type: DNS-01 + Cloudflare를 권장합니다.
DNS-01을 쓰는 이유가 중요합니다. HTTP-01 방식은 WAN으로 80포트 인바운드가 열려 있어야 하는데, 절체 전에는 아직 WAN이 OPNsense로 안 들어옵니다. 반면 DNS-01은 도메인 DNS에 TXT 레코드를 넣어 인증하므로 WAN 상태와 무관하게 발급됩니다. DNS를 Cloudflare로 옮겨두고 API 토큰을 연동하면, 와일드카드 인증서까지 완전 자동으로 발급·갱신됩니다.
와일드카드 인증서 발급
Services → ACME Client → Certificates → +
| 항목 | 값(예시) |
|---|---|
| Common Name | *.example.com |
| SAN List | example.com (apex 포함 시) |
| ACME Account | 등록한 Let’s Encrypt 계정 |
| Challenge Type | Cloudflare DNS-01 |
| Auto Renewal | ✅ |
Save → Issue/Renew. 와일드카드(*.example.com) 하나면 그 도메인의 모든 서브도메인(서비스·VPN·관리 GUI 등)에 재사용할 수 있어 관리가 단순해집니다. 이 프로젝트에서는 용도별로 여러 와일드카드(서비스용·개발용·검증용 등)를 발급해 일관된 패턴으로 관리했습니다.
발급된 인증서는 System → Trust → Certificates에 자동 임포트되어, Caddy·OpenVPN·관리 GUI 등 다른 서비스에서 바로 가져다 씁니다.
자동 갱신 Cron
ACME Settings에서 Apply하면, 매일 자정(0시 0분)에 갱신 필요 여부를 검사하는 Cron 작업이 자동 등록됩니다(System → Settings → Cron에서 확인). 덕분에 90일짜리 Let’s Encrypt 인증서가 사람 손 안 타고 갱신됩니다.
보안 주의: Cloudflare API 토큰은 DNS 레코드를 바꿀 수 있는 강력한 권한입니다. 백업(config.xml)이나 채팅·문서에 노출됐다면 작업 후 반드시 폐기하고 재발급하세요. DNS-01 + Cloudflare 조합은 WAN IP가 바뀌어도(IDC 이전 등) 갱신에 영향이 없다는 큰 장점이 있습니다.
이번 편 체크포인트
절체 전 보안 기반 네 가지가 갖춰진 상태입니다.
- NTP — 내부망에만 제공(WAN 제외), Iburst로 빠르게 동기화. 모든 로그·인증서·2FA의 시간 기준 확보
- Backup — 암호화 설정 백업을 여러 곳에 분산. 언제든 직전 상태로 복구 가능
- GeoIP — 약 120만 대역 DB 등록 + 고위험국 차단 Alias 생성(WAN 차단 룰은 방화벽 정리 단계로 보류)
- ACME — Cloudflare DNS-01로 와일드카드 인증서 발급, 매일 자정 자동 갱신. WAN 상태와 무관하게 동작
이 네 가지는 절체 순간 바로 효력을 냅니다. 인증서는 이미 준비돼 있고, 시간은 맞아 있고, GeoIP DB는 룰만 켜면 되는 상태입니다.
다음 편 예고
06. OPNsense 보안 설정 ② — 절체 후 방어선과 접근(Caddy·Suricata·TOTP·VPN) — 외부에 노출되기 시작한 뒤 세우는 능동 방어를 다룹니다. Caddy로 443 단일 진입점 리버스 프록시를 만들고(80/443 포트 충돌·Alternate Hostnames 트러블슈팅 포함), Suricata를 IDS로 시작해 1~2주 검증 후 IPS로 전환하며, 관리자 2FA(TOTP)를 걸고, 마지막으로 OpenVPN/WireGuard와 사이트 간 IPsec을 재구성합니다.