활용팁/정보

Synology DSM 7.4 업그레이드 문제점 과 해결방안

컨텐츠 정보

본문

802ee1c81c257fbe6e9128949403a6aa_1787792273_8653.jpg

 

# DSM 7.4 업그레이드 후 NPM 뒤에서 운영되는 웹사이트 에서 공통 으로 발생하는 네트워크 계층 문제

고객사 에서 기존에 WebStation를 통해 웹사이트를 운영 하던중 DSM 7.4 업그레이드 이후 php7.4 미지원 으로 Docker 기반 웹서비스로 전환한 작업을 완료한 이후 발생한 외부 방문자의 실제 공인 IP가 웹서버까지 전달되지 않고 Docker 게이트웨이 주소인172.21.0.1로 기록되는 문제가 확인이 되었습니다. 이를 해결한 내용을 회원(사) 포함 공개로 전환해 공유 합니다.  본 문제는 발생은 Docker bridge를 통과하면서 실제 IP가 172.21.0.1로 바뀌어 하나로 표시 되는 문제이로 그누보드·나리야·아미나, WordPress, PHP 자체 제작 사이트, Laravel·Node.js 등의 웹 애플리케이션, Immich 각종 관리자 페이지와 API Nginx·Apache 접속 로그 보안 플러그인과 방문자 통계 도구 등 모두 영향을 받게 됩니다.



★ 확인 결과 Docker bridge 포트 전달 계층이 문제 였습니다.

외부 방문자

→ 공유기

→ NAS의 Docker 게시 포트

→ docker-proxy / bridge NAT

→ NPM

→ 내부 웹서버


1. 해결을 위해 host 네트워크의 HAProxy를 입구에 추가하고, 원본 IP를 PROXY protocol로 기존 NPM에 전달하도록 구성했습니다.

외부 방문자

→ host 모드 HAProxy

→ PROXY protocol

→ 기존 bridge 모드 NPM

→ Docker Nginx

→ PHP·그누보드

결과적으로 실제 방문자 IP 보존과 헤더 위조 차단을 모두 달성했습니다.



2. 기존 운영 구성

외부 요청은 다음과 같이 전달되고 있었습니다.

공유기 외부 80  → NAS 8080 → NPM 80

공유기 외부 443 → NAS 4443 → NPM 443

NPM 구성:

항목

기존 설정

이미지

jc21/nginx-proxy-manager:2.15.1

네트워크

proxy-netbridge

관리 포트

81:81

HTTP

8080:80

HTTPS

4443:443

NPM IP

172.21.0.4

데이터

/volume1/docker/npm/data

인증서

/volume1/docker/npm/letsencrypt


웹사이트와 SSL은 모두 정상이었지만 NPM이 받는 접속자의 주소가 실제 공인 IP가 아닌 172.21.0.1로 바뀌었습니다.



3. 문제의 영향

웹사이트 서비스 자체에는 장애가 없었지만 다음 기능의 신뢰도가 떨어졌습니다.

  • 그누보드 방문자 실제 IP 기록
  • IP 기준 중복 방문자 판별
  • 관리자 접속자 현황
  • 공격자 및 비정상 접속 추적
  • IP 차단과 접근 제어
  • 국가·지역 기반 통계
  • 보안 로그 분석

즉, 사이트는 정상적으로 열리지만 방문자 식별과 보안 기록이 부정확한 상태였습니다.



4. 단순 헤더 설정으로 해결되지 않은 이유

일반적으로 다음 헤더를 사용해 실제 IP를 전달합니다.

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

그러나 현재 환경에서는 NPM이 요청을 받기 전에 실제 IP가 이미 172.21.0.1로 변환됐습니다.

실제 IP

→ Docker 포트 전달 과정에서 172.21.0.1로 변경

→ NPM이 172.21.0.1만 인식

따라서 NPM이 전달할 수 있는 $remote_addr자체가 잘못된 상태였습니다. 사라진 원본 IP는 Nginx나 PHP 설정만으로 복구할 수 없습니다.

또한 외부에서 다음 헤더를 임의로 보내는 실험도 진행했습니다.

X-Real-IP: 203.*.***.**

X-Forwarded-For: 198.**.***.**

기존처럼 전달 헤더를 무조건 신뢰하면 방문자가 가짜 IP를 기록하게 만들 수 있으므로 보안상 사용할 수 없었습니다.



5. host 모드 가능성 검증

운영 NPM을 바로 변경하지 않고, host 네트워크에서 18080포트로 동작하는 일회용 Nginx를 생성했습니다.

LAN 테스트

Mac에서 접속한 결과:

192.168.*.102

Docker 게이트웨이가 아닌 Mac의 실제 내부 IP가 기록됐습니다.

LTE 외부 테스트

스마트폰 Wi-Fi를 끄고 LTE로 접속한 결과:

106.***.*.***

NAS의 공인 IP는 확인 결과 다음과 같았습니다.

211.***.**.***

테스트 Nginx 로그에는 스마트폰 LTE/5G의 실제 공인 IP인 106.***.*.***가 정확하게 기록됐습니다.

이를 통해 다음 사실이 증명됐습니다.

  • DSM 7.4가 원본 IP를 무조건 제거하는 것은 아님
  • NAS 본딩이 원인은 아님
  • host 네트워크에서는 원본 IP가 보존됨
  • 실제 IP 손실은 Docker bridge 게시 포트 경로에서 발생



6. NPM 자체를 host 모드로 변경하지 않은 이유

NPM은 컨테이너 내부에서 기본적으로 다음 포트를 사용합니다.

80

81

443

하지만 NAS의 80/443은 DSM 시스템 nginx가 사용하고 있었습니다.

/usr/bin/nginx -c /etc/nginx/nginx.conf.run

DSM 시스템 nginx는 다음 기능과 연관될 수 있습니다.

  • Web Station
  • DSM 역방향 프록시
  • Immich 테스트용 역방향 프록시
  • Synology 웹 패키지
  • MailPlus 웹 접속
  • 인증서와 로그인 포털

따라서 NPM 자체를 host 모드로 바꾸면 DSM nginx와 포트 충돌이 발생합니다.

또한 host 모드 NPM은 기존 proxy-net의 Docker DNS와 컨테이너 이름 연결을 잃을 수 있습니다.

theon-nginx

careon-nginx

immich_server

이런 내부 컨테이너 이름을 계속 사용하려면 NPM은 기존 bridge 네트워크에 남아 있는 편이 안전했습니다.



7. 최종 해결 구조

NPM 앞에 host 네트워크의 HAProxy를 추가했습니다.

인터넷

→ 공유기

→ host 모드 HAProxy

→ PROXY protocol

→ bridge 모드 NPM

→ Docker 웹서버

포트 구성은 다음과 같이 변경했습니다.

구분

변경 전

변경 후

공유기 HTTP

NAS 8080

그대로

공유기 HTTPS

NAS 4443

그대로

HAProxy HTTP

없음

0.0.0.0:8080

HAProxy HTTPS

없음

0.0.0.0:4443

NPM HTTP

0.0.0.0:8080

127.0.0.1:18080

NPM HTTPS

0.0.0.0:4443

127.0.0.1:18443

NPM 관리

0.0.0.0:81

그대로


NPM의 HTTP·HTTPS 포트는 이제 NAS 외부나 LAN에서 직접 접근할 수 없고, 로컬 HAProxy만 접근할 수 있습니다.

이 구조는 위조된 PROXY protocol 요청이 외부에서 NPM으로 직접 들어오는 것도 막아줍니다.



8. HAProxy 역할

HAProxy는 HTTP나 HTTPS 내용을 수정하거나 인증서를 관리하지 않습니다.

주요 역할은 두 가지입니다.

  1. host 네트워크에서 실제 외부 IP를 직접 수신
  2. 원본 IP를 PROXY protocol v2에 넣어 NPM으로 전달

HTTP 경로:

HAProxy :8080

→ 127.0.0.1:18080

→ NPM :80

HTTPS 경로:

HAProxy :4443

→ 127.0.0.1:18443

→ NPM :443

HTTPS 암호화 종료, 인증서 선택, 도메인 분기, Force SSL 등의 기존 기능은 계속 NPM이 담당합니다.



9. NPM 변경 사항

NPM 2.15.1의 기본 템플릿은 다음과 같이 동작합니다.

listen 80;

listen 443 ssl;

real_ip_header X-Real-IP;

전용 이미지를 생성해 다음과 같이 변경했습니다.

listen 80 proxy_protocol;

listen 443 ssl proxy_protocol;

real_ip_header proxy_protocol;

패치 대상:

/app/templates/_listen.conf

/app/templates/default.conf

/app/templates/letsencrypt-request.conf

/etc/nginx/conf.d/default.conf

/etc/nginx/nginx.conf

기존에 생성돼 있던 NPM Proxy Host 설정도 시작 스크립트에서 자동 변환하도록 구성했습니다.

따라서 다음 상황에서도 PROXY protocol 설정이 유지됩니다.

  • NPM 컨테이너 재생성
  • NAS 재부팅
  • Proxy Host 수정 및 저장
  • 새로운 Proxy Host 생성
  • Let’s Encrypt 인증서 발급·갱신
  • 기본 호스트 응답



10. 주요 파일 위치

/volume1/docker/npm/compose.yaml

/volume1/docker/npm/compose.proxyproto.yaml

/volume1/docker/npm/haproxy/haproxy.cfg

/volume1/docker/npm/proxyproto/Dockerfile

/volume1/docker/npm/proxyproto/proxyproto-entrypoint.sh

/volume1/docker/npm/data

/volume1/docker/npm/letsencrypt

전환 전 백업:

/volume1/docker/npm/backups/manual/

NPM 폴더 전체가 Hyper Backup 대상이므로 새 HAProxy 설정과 전용 이미지 파일도 함께 백업됩니다.



11. 최종 검증 결과

전체 도메인

theon.kr        HTTP=200

studio.theon.kr HTTP=200

careon.kr       HTTP=200

mail.theon.kr   HTTP=200

컨테이너

npm          running / healthy

npm-haproxy  running / healthy

실제 LTE IP 전달

NPM 로그:

[Client 106.***.*.***]

내부 웹서버 로그:

106.***.*.***

두 계층에 동일한 LTE 공인 IP가 기록됐습니다.

IP 위조 테스트

요청에 가짜 헤더를 포함했습니다.

X-Real-IP: 203.0.113.77

X-Forwarded-For: 198.51.100.88

결과:

NPM:        127.0.0.1

내부 Nginx: 127.0.0.1

가짜 IP는 모두 무시되고 PROXY protocol이 전달한 실제 접속 주소만 사용됐습니다.

Nginx 설정 검사

syntax is ok

test is successful

PROXY protocol이 누락된 80/443수신 설정도 존재하지 않습니다.



12. 운영 시 주의사항

공유기 포트포워딩 유지

다음 설정을 그대로 유지해야 합니다.

외부 80  → NAS 8080

외부 443 → NAS 4443

NPM 내부 포트를 직접 외부에 공개하지 않기

다음 포트는 반드시 loopback 상태를 유지해야 합니다.

127.0.0.1:18080

127.0.0.1:18443

외부 또는 LAN 전체에 공개하면 PROXY protocol 위조 가능성이 생길 수 있습니다.

NPM 버전 업그레이드

현재 전용 이미지는 다음 버전에 맞춰져 있습니다.

Nginx Proxy Manager 2.15.1

향후 NPM을 업데이트할 때 원본 이미지만 바로 교체하면 안 됩니다. 새 버전에서 다음 항목을 먼저 확인해야 합니다.

  • NPM 템플릿 경로 변경 여부
  • listen구문 변경 여부
  • nginx.conf구조 변경 여부
  • Let’s Encrypt 임시 설정 변경 여부
  • 전용 Dockerfile 재빌드
  • 독립 테스트 컨테이너 검증
  • 실제 전환 전 백업

장애 시 우선 확인

cd /volume1/docker/npm


docker compose ps

docker logs --tail 100 npm

docker logs --tail 100 npm-haproxy

docker exec npm nginx -t

포트 확인:

netstat -lntp |

grep -E ':(81|8080|4443|18080|18443) '



13. 최종 평가

이번 문제는 단순 Nginx 헤더 수정으로 해결할 수 있는 문제가 아니었습니다. 실제 IP가 NPM에 도달하기 전에 Docker bridge 계층에서 이미 사라졌기 때문입니다.

해결의 핵심은 다음 세 가지였습니다.

  1. host 모드에서 실제 공인 IP가 보존되는지 독립 실험
  2. NPM을 host 모드로 바꾸지 않고 HAProxy만 host 모드로 운영
  3. 신뢰할 수 있는 PROXY protocol을 사용해 기존 NPM으로 원본 IP 전달

결과적으로 DSM Web Station, Immich, MailPlus, 본딩, 공유기 설정과 기존 Docker 네트워크를 유지하면서 방문자 실제 IP 문제를 안전하게 해결했습니다.

이 페이지의 QR코드 입니다.


QR Code

   

관련자료

댓글 0
등록된 댓글이 없습니다.
전체 101 / 1 페이지
RSS
번호
제목
이름
알림 0