1393 words
7 minutes
[Web]웹서버 수준에서의 요청 핸들링
2024-10-29
2025-10-12

01. 오리진 모델#

SOP 개념#

  • Same Origin Policy는 브라우저 레이어의 핵심 보안 메커니즘
  • 기본적으로 한 오리진에서 로드된 리소스가 다른 오리진과 상호작용하는 것을 막는다
  • SOP로 제한하는 것들
    • DOM 접근
    • js를 통한 크로스오리진 요청
    • Web Storage , Indexed DB접근

오리진#

  • 오리진은 다음 세 가지 요소의 조합이다.
    • scheme(프로토콜)
    • host
    • port
scheme://host:port
오리진 비교:
https://example.com:443/path ← 기준 URL
같은 오리진:
- https://example.com/other (443 포트 생략)
- https://example.com:443/api
다른 오리진:
- http://example.com (scheme 다름)
- https://api.example.com (host 다름)
- https://example.com:8443 (port 다름)

Concept

  • Same Origin Policy : 브라우저가 한 오리진의 스크립트가 다른 오리진의 리소스에 접근하는 것을 제한하는 일종의 보안 정책
  • scheme : url의 프로토콜 부분(https, http)
  • host : 도메인명 또는 ip주소
  • CSRF : Cross-Site Request Forgery. 사용자의 의도와 무관하게 공격자가 요청을 위조하는 공격
  • Content Security Policy (CSP): SOP를 보완하는 추가 보안 레이어

02. CORS & Preflight#

CORS#

  • CORS(Cross Origin Resource Sharing)은 서버가 명시적으로 허용한 경우에만 크로스 오리진을 가능하게 하는것

CORS 응답헤더 예제#

오리진 수준

# 특정 오리진만 허용( 정적 cors)
add_header Access-Control-Allow-Origin "https://app.allowed.com";
# 모든 오리진 허용
add_header Access-Control-Allow-Origin "*";
# 동적 cors (요청 오리진. 클라이언트가 보낸 오리진을 허용)
add_header Access-Control-Allow-Origin $http_origin;
# Vary: Origin은 CDN/Proxy에게 origin별 별도 캐싱을 지시
# 동적 cors 사용 시 필수
add_header Vary "Origin"
# 조건부 cors
map $http_origin $cors_origin {
default "";
"https://app.example.com" $http_origin;
"https://admin.example.com" $http_origin;
}
location /api {
add_header Access-Control-Allow-Origin $cors_origin;
add_header Vary "Origin"; # 여전히 필요함
# 허용되지 않은 오리진은 빈 응답 → 이것도 캐시됨
}

메서드 수준

# 허용할 HTTP 메서드 명시
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";

헤더 수준

add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Request-ID";

그 외 옵션

# 쿠키/인증 정보 포함 허용 (Origin이 * 이면 안됨)
add_header Access-Control-Allow-Credentials "true";
# 프리플라이트 응답 캐시 시간 (초)
add_header Access-Control-Max-Age "86400"; # 24시간

프리플라이트(Preflight)#


Concept

  • CORS Resource Sharing, SOP를 안전하게 완화하는 W3C 표준
  • 프리플라이트 요청 : 실제 요청 전 OPTIONS 메서드로 권한을 확인하는 사전 요청
  • 단순 요청 : GET/HEAD/POST + 기본 헤더만 사용하는 프리플라이트가 불필요한 요청
  • 비단순 요청 : JSON, 커스텀 헤더, PUT/DELETE 등 프리플라이트가 필요한 요청
  • Vary Origin: 오리진별로 다른 응답을 캐시하도록 지시하는 옵션
  • $http_origin: NGINX 변수, 요청의 Origin 헤더 값

몇가지 CORS/Preflight 패턴들#

1. 오리진 허용 패턴

# $http_origin을 그대로 반사 - 모든 오리진 허용
location /api {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin $http_origin always;
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header Access-Control-Allow-Headers 'Content-Type, Authorization' always;
add_header Access-Control-Max-Age 86400;
return 204; # 요청이 성공했지만 서버에서 반환할 정보가 없음
}
add_header Access-Control-Allow-Origin $http_origin always;
proxy_pass http://backend;
}

2. White List 패턴

# map을 이용한 허용 오리진 관리
map $http_origin $cors_origin {
default "";
"https://app.example.com" $http_origin;
"https://admin.example.com" $http_origin;
"http://localhost:3000" $http_origin;
}
location /api {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin $cors_origin always;
# etc..
return 204;
}
add_header Access-Control-Allow-Origin $cors_origin always;
proxy_pass http://backend;
}

3. asdfjaha 4. asdfjaha

실제 업무용 세팅은 이거보다는 복잡하지만 몇가지 패턴이 정해져있어서 그거 중심으로 보면 된다.

03. 리버스 프록시#

Unsorted#


Concept

  • Preflight(프리플라이트) : 크로스 오리진의 비단순 요청 전에 브라우저가 OPTIONS로 서버 허용을 미리 확인하는 절차.
  • proxy_pass : 현재 location으로 들어온 요청을 보낼 업스트림(목적지) 지정.
  • proxy_set_header Host … : 업스트림에 보낼 Host 헤더를 지정(가상호스트/SNI 선택에 영향).
  • proxy_ssl_server_name on : 업스트림 HTTPS 연결 시 SNI 확장에 서버 이름을 포함하여 올바른 인증서 선택 유도.
  • proxy_http_version 1.1 : 업스트림과의 프록시 연결을 HTTP/1.1로 사용(keep-alive, chunked 등 지원).
  • X-Real-IP : 업스트림에 전달하는 직전 클라이언트 IP(로그/감사용).
  • X-Forwarded-For : 프록시 체인을 따라 누적된 클라이언트 IP 목록(표준 관례).
  • X-Forwarded-Proto : 원 요청의 스킴(HTTP/HTTPS) 정보 전달.
  • X-Forwarded-Host : 원 요청의 호스트(도메인/IP) 전달.
  • X-Forwarded-Port : 원 요청의 포트 전달.
  • X-Forwarded-Prefix : 프록시 뒤에서 서비스가 놓인 서브경로를 백엔드에 알림(경로 보정용).
  • proxy_redirect : 업스트림이 응답한 Location 절대 URL을 현재 스킴/호스트 등으로 재작성.
  • port_in_redirect off : 리다이렉트 URL에 불필요한 포트 번호 추가를 방지.
  • proxy_cookie_domain : Set-Cookie의 도메인을 클라이언트 호스트로 보정.
  • proxy_cookie_path : Set-Cookie의 경로를 프록시 서브경로로 보정.
  • OPTIONS 204 처리 : 프리플라이트 요청을 프록시에서 즉시 204로 응답하여 백엔드 도달 전 허용.
  • Access-Control-Allow-* 헤더 : 프리플라이트/실요청에 오리진/메서드/헤더/자격증명 허용 범위를 명시.
  • proxy_intercept_errors on : 업스트림 에러를 프록시에서 가로채 자체 처리 가능.
  • error_page 404 = /index.html : SPA에서 라우트 미스 시 index.html로 내부 리라이트.
  • SNI : TLS에서 클라이언트가 접속하려는 호스트명을 전송해 서버가 올바른 인증서를 선택하도록 하는 확장.
  • cert-manager(개념) : Kubernetes에서 인증서 발급/갱신을 자동화하는 컨트롤러(예: Let’s Encrypt 연동).

[Web]웹서버 수준에서의 요청 핸들링
https://yjinheon.netlify.app/posts/03be/01web-server/nginx/
Author
Datamind
Published at
2024-10-29
License
CC BY-NC-SA 4.0