Junjangsee's Blog

Network - 프락시

2019-09-22

images

이번 장에서 살펴볼 주제

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


웹 중개자

클라이언트 입장에서 프락시 서버는 트랜잭션을 수행하는 중개인입니다. 웹 프락시가 없다면, 클라이언트는 HTTP 서버와 직접 이야기 할 것이고, 있다면 프락시를 통해 간접으로 이야기 합니다. 또한 프락시는 서버이면서 동시에 클라이언트처럼 동작합니다.


개인 프락시와 공유 프락시

하나의 클라이언트만을 위한 프락시를 개인 프락시, 여러 클라이언트가 함께 사용하는 프락시는 공용 프락시라고 부릅니다.

  • 공용 프락시: 대부분의 프락시는 공용이며 공유된 프락시입니다. 중앙 집중형 프락시를 관리하는게 더 비용효율이 높고 쉽습니다.
  • 개인 프락시: 개인 프락시를 사용하는 경우는 흔치 않지만, 클라이언트 컴퓨너에서 직접 실행되는 형태로 종종 사용되고있습니다.


프락시 대 게이트웨이

프락시같은 프로토콜을 사용하는 둘 이상의 애플리케이션을 연결합니다.
게이트웨이는 서로 다른 프로토콜을 사용하는 둘 이상을 연결하고 서로 다른 프로토콜로 말하더라도 트랜잭션을 완료할 수 있도록하는 프로토콜 변환기처럼 동작합니다.


왜 프락시를 사용하는가?

프락시는 보안을 개선하고, 성능 향상 및 비용을 절약하며 모든 HTTP 트래픽을 들여다보고 건드릴 수 있기 때문에 프락시는 부가적인 가치를 주는 여러 유용한 웹 서비스를 구현하기 위해 트래픽을 감시하고 수정할 수 있습니다.

  • 어린이 필터 : 어린이들에게 교육 사이트를 제공하면서 동시에 성인 컨텐츠를 차단하려고 필터링 프락시를 사용할 수 있습니다.
  • 문서 접근 제어자 : 많은 웹 서버들과 웹 시로르에 대한 단일한 접근 제어 전략을 구현하고 감사 추적을 하기 위해 사용됩니다.
  • 보안 방화벽 : 보안을 강화하기 위해 프락시 서버를 사용하며, 조직 안에 들어오거나 나가는 프로토콜의 흐름을 네트워크의 한 지점에서 통제합니다. 그리고 트래픽을 살펴보는 훅을 제공합니다.
  • 웹 캐시 : 인기 있는 문서의 로컬 사본을 관리하고 해당 문서에 대한 요청이 오면 빠르게 제공하여 느리고 비싼 인터넷 커뮤니케이션을 줄입니다.
  • 대리 프락시 : 어떤 프락시들은 웹 서버인 것처럼 위장하는데 이를 대리 혹은 리버스 프락시라고 불립니다. 이들은 진짜 웹 서버 요청을 받지만 웹 서버와는 달리 요청 받은 콘텐츠의 위치를 찾아내기 위해 다른 서버와 커뮤니케이션을 시작합니다. 웹 서버의 성능 개선을 위해 사용되고 콘텐츠 라우팅 기능과 결합되어 주문형 복제 콘텐츠의 분산 네트워크를 만들기 위해 사용될 수 있습니다.
  • 컨텐츠 라우터 : 사용자들에게 조건과 컨텐츠의 종류에 따라 요청을 특정 웹 서버로 유도하도록 동작하게끔 할 수 있습니다.
  • 트랜스코더 : 데이터의 표현 방식을 자연스럽게 변환합니다.
  • 익명화 프락시 : HTTP 메시지에서 신원을 식별할 수 있는 특성들 (클라이언트 IP 주소, Form 헤더, Referer 헤더, 쿠키, 세션 아이디)을 적극적으로 제거함으로써 개인 정보 보호와 익명성 보장에 기여합니다.


프락시는 어디에 있는가 ?

프락시 서버 배치

  • 출구 프락시 : 로컬 네트워크와 더 큰 인터넷 사이를 오가는 트래픽을 제어하기 위해 프락시를 로컬 네트워크의 출구에 박아 넣을 수 있습니다.
  • 접근(입구) 프락시 : 모든 요청을 종합적으로 처리하기 위해 프락시는 ISP 접근 지점에 위치하기도 합니다.
  • 대리 프락시 : 네트워크의 가장 끝에 있는 웹 서버의 바로 앞에 위치하여 웹 서버로 향하는 모든 요청을 처리하고 필요할 때만 웹 서버에게 자원을 요청 할 수 있습니다. 또한 보안 기능을 추가하거나 웹 서버 캐시를 느린 웹 서버의 앞에 놓음으로써 성능을 개선할 수도 있습니다.
  • 네트워크 교환 프락시 : 캐시를 이용해 인터넷 교차로의 혼잡을 완화하고 트래픽 흐름을 감시하기 위해, 처리 능력을 갖춘 프락시가 네트워크 사이의 인터넷 피어링 교환 지점들에 놓을 수 있습니다.


프락시 계층

프락시 계층에서 메시지는 원 서버에 도착할 때 까지 프락시와 프락시를 거쳐 이동합니다. 프락시 계층에서 프락시 서버들은 부모와 자식의 관계를 갖습니다.
인바운드 (서버와 가까운 쪽) 을 부모, 아웃바운드 (클라이언트 가까운 쪽) 을 자식이라고 부릅니다.

프락시 계층 콘텐츠 라우팅

프락시 계층은 정적입니다. 프락시 1은 언제나 메시지를 프락시 2로, 2는 3으로 보냅니다. 그러나 계층이 반드시 정적이어야 하는 것은 아니며 동적일 수도 있습니다.

  • 부하 균형 : 자식 프락시는 부하를 분산하기 위해 현재 부모들의 작업략 수준에 근거하여 부모 프락시를 고릅니다.
  • 지리적 인접성에 근거한 라우팅 : 자식 프락시는 원 서버의 지역을 담당하는 부모를 선택할 수도 있습니다.
  • 프로토콜/타입 라우팅 : URI 에 근거하여 다른 부모나 원 서버로 라우팅 할 수 있습니다.


어떻게 프락시가 트래픽을 처리하는가

클라이언트는 보통 웹 서버와 직접 대화하기 때문에 우리는 어떻게 HTTP 트래픽이 프락시로 향하는 을 찾아내는지 설명할 필요가 있습니다. 이러한 방법에는 아래 4가지 방법이 있습니다.

  • 클라이언트 수정 : 많은 웹 클라이언트들은 수동 혹은 자동 프락시 설정을 지원합니다. 때문에 자동으로 프락시 설정이 되어 있다면, HTTP 요청을 원 서버가 아닌 프락시 서버로 보냅니다.
  • 네트워크 수정 : 스위칭, 라우터 장치를 이용하여 네트워크 인프라를 가로채서 웹 트래픽을 프락시로 가도록 조정할 수 있습니다.
  • DNS 이름공간 수정 : DNS 이름 테이블을 수동으로 편집하거나 사용할 적절한 프락시나 서버를 계산해주는 특별한 동적 DNS 서버를 이용해서 조정될 수 있습니다.
  • 웹 서버 수정 : 웹 서버는 HTTP 리다이렉션 (응답 코드 305) 를 클라이언트에게 돌려줌으로써 요청을 프락시로 리다이렉트 하도록 설정할 수 있습니다.


클라이언트 프락시 설정

브라우저가 제공하는 프락시 설정 방법입니다.

  • 수동 설정 : 프락시 사용을 명시적으로 설정합니다.
  • 브라우저 기본 설정 : 브라우저를 소비자에게 전달하기 전에 프락시를 미리 설정해 놓을 수 있습니다.
  • 프락시 자동 설정 : 자바스크립트 프락시 자동 설정 파일에 대한 URI를 제공할 수 있습니다.
  • WPAD 프락시 발견 : 자동설정 파일을 다운받을 수 있는 ‘설정 서버’를 자동으로 찾아주는 웹 프락시 자동 발견 프로토콜을 제공합니다.


프락시 요청의 미묘한 특징들

프락시 URI 는 서버 URI 랑 다르다

웹 서버와 웹 프락시 메시지의 문법은 서로 같지만, 한 가지 예외가 있습니다. 클라이언트가 프락시 대신 서버로 요청을 보내면 요청의 URI가 달라잡니다.
클라이언트가 웹 서버로 요청을 보낼 때, 요청중은 다음의 예와 같이 스킴, 호스트, 포트번호가 없는 부분 URI를 가집니다.

1
2
GET /index.html HTTP/1.0
User-Agent: SuperBrowserv1.3



그러나 클라이언트가 프락시로 요청을 보낼 때, 요청줄은 완전한 URI 를 가집니다.

1
2
GET http://www.marys-antiques.com/index.html HTTP/1.0
User-Agent: SuperBrowser v1.3

단일 서버는 자신의 호스트 명과 포트번호를 알고 있으므로, 클라이언트는 불필요한 정보 발송을 피하기 위해 부분 URI만 사용했었습니다. 프락시는 목적지 서버와 커넥션을 맺어야 하기 때문에 완전한 URI를 요구합니다.


가상 호스팅에서 일어나는 같은 문제

  • 명시적인 프락시는 요청 메시지가 완전한 URI 를 갖도록 함으로써 문제를 해결했습니다.
  • 가상으로 호스팅 되는 웹 서버는 호스트와 포트에 대한 정보가 담겨 있는 Host 헤더를 요구합니다.


인터셉트 프락시는 부분 URI를 받는다

클라이언트는 자신이 프락시와 대화하고 있음을 항상 알고있는 것은 아닙니다.
이유로는, 몇몇 프락시는 클라이언트에게 보이지 않기 때문에 클라이언트가 프락시를 사용한다고 설정되어 있지 않더라도 여전히 대리 혹은 인터셉트 프락시를 지날 수 있습니다. 클라이언트는 자신이 웹 서버와 대화하고 있다고 생각하고 완전한 URI를 보내지 않을 수도 있습니다.


프락시는 프락시 요청과 서버 요청을 모두 다룰 수 있다

트래픽이 프락시 서버로 리다이렉트 될 수 있는 여러 가지 방법이 존재하기 때문에, 다목적 프락시 서버는 요청 메시지의 완전한 URI부분 URI모두 지원해야 합니다. 그 규칙은 아래와 같습니다.

  • 완전한 URI 가 주어졌다면, 프락시는 그 주소를 이용해야 합니다.
  • 부분 URI 가 주어졌고 Host 헤더가 있다면, Host 헤더를 이용해 원 서버의 이름과 포트번호를 알아내야 합니다.
  • 부분 URI 이지만 Host 헤더가 없다면?
    • 프락시가 원 서버를 대신하는 대리 프락시라면, 프락시에 실제 서버의 주소와 포트번호가 설정되어 있을 수 있습니다.
    • 인터셉터 프락시가 원 IP주소와 포트번호를 사용할 수 있도록 해두었다면 사용할 수 있습니다.


전송 중 URI 변경

요청 URI의 변경에 매우 신경을 써야합니다. 사소한 URI 변경이라도 다운스트림 서버와 상호운용성 문제를 일으킬 수 있습니다.


URI 클라이언트 자동확장과 호스트명 분석

브라우저는 프락시의 존재 여부에 따라 요청 URI를 다르게 분석합니다. 프락시가 없다면 사용자가 타이핑한 URI를 가지고 그에 대응하는 IP 주소를 찾습니다.
호스트가 발견되지 않는다면 짧은 약어를 타이핑한 것을 보고 자동화된 호스트 명의 ‘확장’을 제공하고자 아래와 같은 시도를 합니다.

  • ‘www’ 접두사와 ‘.com’ 접미사를 붙입니다.
  • 해석할 수 없는 URI는 서드파티 사이트로 넘깁니다. 이 사이트에서 오타 교정을 시도하고 사용자가 의도했을 URI를 제시합니다.
  • DNS는 사용자가 호스트 명의 앞부분만 입력하면 자동으로 도메인을 검색하도록 설정되어 있습니다.


프락시 없는 URI 분석

  1. 사용자가 ‘junjang’을 브라우저 URI 창에 입력했을때, junjang을 호스트 명으로 사용하고 http://를 기본 스킴으로, 기본 포트를 ‘80’으로, 기본 경로를 ‘/‘로 간주합니다.
  2. 브라우저는 호스트 junjang을 찾지만 실패합니다.
  3. 호스트명을 자동으로 확장한 후 DNS에 www.junjang.com 의 주소 분해를 요청합니다.
  4. 브라우저는 www.junjang.com 으로 연결합니다.


명시적인 프락시를 사용할 때의 URI 분석

명시적인 프락시가 있는 경우 브라우저는 편리한 확장 기능중 하나도 수행할 수 없스빈다. 브라우저창에 junjang 라고 타이핑 했을때 프락시는 ‘http://junjang/' 라고 보냅니다.


인터셉터 프락시를 이용한 URI 분석

호스트명 분석은 보이지 않는 인터셉트 프락시와 함께일 때 달라지는데, 그 이유는 클라이언트의 입장에서 프락시는 존재하지 않는 것이기 때문입니다.
DNS가 성공할 때까지 호스트 명을 자동확장하는 브라우저를 사용할 때, 동작은 프락시가 아닌 서버의 경우 별 차이가 없습니다. 그러나 서버로의 커넥션이 만들어졌을 때는 분명한 차이가 발생합니다.


메시지 추적

프락시가 점점 더 흔해지면서, 서로 다른 스위치와 라우터를 넘나드는 IP 패킷의 흐름을 추적하는 것 못지 않게 프락시를 넘나드는 메시지의 흐름을 추적하고 문제점을 찾아내는 것도 필요한 일이 되었습니다.


Via 헤더

Via 헤더 필드는 메시지가 지나는 각 중간 노드의 정보를 나열합니다. 메시지가 또 다른 노드를 지날 때마다, 중간 노드는 Via 목록의 끝에 반드시 추가되어야만 합니다.

메시지의 전달을 추적하고, 메시지 루프를 진단하고, 요청을 보내고 그에 대한 응답을 돌려주는 과정에 관여하는 모든 메시지 발송자들의 프로토콜을 다루는 능력을 알아보기 위해 사용됩니다.
또한 네트워크의 라우팅 루프를 탐지하기 위해 Via 헤더를 사용할 수 있습니다.

1
2
3
4
Via = "Via":" { waypoint } [", "{ waypoin } ...]
waypoint = ( received-protocol received-by [ comment ] )
received-protocol = [ protocol-name "/" ] protocol-version
receved-by = ( host [ ":" prot ] ) | pseudnym
  • 프로토콜 이름 : 프로토콜이 만약 HTTP 라면 프로토콜 이름은 없어도 됩니다. 한편, 프로토콜 이름은 버전 앞에 “/“ 로 구분되어 붙습니다.
  • 프로토콜 버전 : 버전의 포맷은 프로토콜에 달려있습니다. 버전은 Via 필드에 포함되므로, 애플리케이션들은 자신 이전의 모든 중개자들이 어떤 버전을 다룰 수 있는지 압니다.
  • 노드 이름 : 어떤 조직은 정보 보호를 이유로 진짜 호스트 명을 밝히고 싶지 않을 경우가 있을 때 가명으로 대체 할 수 있습니다.
  • 노드 코멘트 : 중개자 노드를 서술하는 선택적인 코멘트, 벤더나 버전 정보를 포함시키며, 이벤트의 진단정보를 포함합니다.
  • Via 요청과 응답 경로 : 요청 메시지와 응답 메시지 모두 프락시를 지나가므로 둘 모두 Via 헤더를 가집니다. 응답의 Via 헤더는 언제나 요청 Via 헤더의 반대입니다.
  • Via와 게이트웨이 : 서버에게 비 HTTP 프로토콜을 사용할 수 있는 게이트웨이 기능을 제공합니다.
  • Server 헤더와 Via 헤더 : Server 응답 헤더 필드는 원 서버에 의해 사용되는 소프트웨어를 알려준다.
  • Via가 개인정보 보호와 보안에 미치는 영향 : 만약 Via 노드 이름 전달이 가능하지 않다면, 보안 경계선의 일부분인 프락시는 호스트 명을 그 호스트에 대한 적당한 가명으로 교체해야합니다. 프락시는 정렬된 일련의 Via 경유지 항목들을 하나로 합칠 수 있습니다. 이 때 위 요소들이 만족하지 않는 이상 항목을 합치면 안됩니다.


TRACE 메소드

프락시 서버는 메시지가 전달될 때 메시지를 바꿀 수 있습니다. TRACE는 프락시 흐름을 디버깅 하는데 매우 유용합니다. TRACE 요청이 목적지 서버에 도착했을 때, 서버는 전체 요청 메시지를 HTTP 응답 메시지의 본문에 포함시켜 돌려보내고 응답이 도착했을 때, 클라이언트는 서버가 받은 메시지와 프락시의 목록을 볼 수 있습니다.

  • Max-Forwards : 일반적으로 TRACE 메시지는 중간에 프락시들이 몇 개가 있든 상관하지 않지만 프락시 홉 개수를 제한하기 위해 Max-Forwards 헤더를 사용할 수 있는데 이는 전달되는 메시지가 무한 루프에 빠지지 않는지 프락시 연쇄를 테스트하거나 연쇄 중간의 특정 프락시 서버들의 효과를 체크할 때 유용하게 사용됩니다.


프락시 인증

프락시는 접근 제어 장치로서 제공될 수 있습니다. 프락시 인증은 인증에 참여하는 프락시가 프락시 연쇄상에 여러 개 있을 때는 일반적으로 잘 동작히지 않습니다.


프락시 상호운용성

프락시 서버는 서로 다른 프로토콜을 구현했을 수도 있고 골치 아프게 이상한 동작을 할 수도 있는 클라이언트와 서버 사이를 중개해야 합니다.


지원하지 않는 헤더와 메서드 다루기

프락시 서버는 넘어오는 헤더 필드들을 모두 이해하지 못할 수도 있습니다. 그래서 프락시는 이해할 수 없는 헤더 필드는 반드시 전달하여 통과시켜야 합니다.


OPTIONS : 어떤 기능을 지원하는지 알아보기

서버나 웹 서버의 특정 리소스가 어떤 기능을 지원하는지 클라이언트가 알아볼 수 있게 해줍니다.


Allow 헤더

Allow 엔티티 헤더 필드는, 요청 URI에 의해 식별되는 자원에 대해 지원되는 메소드들이나 서버가 지원하는 모든 메소드를 열거합니다. 또한 새 리소스가 지원했으면 하는 메소드를 추천하기 위해 요청 헤더로 사용될 수 있습니다.