들어가며

  • 웹 프락시 서버는 중개자 역할로 클라이언트와 서버 사이에 위치하여 그들 사이의 HTTP 메시지를 정리하는 중개인처럼 동작
  • 다룰 내용
    • HTTP 프락시와 웹 게이트웨이를 비교하고 HTTP 프락시가 어떻게 배치되는지 설명
    • 활용방법
    • 프락시가 실제 네트워크에 어떻게 배치되어 있는지, 트래픽이 어떻게 프락시 서버로 가게 되는지 설명
    • 브라우저에서 프락시를 사용하려면 어떻게 설정해야 되는지
    • HTTP 프락시 요청이 서버 요청과 어떻게 다른지, 그리고 프락시가 어떻게 브라우저의 동작을 미묘하게 바꾸는지 보여준다.
    • 일련의 프락시 서버들을 통과하는 메시지의 경로를, Via 헤더와 TRACE 메서드를 이용해 기록하는 방법 설명
    • 프락시에 기반한 HTTP 접근 제어 설명
    • 어떻게 프락시가 클라이언트와 서버 사이에서 각각의 다른 기능과 버전들을 지원하면서 상호작용 할 수 있는지 설명

6.1 웹 중개자

  • 웹 프락시가 있다면, 클라이언트는 직접 HTTP 서버와 이야기하는 대신, 자신의 입장에서 서버와 대화해주는 프락시와 대화한다.
  • 프락시는 HTTP 클라이언트의 요청을 받게 되므로, 반드시 웹 서버처럼 요청과 커넥션을 적절히 다루고 응답을 돌려줘야 한다.
  • 프락시는 요청을 서버로 보내기도 하므로, 요청을 보내고 응답을 받는 올바른 HTTP 클라이언트처럼 동작해야 한다.

  • 개인 프락시와 공유 프락시
    • 하나의 클라이언트만을 위한 프락시를 개인 프락시, 여러 클라이언트가 함께 사용하는 프락시는 공용 프락시
  • 프락시 대 게이트웨이
    • 프락시는 같은 프로토콜을 사용하는 둘 이상의 애플리케이션을 연결
    • 게이트웨이는 서로 다른 프로토콜을 사용하는 둘 이상을 연결
    • 하지만 둘의 차이는 모호하다.
      • 프락시는 다른 HTTP 버전을 연결하기 때문에 프로토콜을 약간 변환하기도 한다.
      • 상용 프락시는 SSL, FTP 등 웹 어플리케이션을 지원하기 때문에 게이트웨이 기능을 구현하기도 한다.

6.2 왜 프락시를 사용하는가?

  • 보안 개선, 성능, 비용 절약, 트래픽 감시 및 수정 등을 위해 사용된다.

  • 어린이 필터
    • 성인 콘텐츠를 차단하기 위해 필터링 프락시 사용
  • 문서 접근 제어자
    • 프락시 서버는 많은 웹 서버들과 리소스에 대한 단일한 접근 제어 전략을 구현하고 감사 추적을 하기 위해 사용
  • 보안 방화벽
    • 프락시 서버는 조직안에 들어오가나 나가는 응용 레벨 프로토콜의 흐름을 네트워크의 한 지점에서 통제 가능
    • 트래픽을 세심히 살펴볼 수 있는 후크(hook)를 제공
  • 웹 캐시
    • 프락시 캐시는 인기 있는 문서의 로컬 사본을 관리하고 해당 문서에 대한 요청이 오면 빠르게 제공하여 커뮤니케이션을 줄일 수 있다.
  • 대리 프락시
    • 웹 서버인 것처럼 위장하여 요청을 받는다.
    • 웹 서버와 달리 요청받은 콘텐츠의 위치를 찾기 위해 다른 서버와 커뮤니케이션을 시작한다.
    • 대리 프락시는 공용 콘텐츠에 대한 느린 웹 서버의 성능 개선을 위해 사용
  • 콘텐츠 라우터
    • 프락시 서버는 인터넷 트래픽 조건과 콘텐츠의 종류에 따라 요청을 특정 웹 서버로 유도하는 콘텐츠 라우터로 동작
  • 트랜스코더
    • 프락시 서버는 콘텐츠를 클라이언트에게 전달하기 전에 본문 포맷을 수정할 수 있다.
  • 익명화 프락시
    • HTTP 메시지에 신원을 식별할 수 있는 특성을 제거함으로써 개인 정보 보호와 익명성 보장

6.3 프락시는 어디에 있는가?

  • 프락시 서버 배치
    • 출구 프락시
      • 개인 LAN 출구 프락시: 프락시를 로컬 네트워크의 출구에 넣을 수 있다.
      • 보안 등에 문제, 필터링 등에 이유로 사용
    • 접근(입구) 프락시
      • ISP 접근 프락시
      • 고객으로부터의 모든 요청을 종합적으로 처리하기 위해 프락시는 ISP 접근 지접에 위치하기도 한다.
      • 캐시 프락시를 사용해 대역폭 비용을 줄일 수 있다.
    • 대리 프락시
      • 네트워크의 가장 끝에 있는 웹 서버들의 바로 앞에 위치하여 웹 서버로 향하는 모든 요청을 처리하고 필요할 때만 웹 서버에게 자원을 요청할 수 있다.
      • 웹 서버에 보안, 캐시 등을 설정할 수 있다.
    • 네트워크 교환 프락시
      • 캐시를 이용해 인터넷 교차로의 혼잡을 완화하고 트래픽 흐름을 감시하기 위해 사용하며 인터넷 피어링 교환 지접들에 놓일 수 있다.
  • 프락시 계층
    • 프락시 계층에서 메시지는 최종적으로 원 서버에 도착할 때까지 프락시와 프락시를 거쳐 이동한다.
    • 프락시 계층에서 프락시 서버들은 부모와 자식의 관계를 갖는다.
      • 서버에 가까운 쪽이 부모이고, 클라이언트와 가까운 쪽이 자식이라고 한다.
    • 프락시 계층 콘텐츠 라우팅
      • 프락시 계층은 정적이다.
      • 반드시 정적이어야 하는 것은 아니다. (= 동적 부모 선택)
        • 프락시 서버는 여러 가지 판단 근거에 의해 메시지를 다양하고 유동적인 프락시 서버와 원 서버들의 집합에게보낼 수 있다.
        • 부하 균형: 부모들의 작업량 수준에 근거하여 부모 프락시를 선택
        • 지리적 인접성에 근거한 라우팅
        • 프로토콜 / 타입 라우팅
        • 유료 서비스 가입자를 위한 라우팅
  • 어떻게 프락시가 트래픽을 처리하는가
    • 클라이언트 수정
      • 브라우저에서 수동 혹은 자동 프락시 설정을 지원
    • 네트워크 수정
      • 네트워크 인프라를 가로채서 웹 트래픽을 프락시로 가도록 조정하는 몇가지 기법이 있다.
      • HTTP 트래픽을 지켜보고 가로채어 클라이언트 모르게 트래픽을 프락시로 보내는 스위칭 장치, 라우팅 장치가 필요하다.
      • 인터셉트 프락시라고 부른다.
    • DNS 이름공간 수정
      • 웹 서버의 이름과 IP를 서버 대신 대리 프락시로 가도록 DNS 서버를 이용해 조정
    • 웹 서버 수정
      • HTTP 리다이렉션 명령(응답 코드: 305)을 클라이언트에게 돌려줌으로써 클라이언트의 요청을 프락시로 리다이렉트 되도록 설정할 수 있다.

6.4 클라이언트 프락시 설정

  • 클라이언트 프락시 설정: 수동
    • 브라우저 설정에서 프락시 서버 설정
  • 클라이언트 프락시 설정: PAC 파일
    • 프락시 자동 설정(PAC) 파일은 프락시 설정에 대한 동적인 해결책으로 상황에 맞게 계산해주는 자바스크립트 프로그램이다.
    • 자바스크립트 PAC 파일의 URI를 브라우저에 설정해야 한다.
    • PAC 파일은 일반적으로 .pac 확장명을 가지며 MIME TYPE은 application/x-ns-proxy-autoconfig 이다.
    • FindProxyForURL: URI에 접근할 때 사용할 적절한 프락시 서버를 계산해주는 FindProxyForURL(url, host) 함수 정의 필요

      // ex) FindProxyForURL function 정의
      function FindProxyForURL(url, host) {
          if(url.substring(0, 5) == 'http:') return "PROXY http-proxy.mydomain.com:8080";
          else if(url.substring(0, 4) == 'ftp:') return "PROXY ftp-proxy.mydomain.com:8080";
          else return "DIRECT";
      }
      
      FindProxyForURL 반환값 설명
      DIRECT 프락시 없이 연결이 직접 이뤄져야 한다.
      PROXY host:port 지정한 프락시를 사용해야 한다.
      SOCKS host:port 지정한 SOCKS 서버를 사용해야 한다.
  • 클라이언트 프락시 설정 WPAD
    • WPAD는 여러 발견 메커니즘들의 상승 전략을 이용해 브라우저에게 알맞은 PAC 파일을 자동으로 찾아주는 알고리즘
    • WPAD 프로토콜이 구현된 클라이언트가 하는 일
      • PAC URI를 찾기 위해 WPAD 사용
      • 주어진 URI에서 PAC 파일을 가져온다
      • 프락시 서버를 알아내기 위해 PAC 파일 실행
      • 알아낸 프락시 서버를 이용해 요청 처리

6.5 프락시 요청의 특징들

  • 프락시 URI는 서버의 URI와 다르다
    • 본래 HTTP 설계에서는 클라이언트가 단일 서버와 바로 대화했기 때문에 URI의 많은 부분을 생략할 수 있었지만 프락시가 사용되기 시작했고 프락시는 목적지 서버에 대한 정보가 필요했다.
    • 프락시로 요청을 보낼 때는 생략되지 않은 URI를 보내고 서버로 바로 보낼 경우에는 스킴, 호스트, 포트번호가 없는 부분 URI를 보낸다.
    • HTTP/1.1에서는 모든 서버 요청에 대해 완전한 URI를 다룰 것을 요구하지만 여전히 많은 서버가 부분 URI만을 받아들인다.
  • 가상 호스팅에서 일어나는 같은 문제
    • 가상 호스팅은 여러 개의 웹 사이트가 동일한 물리적 웹 서버를 공유하기 때문에 서버로 들어오는 요청이 어떤 웹 페이지에게 온 것인지 알 필요가 있다.
    • 명시적인 프락시의 경우 요청 메시지가 완전한 URI를 갖도록 했고 가상으로 호스팅되는 웹 서버의 경우 호스트와 포트에 대한 정보가 담겨 있는 Host 헤더를 요구한다.
  • 인터셉트 프락시는 부분 URI를 받는다
    • 인터셉트 프락시는 클라이언트에게 보이지 않기 때문에 클라이언트는 서버로 요청을 보낸다고 생각하고 부분 URI를 보낼 수 있다.
  • 프락시는 프락시 요청과 서버 요청을 모두 다룰 수 있다
    • 완전한 URI가 주어졌다면, 그것을 사용해야 한다.
    • 부분 URI가 주어졌고 Host 헤더가 있다면, Host 헤더를 이용해 원 서버의 이름과 포트 번호를 알아내야 한다.
    • 부분 URI가 주어졌으나 Host 헤더가 없을 경우
      • 대리 프락시라면, 프락시에 원 서버의 주소와 포트 번호가 설정되어 있을 수 있다.
      • 이전에 어떤 인터셉트 프락시가 가로챘던 트래픽을 받았고 그 인터셉트 프락시가 원 IP 주소와 포트번호를 사용할 수 있도록 해두었다면, 그 IP 주소와 포트번호를 사용할 수 있다.
      • 모두 실패했다면 에러 메시지를 반환해야 한다. 보통 사용자에게 Host 헤더를 지원하는 브라우저로 업그레이드를 하라는 메시지다.
  • 전송 중 URI 변경
    • 전송 중 URI 변경은 사소한 변경이라도 다운스트림 서버와 상호운용성 측면에서 문제가 발생할 수 있기 때문에 조심해야 한다.
    • 몇몇 프락시들은 URI를 다음 홉으로 보내기 전에 표준 형식으로 정규화하는 것으로 알려져 있는데 이는 문제를 일으킬 수 있다.
    • 프락시 서버는 가능한 한 관대하도록 애써야 하며, HTTP 명세는 일반적인 인터셉트 프락시가 URI의 절대 경로를 고쳐 쓰는 것을 금지한다.
    • 유일한 예외는 빈 경로를 /로 교체하는 것뿐이다.
  • URI 클라이언트 자동확장과 호스트 명 분석(Hostname Resolution)
    • 브라우저는 프락시의 여부에 따라 요청 URI를 다르게 분석한다. 프락시가 없다면 사용자가 입력한 URI를 가지고 그에 대응하는 IP 주소를 찾는다.
    • 만약 호스트명이 발견되면 그에 대응하는 IP 주소들을 연결할 때까지 시도해본다.
    • 호스트명이 발견되지 않을 경우 사용자가 입력한 부분에 확장을 제공하고자 한다.
  • 명시적인 프락시를 사용할 때의 URI 분석
    • 명시적인 프락시를 사용할 경우 브라우저는 확장들 중 어느 것도 수행할 수 없다.
      • 브라우저의 URI가 프락시를 그냥 지나쳐버리기 때문
      • 브라우저는 기본 스킴과 경로를 추가하지만 호스트 명은 입력한 대로 남겨둔 채 프락시로 HTTP 요청을 보낸다.
    • 몇몇 프락시는 자동확장 등을 최대한 흉내내려고 한다.
  • 인터셉트 프락시를 이용한 URI 분석
    • 인터셉트 프락시의 경우 프락시가 존재하지만 클라이언트의 입장에서는 모르기 때문에 호스트 명 분석이 약간 달라진다.
    • DNS가 성공할 때까지 호스트 명을 자동확장하는 브라우저를 사용할 때, 동작은 프락시가 아닌 서버의 경우와 별 차이가 없지만 서버로의 커넥션이 만들어졌을 경우에는 분명한 차이가 발생한다.
    • 클라이언트가 호스트 분석에 성공하고 IP 주소의 목록을 갖고 있는 경우.
      • 이 중 몇 개는 이미 죽은 IP 주소일 수 있다.
      • 하지만 인터셉트 프락시와 연결할 경우, 첫 번째 시도가 죽은 IP 주소라고 해도 클라이언트는 프락시와 커넥션이 맺어졌기 때문에 서버와 연결되었다고 착각한다.
      • 인터셉트 프락시는 호스트 헤더에 들어 있는 호스트 명을 다시 분석하든 IP 주소에 대한 역방향 DNS 룩업을 해서든 다른 IP 주소를 시도해야 한다.
    • 인터셉트 프락시나 명시적인 프락시를 사용할 경우 장애 허용은 프락시에 달려있기 때문에 죽은 서버의 DNS 분석에 대한 장애 허용을 지원해야 한다.

6.6 메시지 추적

  • Via 헤더
    • Via 헤더 필드는 메시지가 지나는 각 중간 노드(프락시 or 게이트웨이)의 정보를 나열한다. 메시지가 노드를 지날 때마다, 중간 노드는 Via 목록의 끝에 반드시 추가되어야 한다.
    • Via: 1.1 proxy-62.irenes-isp.net, 1.0 cache.joes-hardware.com
    • 위의 문자열은 메시지가 두 개의 프락시를 지나갔음을 보여준다.
    • Via 헤더 필드의 용도는 다음과 같다.
      • 메시지 전달 추적
      • 메시지 루프 진단
      • 요청과 응답의 과정에 관여하는 모든 메시지 발송자들의 프로토콜을 다루는 능력 진단
      • 네트워크의 라우팅 루프 탐지
      • 프락시는 요청을 보내기 전에 자신을 가리키는 유일한(unique) 문자열을 Via 헤더에 삽입해야 한다.
        • 이 문자열이 들어온 요청에 이미 존재한다면 네트워크에 라우팅 루프가 있다는 뜻이 된다.
    • Via 문법
      • 경유지(waypoint) 목록이 쉼표로 구분된 형태다.
      • 각 경유지는 개별 프락시 서버나 게이트웨이 홉을 나타내며 각 노드의 프로토콜과 주소에 대한 정보를 담고 있다.
      • 각 경유지는 프로토콜 이름(선택 기본은 HTTP), 프로토콜 버전(필수), 노드 이름(필수), 코멘트(선택)의 최대 4개의 구성요소를 담을 수 있다.

      • 프로토콜 이름
        • 중개자가 받은 프로토콜. 기본값은 HTTP다. 버전 앞에 /로 구분되어 붙는다.
      • 프로토콜 버전
        • 수신한 메시지의 버전. 버전의 포맷은 프로토콜마다 다르며 HTTP의 경우, 표준 버전 번호(1.0, 1.1 등)가 사용된다.
      • 노드 이름
        • 중개자의 호스트와 포트 번호(선택, 없다면 기본 포트라고 간주). 진짜 호스트 명을 밝히고 싶지 않은 경우 가명으로 대체할 수 있다.
      • 노드 코멘트
        • 중개자 노드를 서술하는 선택적인 코멘트.
        • 주로 벤더나 버전 정보를 포함시키며, 장치에서 일어난 이벤트에 대한 진단 정보를 포함하기도 한다.
      • Via 요청과 응답 경로
        • 요청, 응답 메시지 모두 프락시를 지나므로 둘 모두 Via 헤더를 가진다.
        • 요청과 응답이 지나는 경로는 서로 반대 순서를 가진다.
      • Via와 게이트웨이
        • 몇몇 프락시는 서버에게 비 HTTP 프로토콜을 사용할 수 있는 게이트웨이 기능을 제공한다.
        • Via 헤더는 이러한 프로토콜 변환을 기록한다.
      • Server 헤더와 Via 헤더
        • Server 응답 헤더 필드는 원 서버에 의해 사용되는 소프트웨어를 알려준다.
          Server: Apache/1.3.14 (Unix) PHP/4.04
          Server: Netscape=Enterprise/4.1
          Server: Microsoft-IIS/5.0
          
        • 응답 메시지가 프락시를 통과할 때, 프락시는 Server 헤더를 수정해서는 안 된다.
        • Server 헤더는 원 서버를 위해 존재하기 때문에 프락시는 대신 Via 항목을 추가해야 한다.
      • Via가 개인정보 보호와 보안에 미치는 영향
        • Via 문자열 안에 정확한 호스트 명이 들어가기를 원하지 않는 경우도 있다.
        • 이럴 경우엔 적당한 가명으로 교체해줘야 하는데, 여러 경유지들이 모두 같은 조직의 통제하에 있고 호스트가 이미 가명으로 교체되었을 경우 여러 항목들을 합칠 수 있다.
        • 이 때 수신된 프로토콜 값이 같아야 한다.
        • Via: 1.0 foo, 1.1 devirus.company.com, 1.1 access-logger.company.com
          • 위와 같은 경유지 목록을
        • Via: 1.0 foo, 1.1 concealed-stuff
          • 다음과 같이 합칠 수 있다.
  • TRACE 메서드
    • 프락시 서버를 지나면서 메시지는 바뀔 수 있다.
    • 헤더의 추가/변경/삭제, 본문 변환 등이 일어날 수 있기 때문에 프락시의 흐름에 따라 메시지의 변화 흐름을 파악할 필요가 있다.
    • 이 때 사용할 수 있는 게 HTTP/1.1의 TRACE 메서드이다.
    • TRACE 요청이 서버에 도착했을 때, 서버는 전체 요청 메시지를 클라이언트에 그대로 돌려준다.

    • Max-Forwards
      • 기본적으로 TRACE 메시지는 홉의 개수와 상관없이 다음 홉으로 전달되는데, 메시지가 전달되는 홉의 개수를 제한하는 요청 헤더 필드이다.
      • Max-Forwards가 0이라면 수신자는 더 이상 메시지를 전달하지 않고 클라이언트에게 돌려줘야 한다.

6.7 프락시 인증

  • 프락시는 접근 제어 장치로서 제공될 수 있다.
  • HTTP는 사용자가 유효한 접근 권한 자격을 프락시에 제출하지 않는 한 콘텐츠에 대한 요청을 차단하는 프락시 인증이라는 메커니즘을 정의하고 있다.
    • 제한된 콘텐츠에 대한 요청이 프락시 서버에 도착했을 때, 프락시 서버는 접근 자격을 요구하는 407 Proxy Authorization Required 상태 코드를 어떻게 그러한 자격을 제출할 수 있는지 설명해주는 Proxy-Authenticate 헤더 필드와 함께 반환할 수 있다.
    • 클라이언트는 407 응답을 받게 되면, 로컬 DB를 확인하거나 사용자에 물어봐서 요구되는 자격을 수집한다.
    • 자격을 획득하면, 클라이언트는 요구되는 자격을 Proxy-Authorization 헤더 필드에 담아서 요청을 다시 보낸다.
    • 자격이 유효하다면, 프락시는 원 요청을 연쇄를 따라 통과시킨다. 유효하지 않다면 407 응답을 다시 보낸다.
    • 프락시 인증은 보통 프락시 연쇄상에 인증에 참여하는 프락시가 여러 개가 아닐 때 잘 동작한다.

6.8 프락시 상호운용성

  • 프락시 서버는 다양한 환경에 따른 다양한 클라이언트와 서버 사이를 중개해야 한다.

  • 지원하지 않는 헤더와 메서드 다루기
    • 프락시 서버는 넘어오는 헤더와 메서드를 모두 이해하지 못한다.
    • 이 때, 이해하지 못하는 모든 헤더와 메서드는 그대로 전달해야 한다.
    • 같은 이름의 헤더 필드가 여러 개 있는 경우에는 상대적인 순서도 반드시 유지해야 한다.
  • OPTIONS: 어떤 기능을 지원하는지 알아보기
    • HTTP OPTIONS 메서드는 서버나 웹 서버의 특정 리소스가 어떤 기능을 지원하는지 클라이언트가 알아볼 수 있게 해준다.
    • 응답으로 HTTP/1.1이 명시한 헤더는 서버 혹은 특정 리소스에 어떤 메서드가 지원되는지 서술하는 Allow 헤더 하나뿐이다.
  • Allow 헤더
    • Allow 엔터티 헤더 필드는, 요청 URI에 의해 식별되는 자원에 대해서나 서버가 지원하는 모든 메서드를 열거한다.
      Allow: GET, HEAD, PUT
      
      • Allow 헤더는 새 리소스가 지원했으면 하는 메서드를 추천하기 위해 요청 헤더로 사용될 수 있다.
      • 그 요청에 대한 응답에는 실제로 지원하는 메서드들을 열거한 Allow 헤더가 포함되어야 한다.

** 참고 서적: HTTP 완벽 가이드