TPROXY(Transparent Proxy)는 Linux에서 투명 프록시를 구성하기 위한 기능이다. 패킷의 목적지 헤더를 바꾸지 않고 트래픽을 로컬 소켓으로 전달할 수 있다. 이 글에서는 NAT/REDIRECT 방식과의 차이, 구성 요소, 사용자 공간 프록시까지의 경로를 정리한다.

투명 프록시가 필요한 이유

투명 프록시는 클라이언트의 별도 프록시 설정 없이 네트워크 경로에서 트래픽을 받아 처리한다. 검사, 접근 제어, 전달, 캐싱 같은 기능을 중간 장비에서 수행할 수 있다.

명시적 프록시는 클라이언트가 프록시 서버에 접속하도록 설정하는 방식이다. 따라서 일반 프록시가 반드시 DNAT로 구현되는 것은 아니다. NAT/REDIRECT와 TPROXY는 투명하게 트래픽을 로컬 프록시로 전달하기 위한 방법으로 비교해야 한다.

NAT/REDIRECT와의 차이

그림 1. NAT의 주소 변환 단계

SNAT는 출발지 주소를, DNAT는 목적지 주소를 바꾼다. REDIRECT는 트래픽의 목적지를 로컬 시스템으로 변경하는 방식이다. 목적지가 변경되면 프록시는 원래 목적지를 별도로 알아내야 한다.

Linux 커널 문서는 REDIRECT를 사용할 때 원래 목적지를 얻는 과정의 한계를 설명한다. TPROXY는 목적지 헤더를 유지하므로 이 주소 변환에 따른 제약을 줄인다. 다만 SNAT가 없는 DNAT까지 모두 클라이언트 주소를 숨긴다고 일반화해서는 안 된다. (커널 문서)

프록시 경로의 비용

그림 2. 프록시 처리 경로의 병목

NAT 기반 프록시는 패킷을 받아 netfilter와 연결 상태 처리를 거친 뒤 사용자 공간 소켓으로 전달한다. 프록시가 업스트림 연결을 생성하면 별도의 소켓 경로도 필요하다.

TPROXY 역시 사용자 공간 프록시로 동작한다면 소켓 처리, 데이터 복사, 업스트림 연결 비용을 갖는다. 주소 변환을 줄이는 것이 프록시 전체 비용을 없애는 것은 아니다. 연결 추적 사용 여부와 규칙 구성도 실제 처리 비용에 영향을 준다.

멀티코어 확장성은 세션 상태의 소유권, 큐 배치, CPU 간 데이터 이동에 따라 달라진다. TPROXY를 선택했다는 사실만으로 성능이 높아진다고 판단하기보다 동일한 워크로드에서 처리량과 지연을 비교해야 한다.

TPROXY 구성 요소

구성에는 netfilter의 TPROXY 규칙, 패킷 마크를 사용하는 정책 라우팅, 프록시의 투명 소켓 설정이 필요하다. 프록시 애플리케이션은 IP_TRANSPARENT 옵션을 사용하도록 구현되어 있어야 한다. 실제 규칙은 TCP/UDP 구분, 인터페이스, 라우팅, 프록시 자체 트래픽의 재진입 방지 조건에 맞춰 작성해야 한다.

TPROXY는 요청을 대신 검사하거나 업스트림으로 전달하는 애플리케이션이 아니다. 트래픽을 프록시 소켓에 도달시키는 기능이며, 연결 관리와 전달 정책은 별도의 구현이 담당한다.

패킷의 처리 흐름

구성된 시스템에서의 흐름은 다음과 같이 정리할 수 있다.

  1. 패킷이 프록시 장비의 네트워크 인터페이스로 들어온다.
  2. netfilter 규칙이 대상 트래픽을 선택해 TPROXY 처리와 마크 설정을 수행한다.
  3. 정책 라우팅이 해당 패킷을 로컬 전달 경로로 보낸다.
  4. 투명 소켓을 사용하는 사용자 공간 프록시가 트래픽을 받는다.
  5. 프록시가 검사와 전달 정책을 적용하고 필요하면 업스트림 연결로 데이터를 전달한다.

TCP 프록시에서는 클라이언트 측 연결과 업스트림 측 연결을 별도로 관리한다. 목적지 헤더를 유지하는 것과 업스트림에서 원래 클라이언트 주소를 그대로 사용하는 것은 별도의 설정 문제다. TLS 본문을 검사하려면 암호화 처리 범위도 함께 설계해야 한다.

정리

TPROXY를 이해할 때는 목적지 주소 보존, 로컬 소켓으로의 전달, 프록시의 애플리케이션 동작을 구분하는 것이 중요하다. Mini-IPS 설계에서도 TPROXY 자체보다 검사 시점과 데이터 전달 시점, 세션 상태 관리가 차단 동작을 결정한다.