백엔드 접근 로그에 모든 요청이 같은 주소(프록시나 도커 브리지 게이트웨이)로 기록되는 상태다. 프록시를 거치면 백엔드 입장에서 접속자는 프록시이므로 당연한 결과이며, 원래 주소는 헤더로 전달해야 한다.
프록시에서 헤더를 실어 보낸다. NPM 의 Advanced 탭에 넣는다.
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
$proxy_add_x_forwarded_for 는 기존 헤더가 있으면 뒤에 덧붙인다. 프록시가 여러 단이면 값이 쉼표로 이어진다.
백엔드에서도 그 헤더를 신뢰하도록 설정해야 반영된다.
# 백엔드가 Nginx 인 경우
set_real_ip_from 172.29.0.0/16; # 프록시가 오는 대역만
real_ip_header X-Forwarded-For;
real_ip_recursive on;
# 백엔드가 Apache 인 경우
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 172.29.0.0/16
신뢰 대역을 반드시 지정한다. 아무 출발지의 X-Forwarded-For 를 믿으면 클라이언트가 IP 를 위조할 수 있고, IP 기반 접근 제어나 차단이 무력해진다.
도커로 운영한다면 프록시 컨테이너가 백엔드에게 보이는 주소를 확인해 그 대역을 넣는다.
docker network inspect <network> | grep -E 'Name|Subnet|IPv4Address'
docker exec -it <backend> sh -c 'tail -5 /var/log/nginx/access.log'
애플리케이션별 설정도 있다. Nextcloud 는 trusted_proxies 와 forwarded_for_headers, WordPress · Django 등은 각자의 프록시 설정을 따른다.
413(Request Entity Too Large) 또는 업로드 도중 끊김이 나면 프록시와 백엔드 양쪽을 본다.
client_max_body_size 10G;
proxy_request_buffering off;
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
client_body_timeout 300s;
send_timeout 300s;
각 값의 의미는 다음과 같다.
| 지시자 | 뜻 |
|---|---|
client_max_body_size |
허용할 요청 본문 최대 크기. 0 이면 무제한 |
client_body_buffer_size |
본문을 메모리에 담는 크기. 넘으면 임시 파일로 간다 |
proxy_request_buffering |
요청을 다 받은 뒤 백엔드로 보낼지 여부 |
proxy_read_timeout |
백엔드 응답 무통신 허용 시간 |
client_body_buffer_size 를 수백 MB 로 잡는 설정을 종종 보는데 권장되지 않는다. 동시 업로드가 여러 건이면 그만큼 메모리를 점유한다. 기본값(수십 KB 수준)이나 수 MB 로 두고, 큰 본문은 디스크 임시 파일로 흘리는 편이 안전하다. 임시 파일 경로(/var/lib/nginx/tmp 등)의 여유 공간이 업로드 크기를 감당해야 한다.
proxy_request_buffering off 를 켜면 받는 즉시 백엔드로 흘려보내 프록시 디스크를 쓰지 않는다. 대용량에서는 유리하지만 백엔드가 느린 클라이언트에 직접 묶이므로 상황에 따라 선택한다.
프록시만 키워도 백엔드 한계에 걸리면 그대로 실패한다.
; PHP
upload_max_filesize = 10G
post_max_size = 10G
memory_limit = 512M
max_execution_time = 3600
max_input_time = 3600
Tomcat 은 maxPostSize, 스프링은 spring.servlet.multipart.max-file-size 를 본다. Nextcloud 는 PHP 설정과 함께 .htaccess · config.php 의 값이 관여한다.
# 실제 용량으로 시험
dd if=/dev/zero of=/tmp/test.bin bs=1M count=2048
curl -T /tmp/test.bin -u <user> https://app.example.com/upload/ -w '%{http_code}\n'
# 413 이면 프록시 또는 백엔드 한계
docker exec -it npm nginx -t
docker logs npm --tail 50
브라우저에서 진행률이 100% 까지 갔다가 실패하면 대개 백엔드 처리 시간 초과(proxy_read_timeout)이고, 중간에 끊기면 크기 제한이다.