본문 바로가기
Tech/Dev Log

Nginx Proxy Manager에서 Access Lists 활용하기 — 셀프호스팅 보안의 첫걸음

by Hoft 2026. 3. 17.
320x100

홈랩이나 소규모 서버 환경에서 리버스 프록시를 운영하다 보면, "이 서비스는 나만 접속할 수 있게 하고 싶다"는 요구가 자연스럽게 생긴다. Nginx 설정 파일을 직접 편집하는 방식은 실수 가능성이 높고 관리가 번거롭다. Nginx Proxy Manager(이하 NPM)의 Access Lists 기능은 웹 UI에서 클릭 몇 번으로 IP 기반 접근 제어와 HTTP 기본 인증을 설정할 수 있게 해주는 기능이다.

이 글에서는 Access Lists의 정의와 작동 원리부터, 실전 설정 방법, 고급 활용 시나리오, 그리고 대안 도구와의 비교까지 다룬다.


1. Access Lists란 무엇인가

Access Lists는 NPM이 제공하는 접근 제어 메커니즘이다. 크게 두 가지 방식을 지원한다.

IP 기반 화이트리스트/블랙리스트: 특정 IP 주소 또는 CIDR 대역(예: 192.168.0.0/16)을 허용하거나 차단한다. 내부 네트워크에서만 접속 가능하게 만들거나, 특정 외부 IP를 차단하는 데 쓴다.

HTTP Basic Authentication: 사용자 이름과 비밀번호를 요구하는 인증 레이어를 추가한다. 브라우저 접속 시 로그인 팝업이 나타나며, 올바른 자격증명을 입력해야 프록시 대상 서비스에 접근할 수 있다.

이 두 방식은 개별 적용도 가능하고, "Satisfy Any" 옵션을 통해 둘 중 하나만 충족해도 접근을 허용하는 OR 조건으로 조합할 수도 있다.


2. 작동 원리

NPM은 내부적으로 OpenResty(Nginx 기반 확장 웹 서버)를 사용한다. Access Lists를 생성하면, NPM이 해당 설정을 Nginx의 allow, deny 디렉티브와 auth_basic 모듈 설정으로 자동 변환해서 적용한다.

요청 처리 흐름은 다음과 같다.

클라이언트 요청
    ↓
NPM (리버스 프록시) 수신
    ↓
해당 Proxy Host에 Access List가 적용되어 있는가?
    ├── Yes → IP 검증 + 인증 검증
    │       ├── 통과 → 백엔드 서비스로 포워딩
    │       └── 실패 → 403 Forbidden 또는 401 Unauthorized 반환
    └── No → 그대로 백엔드 서비스로 포워딩

Nginx 레벨에서 보면 대략 아래와 같은 설정이 자동 생성된다.

# IP 기반 접근 제어 (자동 생성되는 설정 예시)
allow 192.168.1.0/24;
allow 10.0.0.0/8;
deny all;

# HTTP Basic Auth (자동 생성되는 설정 예시)
auth_basic "Restricted";
auth_basic_user_file /data/access/<list_id>;

주의할 점이 하나 있다. NPM이 Docker 컨테이너로 동작할 경우, 클라이언트의 실제 IP가 아닌 Docker 브릿지 네트워크 IP(예: 172.17.0.1)로 인식될 수 있다. 이 경우 IP 기반 필터링이 제대로 동작하지 않는다. 이를 해결하려면 NPM 컨테이너를 network_mode: host로 실행하거나, X-Forwarded-For 헤더를 활용하는 real_ip 설정이 필요하다.


3. 실전 설정 가이드

3-1. Access List 생성

NPM 대시보드에서 Access Lists 탭으로 이동한 뒤 Add Access List 버튼을 클릭한다.

Details 탭 설정:

  • Name: 식별 가능한 이름 입력 (예: local-only, admin-auth)
  • Satisfy Any: 체크하면 IP 조건 OR 인증 조건 중 하나만 만족해도 허용. 미체크 시 AND 조건으로 동작

Authorization 탭 설정:

  • HTTP Basic Auth에 사용할 사용자 이름과 비밀번호를 등록한다
  • 여러 계정을 등록할 수 있다

Access 탭 설정:

  • allow할 IP 또는 CIDR 대역을 입력한다 (예: 192.168.1.0/24)
  • 마지막에 deny all을 추가하여 명시적으로 허용하지 않은 IP를 차단한다

3-2. Proxy Host에 Access List 적용

Hosts → Proxy Hosts에서 보호할 호스트를 선택하고, EditDetails 탭의 Access List 드롭다운에서 방금 만든 Access List를 선택한다. 저장하면 즉시 적용된다.

3-3. 로컬 네트워크 전용 접근 설정 예시

셀프호스팅에서 가장 많이 쓰이는 패턴은 "내부 네트워크에서만 접근 가능"하게 만드는 것이다. RFC 1918 사설 IP 대역을 모두 허용하는 Access List를 만든다.

Allow: 10.0.0.0/8
Allow: 172.16.0.0/12
Allow: 192.168.0.0/16
Deny: all

이렇게 설정하면 외부 인터넷에서는 접근할 수 없고, 로컬 네트워크 또는 VPN(WireGuard 등)을 통해 접속한 클라이언트만 서비스에 접근할 수 있다.


4. 고급 활용: Advanced 탭과 외부 인증 연동

4-1. Advanced 탭을 활용한 커스텀 Nginx 디렉티브

NPM의 기본 Access Lists는 Proxy Host 단위로만 적용된다. 특정 URL 경로(예: /wp-admin)만 보호하고 싶다면, Proxy Host 편집 화면의 Advanced 탭에서 커스텀 Nginx 설정을 직접 입력해야 한다.

location /wp-admin {
    allow 192.168.1.0/24;
    deny all;
    proxy_pass http://backend:80;
}

이 방식은 워드프레스 관리 페이지, API 엔드포인트, 모니터링 대시보드 등 세분화된 접근 제어가 필요한 경우에 유용하다. 다만 GitHub 이슈에서도 확인할 수 있듯이, Custom Location 탭에서 정의한 경로에는 Access Lists가 자동 적용되지 않으므로 주의가 필요하다.

4-2. Authelia / Authentik 연동으로 SSO 구현

NPM의 내장 Access Lists는 IP 필터링과 HTTP Basic Auth만 지원하기 때문에, MFA(다중 인증)나 SSO(싱글 사인온)가 필요하다면 외부 인증 서버와 연동해야 한다.

Authelia는 오픈소스 인증·인가 서버로, NPM과 함께 Docker 네트워크에서 실행하며 auth_request 모듈을 통해 통합된다. NPM의 Advanced 탭에 Nginx snippet을 삽입하는 방식으로 연동한다. 1FA(비밀번호) 또는 2FA(TOTP, 보안키)를 도메인 단위로 정책 적용할 수 있다.

Authentik은 더 풍부한 기능을 가진 IdP(Identity Provider)로, OIDC, SAML, LDAP 등 다양한 프로토콜을 지원한다. Forward Auth 모드를 통해 NPM과 연동하며, 마찬가지로 Advanced 탭에 커스텀 설정을 추가하는 방식이다.

두 도구 모두 NPM의 기본 Access Lists를 대체하거나 보완하는 역할을 한다. 서비스 수가 많고 사용자 관리가 필요하다면 이쪽이 더 적합하다.


5. 리버스 프록시 도구 비교

Access Lists 같은 접근 제어는 NPM만의 기능이 아니다. 다른 리버스 프록시들도 유사한 기능을 다른 방식으로 제공한다.

접근 제어 방식 웹 UI에서 Access List 생성 미들웨어(IPWhiteList 등) YAML 설정 Caddyfile에서 remote_ip matcher 사용
설정 난이도 낮음 (GUI 기반) 중간 (코드 기반, 학습곡선 있음) 낮음 (간결한 텍스트 설정)
동적 서비스 탐지 미지원 Docker 라벨 자동 탐지 caddy-docker-proxy로 가능
인증 미들웨어 Basic Auth만 내장 BasicAuth, ForwardAuth 미들웨어 basic_auth, forward_auth 지시자
로드 밸런싱 GUI에서 미지원 네이티브 지원 네이티브 지원
장애 격리 하나의 설정 오류 시 전체 중단 개별 라우트만 영향받음 개별 라우트만 영향받음

항목 Nginx Proxy Manager Traefik Caddy

NPM은 GUI 기반의 직관적인 관리가 장점이지만, 하나의 프록시 호스트 설정에 문제가 생기면 전체 Nginx 프로세스가 기동하지 않는 약점이 있다. Traefik은 동적 환경에 강하고, Caddy는 설정 간결성과 자동 HTTPS가 장점이다.


6. 주의사항과 트러블슈팅

Docker 환경에서의 IP 인식 문제: 앞서 언급했듯이, Docker 네트워크를 통해 들어오는 요청은 실제 클라이언트 IP가 아닌 Docker 게이트웨이 IP로 인식된다. NPM의 액세스 로그(/data/logs/proxy-host-<id>_access.log)를 확인해서 실제로 어떤 IP가 기록되는지 먼저 파악하는 것이 중요하다.

Basic Auth와 백엔드 인증의 충돌: NPM의 FAQ에서도 명시하고 있듯이, Access List의 Basic Auth와 백엔드 애플리케이션 자체의 인증이 모두 Authorization 헤더를 사용하는 경우 충돌이 발생할 수 있다. 이 경우 둘 중 하나의 인증이 작동하지 않게 된다.

Access List는 Proxy Host 단위: 하나의 프록시 호스트에는 하나의 Access List만 적용할 수 있다. 복수 조건이 필요하면 하나의 Access List 안에서 조합해야 한다.

정기적인 리뷰 필요: 동적 IP를 사용하는 환경이라면 화이트리스트가 무효화될 수 있다. Dynamic DNS 서비스를 활용하거나, VPN 기반 접근 방식으로 전환하는 것을 권장한다.


7. 전망과 마무리

NPM은 GitHub 기준 32,000개 이상의 스타를 가진 인기 오픈소스 프로젝트다. 다만 커뮤니티에서는 v3 업데이트가 오랫동안 진행 중인 점, CVE 대응 속도가 느린 점 등이 아쉬운 점으로 거론된다. 경로(location) 단위의 Access List 적용 기능도 GitHub 이슈로 요청되어 있지만 아직 구현되지 않은 상태다.

그럼에도 불구하고, 셀프호스팅 초심자나 소규모 서버 운영자에게 NPM의 Access Lists는 가장 쉽게 접할 수 있는 접근 제어 수단이다. GUI에서 몇 번의 클릭으로 IP 필터링과 인증을 설정할 수 있다는 점은 강력한 장점이다.

보안 요구 수준이 높아지면 Authelia나 Authentik 같은 외부 인증 서버를 연동하거나, Traefik이나 Caddy로 전환하는 것도 고려해볼 만하다. 중요한 것은 리버스 프록시 뒤에 있는 서비스라고 해서 안전한 것이 아니며, Access Lists든 다른 방법이든 반드시 접근 제어를 설정해야 한다는 점이다.


이 글은 Nginx Proxy Manager 공식 문서, GitHub 이슈, 그리고 커뮤니티 가이드를 참고하여 작성되었습니다.

반응형

▲ TOP