--- title: HTTP Tunneling date: 2026-06-29 type: note domain: networking tags: [networking, tunneling, http, proxy] --- ## HTTP Tunneling이란? HTTP Tunneling은 **HTTP 프로토콜을 통로(터널)로 사용하여, 원래 HTTP가 아닌 트래픽을 전달하는 기법**이다. 많은 기업 네트워크/방화벽은 HTTP(80)와 HTTPS(443) 포트만 허용한다. HTTP tunneling을 사용하면 이 제한된 환경에서도 다른 프로토콜의 트래픽을 주고받을 수 있다. --- ## 주요 방식 ### 1. HTTP CONNECT (가장 대표적) - 클라이언트가 프록시 서버에 `CONNECT` 메서드를 전송 - 프록시가 목적지와 TCP 연결을 수립하면, 이후 **양방향 바이트 스트림**이 됨 - HTTPS 통신의 기본 동작 방식 ``` Client → Proxy: CONNECT example.com:443 HTTP/1.1 Proxy → Client: HTTP/1.1 200 Connection Established (이후 TLS 핸드셰이크 및 암호화된 데이터가 그대로 통과) ``` ### 2. HTTP Encapsulation - 비-HTTP 데이터를 HTTP 요청/응답 **body에 감싸서** 전달 - 예: SSH-over-HTTP, DNS-over-HTTPS (DoH) - 각 메시지가 일반 HTTP 요청처럼 보이므로 방화벽 통과가 용이 ### 3. WebSocket Upgrade - 초기 HTTP 핸드셰이크 후 **풀-듀플렉스 TCP 연결**로 전환 - 실시간 양방향 통신에 사용 (채팅, 스트리밍 등) --- ## 일반 프록시 vs HTTP Tunnel ``` [일반 HTTP 프록시] Client → Proxy → Server (프록시가 HTTP 내용을 읽고 중계) [HTTP Tunnel (CONNECT)] Client → Proxy → Server (프록시는 바이트를 그대로 전달, 내용 못 봄) ════════════════ ← 투명한 TCP 파이프 ``` 핵심 차이는 **프록시가 payload를 해석하느냐 여부**이다. 터널에서는 프록시가 단순 relay 역할만 하므로 TLS 등 암호화된 트래픽도 통과시킬 수 있다. --- ## 실제 사용 사례 | 사례 | 설명 | |---|---| | **HTTPS** | 브라우저가 프록시 환경에서 `CONNECT`로 TLS 터널 생성 | | **Corporate proxy 우회** | 방화벽 뒤에서 SSH, VPN 등을 HTTP로 감싸서 사용 | | **ngrok / Cloudflare Tunnel** | 로컬 서비스를 외부에 노출할 때 HTTP 터널 활용 | | **DNS-over-HTTPS** | DNS 쿼리를 HTTPS 요청으로 캡슐화 | --- ## 실습: Squid 프록시 + CLI 도구 ### 환경 준비 ```bash # Squid 설치 sudo apt install -y squid # 기본 포트: 3128 # 설정 파일: /etc/squid/squid.conf ``` ### Step 1: HTTPS 트래픽 터널링 (curl + CONNECT) ```bash # CONNECT 터널 경유 HTTPS 요청 curl -x http://localhost:3128 https://httpbin.org/ip # -v 옵션으로 CONNECT 핸드셰이크 과정 확인 curl -v -x http://localhost:3128 https://httpbin.org/ip ``` `curl -v` 출력에서 다음과 같은 흐름이 보인다: ``` * Establish HTTP proxy tunnel to httpbin.org:443 > CONNECT httpbin.org:443 HTTP/1.1 > Host: httpbin.org:443 > < HTTP/1.1 200 Connection established < * CONNECT tunnel established, response 200 * TLS handshake starts... ``` Squid 로그 확인: ```bash sudo tail -f /var/log/squid/access.log # TCP_TUNNEL/200 CONNECT httpbin.org:443 형태의 로그가 기록됨 ``` ### Step 2: 패킷 캡처로 CONNECT 동작 관찰 ```bash # 터미널 1: loopback 트래픽 캡처 sudo tcpdump -i lo port 3128 -A # 터미널 2: curl 요청 curl -x http://localhost:3128 https://httpbin.org/ip ``` 관찰 포인트: - CONNECT 요청/응답 헤더는 **평문**으로 보임 - 이후 TLS 핸드셰이크 데이터는 **암호화**되어 읽을 수 없음 - 프록시는 목적지 호스트:포트만 알 수 있고, 실제 전송 내용은 알 수 없음 ### Step 3: Raw CONNECT 핸드셰이크 직접 해보기 (nc) ```bash # netcat으로 Squid에 직접 접속 nc localhost 3128 ``` 수동으로 아래 내용을 입력: ``` CONNECT httpbin.org:443 HTTP/1.1 Host: httpbin.org:443 ``` 응답: ``` HTTP/1.1 200 Connection established ``` 이 시점에서 터널이 열린 상태이다. 이후 입력하는 모든 바이트는 `httpbin.org:443`으로 그대로 전달된다. ### Step 4: SSH over HTTP Tunnel Squid 설정에서 포트 22에 대한 CONNECT를 허용해야 한다: ```bash # /etc/squid/squid.conf에 추가 # acl Safe_ports port 22 # acl SSL_ports port 22 # 설정 변경 후: sudo systemctl reload squid ``` SSH 터널링 실행: ```bash # nc를 ProxyCommand로 사용하여 SSH를 HTTP CONNECT 터널로 통과 ssh -o ProxyCommand='nc -X connect -x localhost:3128 %h %p' localhost ``` Squid 로그에서 SSH 연결이 CONNECT로 터널링된 것을 확인할 수 있다. ### 정리 ```bash # 실습 후 정리 sudo apt remove --purge squid sudo apt autoremove ``` --- ## 보안 관점 - **정당한 용도**: HTTPS 통신, 기업 VPN, 보안 DNS - **리스크**: 방화벽/DLP를 우회할 수 있어 데이터 유출 경로가 될 수 있음 - **대응**: 프록시에서 CONNECT 대상 도메인/포트를 화이트리스트로 제한 --- ## 핵심 정리 1. **CONNECT 메서드** — 프록시에게 "이 호스트:포트로 TCP 파이프를 열어달라"는 요청 2. **터널 vs 프록시** — 터널은 프록시가 payload를 해석하지 않음 (바이트 릴레이) 3. **보안 시사점** — CONNECT로 임의 포트를 열 수 있으면 방화벽 우회 가능 → 포트 제한 필수