Forward Proxy에 대한 심층 분석

January 12, 2024

Technology

우리는 일반적으로 NGINX나 Apache를 로드 밸런서 및 리버스 프록시 서버로 활용합니다. 이 소프트웨어를 통해 외부 네트워크 트래픽이 내부 네트워크의 실제 서비스에 도달할 때도 마찬가지입니다. 리버스 프록시가 있는 반면, 포워드 프록시도 존재합니다. 이들의 기능을 자세히 살펴보겠습니다.

리버스 프록시

OSI 모델에서 프록시 서버까지

인터넷 서비스에 접근할 때, 우리는 일반적으로 OSI 모델의 7계층에서 동작하는 HTTP 프로토콜을 사용합니다. 이 프로토콜의 익숙한 구성 요소인 호스트 이름, 경로, 쿼리 파라미터 등은 이 계층의 일부입니다. HTTP 프로토콜은 OSI 모델의 4계층에서 동작하는 TCP 또는 UDP 프로토콜 위에 구축되며, 서비스 접근 시 사용되는 포트 개념은 이 프로토콜 내에 존재합니다. 더 나아가, TCP와 UDP는 모두 인터넷 프로토콜(IP)에 기반을 두고 있으며, 이는 OSI 모델의 3계층에서 동작하며, IP 주소는 인터넷의 "주소" 역할을 합니다.

IP 네트워크를 사용하여 인터넷에 접근할 때, IP 프로토콜은 목표를 주소 지정하고, 데이터 패킷을 규칙에 따라 캡슐화하여 IP 네트워크 내에서 소스 주소에서 목적지 주소로 전달하는 역할을 합니다. 예를 들어, 네트워크 트래픽은 방문자의 로컬 네트워크에서 ISP가 제공한 게이트웨이 장치를 통해 ISP의 네트워크에 연결된 후 리소스 제공자의 서비스에 접근합니다.

이 시점에서 우리는 인터넷에 접근하기 위해 게이트웨이를 사용합니다. 프록시 서버에 대해 논의할 때, 우리는 IP 네트워크와 유사하게 그릴 수 있습니다. 프록시 서버는 게이트웨이 역할을 하며, 클라이언트가 서비스에 접근할 수 있도록 돕는 다리 역할을 합니다. 이들은 기본적으로 OSI 모델의 4계층과 7계층 사이에서 동작하며, 실제로는 OSI 모델의 5계층에 속합니다.

API7-OSI 모델

프록시 서버의 목적

프록시 서버는 일반적으로 다음과 같은 목적으로 사용됩니다:

  1. 내부 네트워크 접근의 중앙 집중식 출구

기업은 종종 접근 제어 및 트래픽 로깅과 같은 정보 보안 요구 사항을 가지고 있습니다. HTTPS와 같은 암호화된 트래픽이 널리 퍼짐에 따라, 네트워크 경계에서 트래픽을 기록하고 감사하기 어려워져 유출 위험이 증가합니다. 프록시 서버의 존재는 통합된 트래픽 출구 역할을 하며, 트래픽 감사 작업을 처리하는 중개자 역할을 합니다.

인간 중심의 목적 외에도, 프록시 서비스는 외부 네트워크에 접근하는 프로그래밍 서비스의 출구로도 사용될 수 있습니다. 예를 들어, 서비스 제공자가 웹훅 기능을 제공할 때, 고정된 출구를 통해 트래픽을 전달하고, 단일 고정 IP 주소 또는 고정 IP 주소 범위를 사용합니다. 이는 웹훅 호출의 수신자가 방화벽에서 이를 올바르게 화이트리스트에 추가할 수 있도록 돕습니다. 이를 수행하지 않으면 웹훅 호출의 양쪽 모두 보안 위험에 노출됩니다.

  1. 방문자 신원 숨기기

때때로 인터넷 사용자는 자신의 IP 주소와 같은 신원을 숨기고 싶어할 수 있습니다. 이 경우, 투명 프록시 서버가 작동합니다. 클라이언트는 먼저 프록시 서버에 연결하고, 연결할 실제 서비스 주소를 지정한 후 HTTPS 프로토콜을 통해 프록시 서버를 통해 대상 서비스에 접근합니다. 프록시 서버의 존재는 클라이언트의 신원이 숨겨지도록 보장하며, 암호화된 프로토콜의 사용은 이 과정에서 프록시 서버가 데이터를 훔칠 수 없도록 보장합니다.

포워드 프록시

HTTP 기반 프록시

프록시 서버에서 우리는 일반적으로 HTTP 기반의 HTTP 프록시와 바이너리 기반 프로토콜인 SOCKS 4/5 프로토콜을 접하게 됩니다. 이들은 유사한 기능을 수행하지만 구현 방법이 다릅니다. 여기서는 HTTP 기반 프록시에 초점을 맞추겠습니다.

프로토콜 구현 초기 단계에서 HTTP의 트래픽은 주로 평문이었습니다. 이 투명성은 클라이언트와 서비스 사이에 위치한 프록시 서버가 URL과 요청 페이로드를 쉽게 파싱할 수 있도록 했습니다. DNS 해결 및 유사한 과정을 통해 프록시는 자신의 네트워크 주소를 사용하여 서비스에 연결할 수 있었고, 이를 통해 클라이언트를 숨길 수 있었습니다.

이러한 호출의 예는 다음과 같습니다:

GET http://example.com/resource HTTP/1.1
Proxy-Authorization: Basic encoded-credentials

프록시 서버는 클라이언트가 접근하려는 주소를 이해하고 서비스에 요청을 보내 응답을 받은 후 클라이언트에게 반환합니다.

HTTP/1.1 200 OK
Content-Type: text/html
...
body blahblah
...

이는 HTTP 프록시 서버의 가장 간단한 구현 형태입니다. 그러나 우리는 단점을 관찰합니다: 프록시 서버는 클라이언트 트래픽을 평문으로 처리하므로, 전달 중에 사용자 트래픽을 기록할 수 있는 보안 위험이 있습니다. 따라서 보안을 보장하기 위해 암호화 방법을 고려해야 합니다.

HTTPS 트래픽과 프록시 서버의 복잡한 작동

모든 HTTP 트래픽 내에서 HTTPS 암호화 트래픽의 비율이 증가함에 따라, 프록시 서버는 이 시나리오에 적응해야 합니다.

그러나 문제가 발생합니다: 클라이언트가 서비스 제공자에게 보내는 트래픽은 이제 암호화되었습니다. 프록시 서버는 클라이언트가 어떤 리소스에 접근하려는지 복호화를 통해 이해할 수 없습니다. 이는 트래픽이 클라이언트와 서비스 제공자 간의 비대칭 암호화 알고리즘에 기반한 키 협상 메커니즘에 의해 보호되며, 이후의 암호화된 트래픽은 통신 중간에 있는 중간자에게는 얻을 수 없는 대칭 키를 사용하기 때문입니다. TLS의 근본적인 목적은 중간자 공격의 가능성을 방지하는 것입니다.

그렇다면, 이 경우 프록시 서버는 어떻게 작동할까요?

이는 이전의 평문 요청 파싱 방법에 비해 더 복잡합니다. HTTP 프로토콜은 전용 요청 메소드인 CONNECT를 도입했습니다. 클라이언트는 이 메소드를 사용하여 프록시 서버에 초기 요청을 보냅니다:

CONNECT server.example.com:80 HTTP/1.1
Host: server.example.com:80
Proxy-Authorization: Basic encoded-credentials

클라이언트는 프록시 서버에 CONNECT 요청을 보내며, 클라이언트가 연결하려는 도메인 또는 IP 주소와 포트를 포함합니다. 프록시 서버는 요청을 받으면 대상 서비스와 TCP 연결을 설정하고 클라이언트와 서비스 간의 포트 매핑을 저장합니다. 이후 클라이언트는 프록시 서버에 올바른 요청을 보낼 수 있으며, 프록시 서버는 데이터를 파싱하려고 시도하지 않고 트래픽을 서비스에 그대로 전달합니다. 따라서 HTTPS의 암호화된 통신은 신뢰할 수 있습니다.

이 메커니즘은 평문 HTTP 프록시에 비해 더 다재다능합니다. 첫 번째 HTTP 요청이 프록시 서버에 연결을 설정할 정보를 알려주면, 이는 기본적으로 투명 프록시 채널이 됩니다. 이를 통해 HTTPS 및 TCP 바이너리 트래픽(예: SSH) 모두 프록시 서버를 통해 통신할 수 있습니다.

Tags: