나의 잡다한 노트 및 메모

nginx의 request rewrite, response rewrite 본문

DevOps/Reverse_proxy

nginx의 request rewrite, response rewrite

peanutwalnut 2025. 3. 19. 19:56

1. 요청(request) 리라이트

  • 요청 리라이트는 클라이언트가 보낸 HTTP 요청을 받아서, 백엔드 서버(예: Jenkins)에 전달할 때 필요한 경우 일부 HTTP 헤더를 수정하거나 추가하는 과정을 말합니다.
  • 예를 들어, 클라이언트가 Host: nice.name 으로 요청을 보내면, 프록시가 이 정보를 Jenkins에 전달할 때 그대로 전달하거나, X-Forwarded-* 헤더로 전달하여 Jenkins가 클라이언트의 원래 요청 정보를 알 수 있게 합니다.
  • 잘못 구성된 요청 리라이트는 대개 페이지 자체가 전혀 표시되지 않는 등의 명백한 문제를 일으킵니다.

 

2. 응답(response) 리라이트의 필요성

리버스 프록시의 가장 어려운 부분은 응답에서의 리라이트인데, 특히 리다이렉트 상황에서 발생합니다.

옵션 1: 응답의 "Location" 헤더 재작성

  • 상황:
    Jenkins가 리다이렉트를 위해 응답의 "Location" 헤더를 보낼 때, 기본적으로는 자신의 내부 주소(예: http://actual.server:8080/jenkins/foobar)를 사용합니다.
  • 문제점:
    클라이언트는 외부에서 접근할 때 nice.name 같은 공개된 도메인을 사용하기 때문에, 이 내부 주소로 리다이렉트되면 접근할 수 없게 됩니다.
  • 해결:
    리버스 프록시가 이 응답의 "Location" 헤더를 수정해서 http://nice.name/jenkins/foobar와 같이 공개 도메인으로 바꿔 줍니다.
  • 특징:
    이 방법은 요청 자체는 잘 전달되지만, 응답에 포함된 절대 URL이 잘못되면 클라이언트가 페이지를 리다이렉트할 때 문제가 생깁니다. 단, 페이지가 아예 보이지 않는 문제보다는 발견하기 어려운 문제입니다.

옵션 2: X-Forwarded-* 헤더 사용

  • 상황:
    리버스 프록시는 요청을 백엔드에 전달할 때, X-Forwarded-Host, X-Forwarded-Port (필요하다면) 그리고 X-Forwarded-Proto 등의 헤더를 설정할 수 있습니다.
  • 작동 방식:
    Jenkins는 이 헤더들을 확인하여, 자신이 생성하는 모든 리다이렉트나 링크를 이 값들을 기준으로 만듭니다. 즉, 클라이언트가 원래 요청한 호스트와 프로토콜을 반영하게 됩니다.
  • 예시:
    • 클라이언트가 https://nice.name으로 요청을 보냈다면, 프록시가 요청을 Jenkins에 전달할 때 X-Forwarded-Host: nice.name 및 X-Forwarded-Proto: https와 같이 설정합니다.
    • 그러면 Jenkins는 리다이렉트 시 "Location: https://nice.name/jenkins/foobar"와 같이 올바른 URL을 생성하게 됩니다.
  • 세부 옵션:
    • 어떤 경우에는 단순히 원래의 Host 헤더를 X-Forwarded-Host에 복사하는 방식이 편리할 수도 있고, 경우에 따라 X-Forwarded-Port 헤더를 아예 생략하는 편이 나을 수도 있습니다.
    • 만약 프록시와 클라이언트 간의 프로토콜(HTTP/HTTPS)이 다르다면, X-Forwarded-Proto를 꼭 설정해야 합니다.