* 이 게시물은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
(pfSense 홈랩 방화벽 ㉔)
내부에 웹 서비스가 여러 개면, 포트포워딩으로 8080, 8443… 포트를 줄줄이 여는 건 지저분하고 위험하다. 더 나은 방법은 리버스 프록시 하나를 443 앞에 세우고, 요청한 도메인에 따라 내부의 알맞은 서비스로 나눠 보내는 거다. pfSense는 이 일을 HAProxy 패키지로 한다.
graph TD U([외부 사용자]) --> HP[HAProxy : 443] HP -->|a.example.com| S1[내부 웹 A] HP -->|b.example.com| S2[내부 웹 B] HP -->|/api| S3[내부 API]
설정 흐름
- 구체 값으로 따라가 보자. HAProxy와 ACME 패키지를 설치한다.
- 백엔드에 내부 서버(IP:포트)들을 등록한다.
- 프런트엔드를 443에 열고, 도메인 규칙(ACL)으로 어떤 요청을 어느 백엔드로 보낼지 정한다.
- ACME로 인증서를 발급해 프런트엔드에 붙인다.
✅ 확인 — 외부에서 서로 다른 도메인으로 접속했을 때 각각 다른 내부 서비스가 열리면 리버스 프록시 성공이다. 포트포워딩을 잔뜩 여는 것 대비 리버스 프록시의 장점을 설명해 보자.
각 단계의 실제 설정 값은 이런 모양이다.
[Backend] 이름: wp_backend
서버: wp1 / 192.168.10.20:80 / 헬스체크 HTTP GET /
[Frontend] 이름: https_in / 수신: WAN:443 / 타입: http, SSL Offloading 체크
ACL: 이름 host_blog / 조건 Host matches / 값 blog.example.com
Action: Use Backend wp_backend ← 조건 host_blog일 때
인증서: ACME로 발급한 blog.example.com 선택
[ACME] 검증: DNS-01(권장 — 80포트 안 열어도 됨, 와일드카드 가능)
또는 HTTP-01(80 포트가 HAProxy로 와야 함)
서비스가 늘면 ACL + Use Backend 쌍만 하나씩 추가하면 된다 — 포트는 여전히 443 하나다. ACME 검증 방식은 DNS 제공자 API가 지원되면 DNS-01이 편하다.
프런트엔드·백엔드 — 설정의 두 축
HAProxy 설정은 프런트엔드(외부에서 받는 쪽)와 백엔드(내부 서버로 보내는 쪽)로 나뉜다. 프런트엔드는 443에서 요청을 받아 도메인(Host 헤더/SNI)이나 경로를 보고 어느 백엔드로 보낼지 규칙(ACL)으로 판단한다. 백엔드는 실제 내부 서버(IP:포트)의 목록이다. 이 둘을 잇는 게 리버스 프록시의 뼈대다.
SSL 종료 — 인증서를 한곳에서
큰 이점 하나. HAProxy가 443에서 HTTPS를 받아 복호화하고(SSL termination) 내부엔 평문이나 재암호화로 보낸다. 그러면 인증서를 서비스마다 관리할 필요 없이 HAProxy 한곳에서 관리한다(22편, ACME로 Let’s Encrypt 자동 갱신). 내부 서비스는 인증서의 존재조차 몰라도 된다.
cozlab도 이렇게 — 실제 구성
이 블로그도 Cloudflare → HAProxy → 내부 서비스 구조로 돈다. HAProxy가 도메인별로 워드프레스와 다른 서비스를 갈라 보낸다. 한 가지 디테일 — 프록시를 거치면 서버 로그엔 방문자 IP 대신 프록시 IP가 찍힌다. 그래서 X-Forwarded-For 헤더로 진짜 IP를 전달하고, 백엔드가 그 헤더를 읽도록 맞춰야 한다. 로그와 보안에서 놓치면 안 되는 지점이다.
헬스체크와 로드밸런싱
HAProxy는 백엔드 서버가 살아 있는지 주기적으로 확인(health check)해, 죽은 서버로는 안 보낸다. 같은 서비스를 여러 대 두면 부하를 나누는 로드밸런서로도 쓴다. 홈랩 초반엔 도메인 라우팅만으로 충분하지만, 서비스가 늘고 무중단이 중요해지면 이 기능이 진가를 발휘한다. 포트를 줄줄이 여는 대신 문 하나(443)로 깔끔하게 정리하는 게 리버스 프록시의 값어치다.
서비스를 잘 공개했으니, 다음 편은 그 트래픽의 품질을 다룬다. 대역폭을 나누고 우선순위를 주는 QoS다.
🔧 현장에서 — 리버스프록시 뒤에선 실사용자 IP가 사라진다
ALB나 리버스프록시 뒤에서 애플리케이션·Nginx가 보는 Client IP가 실제 사용자가 아니라 Proxy IP가 되는 문제를 겪었다. X-Forwarded-For를 쓰고 real IP 설정을 잡되, 외부 Client가 이 헤더를 임의로 넣을 수 있으니 Trusted Proxy 범위도 반드시 같이 설정해야 한다.
교훈 — X-Forwarded-For를 무조건 신뢰하면 IP 스푸핑 문제가 생긴다.
🔧 현장에서 — DNS 정상 ≠ HTTP 정상
Cloudflare Wildcard CNAME을 걸었는데 특정 내부 서비스에서 503이 났다. DNS는 정상 resolve되는데 서비스가 응답을 안 했다. DNS Resolution → Cloudflare Proxy 여부 → HAProxy Backend → Origin Port → Host Header → Backend Health 순으로 하나씩 추적해 원인을 좁혔다.
교훈 — DNS가 정상이라고 해서 그 뒤 HTTP 서비스까지 정상인 것은 아니다.
자주 묻는 질문 (FAQ)
리버스 프록시가 왜 필요한가요?
하나의 공인 IP·포트로 여러 내부 서비스를 도메인별로 분기합니다. 포트를 여러 개 열 필요 없이 443 하나로 처리합니다.
cozlab도 이렇게 운영하나요?
네, 이 블로그도 Cloudflare→HAProxy 뒤에서 돌아갑니다. HAProxy가 도메인별로 백엔드를 라우팅하고 HTTPS를 종단합니다.

답글 남기기