웹 프록시는 웹 브라우저와 최정 서버 사이에서 중개 역할을 하는 프로그램.
브라우저는 프록시에 연락하고 프록시는 요청을 최종 서버로 전달.
최종 서버가 프록시에 응답하면, 프록시는 응답을 브라우저로 전송
사용처
- 방화벽 뒤의 브루어저가 프록시를 통해서만 방화벽 너머의 서버와 접속할 수 있도록 함
- 모든 식별 정보를 제거하여 익명화 도구로 작용할 수 있다
- 웹 객체를 캐시하여 서버로부터의 객체의 로컬 복사본을 저장하고, 이후에 캐시에서 읽어 응답
간단한 HTTP 프록시 구현
1. 프록시를 설정하여 들어오는 연결을 수락,
요청을 읽고 파싱,
웹 서버로 요청을 전달
서버의 응답을 읽어 해당 클라이언트로 응답을 전달
2. 여러 동시 연결을 처리하도록 업그레이드 ( 동시성 처리 )
3. 최근에 접근한 컨텐츠의 간단한 주 메모리를 캐시를 사용하여 프록시에 캐싱 기능 추가
1. 순차 웹 프록시 구현
- HTTP/1.0 GET 요청을 처리하는 기본 순차 프록시를 구현
- 프록시 구현 단계
- 프록시 서버 시작
- 명령줄에서 지정된 포트 번호에서 들어오는 연결을 수신
- 포트에서 소켓을 열고, 연결 수신 대기
- 연결 수락
- 클라이언트와 연결 확립되면, 클라이언트의 요청을 수신하기 위한 소켓을
- 칼라이언트 요청 읽기
- 클라이언트로부터 전체 HTTP 요청을 읽음. 메서드(GET), 요청된 URL 및 추가 헤더가 포함
- 요청이 제대로 종료되었는지(빈 줄 감지) 확인
- 요청 파싱
- HTTP 요청이 유효한 HTTP/1.0 GET 요청인지 확인
- 필요한 구성 요소(예: URL)를 추출
- 웹 서버에 연결
- 추출한 URL을 사용하여 적절한 웹 서버에 연결
- 웹 서버와의 통신을 위해 새로운 소켓을 생성
- 웹 서버에 요청 전송
- 클라이언트의 요청을 웹 서버에 전달. GET 요청 및 필요한 헤더를 포함
- 서버의 응답 읽기
- 웹 서버로부터의 응답을 읽음. 상태 줄, 헤더, 본문으로 구성
- 필요한 경우 청크 전송 인코딩을 처리
- 응답을 클라이언트에 전달
- 웹 서버의 응답을 원래 소켓을 통해 클라이언트에게 보냄
- 모든 연결을 적절히 종료하여 리소스 해제
- 프록시 서버 시작
2. HTTP/1.0 GET 요청
" http://www.cmu.edu/hub/index.html " 을 입력하면, 브라우저는 다음과 같은 형식의 HTTP 요청을 프록시로 전송한다.
" GET http://www.cmu.edu/hub/index.html HTTP/1.1 "
프록시는 "www.cmu.edu" 에 연결을 열고, 다음과 같은 형식의 HTTP 요청을 보내야 함.
" GET /hub/index.html HTTP/1.0 "
요청 라인은 HTTP/1.1로 끝나지만 프록시의 요청 라인은 HTTP/1.0으로 끝남
요청 헤더
중요한 요청 헤더는 Host, User-Agent, Connection, Proxy-Connection 헤더.
Host 헤더는 항상 전송. 기술적으로 HTTP/1.0 사양에 승인되지 않지만, 합리적인 응답을 유도하는 데 필요함
Host 헤더는 최종 서버의 호스트명을 설명.
ex) http://www.cmu.edu/hub/index.html 에 접근하기 위해 " Host: www.cmu.edu " 라는 헤더를 전송해야함
User-Agent 헤더를 항상 전송할 수 있다.
" User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0.3) Gecko/20120305 Firefox/10.0.3 "
프록시는 한 줄로 전송해야 함. User-Agent 헤더는 클라이언트를 식별하며,
웹 서버는 식별 정보를 사용하여 제공하는 컨텐츠를 조작.
간단한 텔넷 스타일 테스트 중에 반환되는 자료의 내용과 다양성을 개선할 수 있다.
Connection 헤더를 항상 전송해야함
" Connection: close "
Proxy-Connection 헤더도 항상 전송해야 함
" Proxy-Connection: close "
Connection 및 Proxy-Connection 헤더는 첫 번째 요청/응답 교환이 완료된 후
연결이 유지될 것인지 여부를 지정하는 데 사용
각 요청에 대해 새 연결을 여는 것은 완전히 허용되며,
이 헤더에 close라는 값을 지정하면 웹 서버에 프록시가 첫 번째 요청/응답 교환 후에 연결을 닫으려는 의도를 알림
User-Agent 헤더의 값은 proxy.c에서 문자열 상수로 제공
브라우저가 HTTP 요청의 일부로 추가적인 요청 헤더를 전송하는 경우,
프록시는 이를 변경하지 않고 그대로 전달해야 함
3. 포트 번호
중요한 두 가지 클래스의 포트 번호 : HTTP 요청 포트와 프록시의 수신 포트
- HTTP 요청 포트 : HTTP 요청의 URL에서 선택적 필드
즉, URL이 " http://www.cmu.edu:8080/hub/index.html " 과 같은 형식을 가질 수 있으며,
HTTP 포트인 80 대신 8080 포트에서 호스트 " www.cmu.edu " 에 연결해야 함
프록시는 포트 번호가 URL에 포함되어 있든 없든 적절하게 작동해야 함 - 수신 포트 : 수신 대기하는 포트. 수신 포트 번호를 지정하는 명령줄 인수를 수락해야 함.
예를 들어, 다음 명령으로 프록시는 15213 포트에서 연결을 수신해야 함
linux> ./proxy 15213
1024보다 크고 65536보다 작은 비특권 수신 포트를 선택할 수 있으며, 다른 프로세스에서
사용되지 않아야 함.
다수가 각 머신에서 작업하고 있기 때문에, port-for-user.pl 스크립트를 제공하여
개인 포트 번호를 선택하는 데 도움을 줌.
사용자 ID를 기반으로 포트 번호를 생성하려면 다음을 사용:
linux> ./port-for-user.pl droh
droh: 45806
port-for-user.pl에 의해 반환된 포트 p는 항상 짝수. 따라서 추가 포트 번호가 필요한 경우,
예를 들어 Tiny 서버를 위한 경우, 포트 p와 p + 1을 안전하게 사용할 수 있음.