- httptap은
httptap -- <command>형태로 Linux 프로그램을 실행해 해당 프로그램이 만드는 HTTP/HTTPS 요청과 응답 요약을 터미널에 표시하는 도구임 - 루트 권한, 데몬, 시스템 전역 변경,
iptables규칙, 라우팅 테이블 변경 없이 동작하며, 실행 파일은 의존성 없는 정적 Go 바이너리임 - 현재는 Linux 전용이며, network namespace 같은 Linux 전용 시스템 호출을 사용해 다른 운영체제로 포팅하기 어렵다고 밝힘
- HTTPS 트래픽은 실행 시 즉석에서 만든 인증기관을 서브프로세스 환경에 주입해 복호화하며, 원시 IP/TCP/UDP 패킷을 처리하는 투명 TCP 프록시 방식으로 동작함
- Ubuntu 23.10 이상이나 비권한 user namespace를 기본 비활성화한 배포판에서는
sysctl설정이 필요할 수 있고, 들어오는 연결 수신과/dev/net/tun접근 같은 제약이 있음
httptap이 하는 일
- httptap은 임의의 Linux 명령을 감싸 실행하면서 그 명령이 만드는 HTTP/HTTPS 요청을 보여줌
- 기본 사용 형태는
httptap -- <command>임 - 예시는
curl https://monasticacademy.org실행 시GET https://monasticacademy.org/요청과308응답을 표시함
- 기본 사용 형태는
- Python
requests.get('https://monasticacademy.org')예시에서는 리다이렉트를 따라가며 두 요청을 표시함- 첫 요청은
https://monasticacademy.org/에 대한308 - 다음 요청은
https://www.monasticacademy.org/에 대한200
- 첫 요청은
설치와 실행 조건
- 사전 빌드 바이너리는 최신 릴리스 tarball을 받아 설치할 수 있음
- 모든 버전과 CPU 아키텍처는 releases에서 확인 가능
- Go 설치 방식도 제공함
go install github.com/monasticacademy/httptap@latest
- 실행에는 일반적으로 루트 권한이 필요 없고, 데몬이나 시스템 전역 설정도 필요 없음
iptables규칙을 만들지 않음- 라우팅 테이블을 바꾸지 않음
- 같은 시스템의 다른 프로세스에 일반적으로 영향을 주지 않음
- Ubuntu 23.10 이상에서는 다음 설정이 필요함
sudo sysctl -w kernel.apparmor_restrict_unprivileged_unconfined=0sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
- 이 설정은 비권한 user namespace를 제한하는 최근 커널 기능을 비활성화함
- 비권한 user namespace를 기본 비활성화한 다른 배포판에서도 필요할 수 있음
- httptap에 AppArmor 프로필을 함께 제공해 이 필요성을 없애는 방법을 조사 중임
사용 예시
curl -s https://buddhismforai.sutra.co -o /dev/null실행 예시는 서버가302리다이렉트를 반환했음을 보여줌curl -sL처럼 리다이렉트를 따라가게 하면 추가 요청까지 표시됨- 첫 요청은
302 - 두 번째 요청은 리다이렉트 대상 URL에 대한
200
- 첫 요청은
gcloud compute instances list예시에서는 Google Cloud CLI가 내부적으로 사용하는 HTTP 엔드포인트를 확인할 수 있음POST https://oauth2.googleapis.com/tokenGET https://compute.googleapis.com/compute/v1/.../aggregated/instances?...- 일반
gcloud출력과 httptap의 요청 로그가 함께 나타남
kubectl get all예시에서는 Kubernetes API 서버 요청을 표시함--https 443 6443은 443과 6443 포트 TCP 연결을 HTTPS로 취급하게 함--insecure-skip-tls-verify는 kubectl이 httptap이 생성한 인증기관을 사용하지 않기 때문에 필요함
curl --doh-url https://cloudflare-dns.com/dns-query예시는 DNS-over-HTTP 흐름을 보여줌- 처음 두 요청은 DNS 조회
- 다음 두 요청은 대상 사이트에 대한 일반 HTTP 요청
--head와--body옵션을 함께 쓰면 HTTP 헤더와 원시 페이로드를 출력함
HAR 출력
--dump-har out.har옵션으로 HTTP 요청과 응답을 HAR 파일로 덤프할 수 있음- 생성된 HAR 파일은 여러 HAR 뷰어에서 시각화할 수 있음
- 예시로 Google HAR Analyzer가 제시됨
- 예시 HAR에는
https://monasticacademy.org에 대한308 Redirect요청과https://www.monasticacademy.org에 대한200 OK요청이 들어감
localhost 접근
- httptap 안에서 호스트의 localhost 포트에 접근하려면
localhost대신host.httptap.local또는169.254.77.65를 사용함 - Linux의 각 network namespace는 자체 loopback 장치인
127.0.0.1을 갖기 때문에, httptap 안의127.0.0.1:1234는 호스트의 같은 주소와 포트가 아님 - httptap은
169.254.77.65를127.0.0.1로 라우팅하도록 하드코딩해 이 문제를 우회함
데몬화되는 서브프로세스
- Linux에서는 원래 프로세스가 종료된 뒤에도 남아 있는 서브프로세스를 만들 수 있음
- 데몬과 명령줄에서 실행한 GUI 앱에서 일반적인 방식임
- 이런 프로세스를 httptap 아래에서 실행하면 데몬화된 프로세스는 계속 httptap의 network namespace 안에 남음
--no-exit옵션은 즉시 실행한 서브프로세스가 종료된 뒤에도 httptap이 프록시와 로깅을 계속하게 함- Visual Studio Code 예시에서는
httptap --no-exit -- code --ignore-certificate-errors .형태를 사용함 - 종료하려면 VS Code를 닫은 뒤
Ctrl+C로 httptap을 종료해야 함
- Visual Studio Code 예시에서는
--no-exit없이 httptap이 먼저 종료되면 network namespace는 남아 있어도 TUN 장치의 패킷을 읽는 프로세스가 없어 앱의 네트워크 연결이 끊김setsid setsid curl http://httpbin.org/get과 Python의fork,setsid,fork예시에서도--no-exit이 없으면Could not resolve host오류가 발생함
동작 방식
httptap -- <command>는<command>를 격리된 network namespace에서 실행하고, 즉석에서 만든 인증기관을 주입해 HTTPS 트래픽을 복호화함- Linux의 TUN 장치를 만들어 모든 네트워크 트래픽이 그 장치를 통과하도록 서브프로세스 환경을 구성함
- TUN 장치에 쓰인 트래픽은 해당 장치를 만든 프로세스가 가진 파일 디스크립터로 전달됨
- 루트 network namespace를 바꾸면 시스템 전체 트래픽에 영향을 주므로, httptap은 별도 network namespace를 만듦
- 그 namespace에는 loopback 장치와 TUN 장치만 있음
- 서브프로세스는 이 namespace 안에서 실행됨
- TUN 장치에서 받은 트래픽은 원시 IP 패킷임
- httptap은 IP 패킷과 내부 TCP/UDP 패킷을 파싱함
- 다시 서브프로세스로 원시 IP 패킷을 써야 함
- 자체 TCP/IP 구현은 전체 TCP 프로토콜의 많은 부분이 빠져 있지만 목적에는 합리적으로 동작함
- 서브프로세스가
www.example.com에 요청하면 httptap은 대상 IP로 향하는 TCP SYN을 받고 SYN+ACK로 응답함- 별도로 Linux 커널의 일반 소켓 API를 사용해 실제 대상 IP와 TCP 연결을 맺음
- 이후 양방향 데이터를 중계함
- 이 구조가 전통적인 투명 TCP 프록시임
- HTTPS 복호화는 인증기관 주입으로 처리함
- 시작 시 private key와 x509 certificate에 해당하는 인증기관을 생성함
- 서브프로세스에만 보이는 파일시스템에 인증서를 기록함
- 서브프로세스에만 보이는 환경 변수를 설정해 해당 인증기관을 신뢰 목록에 추가함
- httptap은 인증기관의 private key를 갖고 있으므로 서브프로세스가 통신하려는 서버인 것처럼 증명하고 평문 HTTP 요청을 읽을 수 있음
제약
- 현재 Linux 전용이며 network namespace 같은 Linux 전용 시스템 호출에 의존함
- 프로세스가 들어오는 네트워크 연결을 수신할 수 없음
/dev/net/tun접근 권한이 필요함- 모든 ICMP echo 요청은 실제 네트워크로 ICMP 패킷을 보내지 않고 그대로 echo됨