8P by GN⁺ | ★ favorite | 댓글 2개
  • httptaphttptap -- <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이 하는 일

설치와 실행 조건

  • 사전 빌드 바이너리는 최신 릴리스 tarball을 받아 설치할 수 있음
    • 모든 버전과 CPU 아키텍처는 releases에서 확인 가능
  • Go 설치 방식도 제공함
    • go install github.com/monasticacademy/httptap@latest
  • 실행에는 일반적으로 루트 권한이 필요 없고, 데몬이나 시스템 전역 설정도 필요 없음
    • iptables 규칙을 만들지 않음
    • 라우팅 테이블을 바꾸지 않음
    • 같은 시스템의 다른 프로세스에 일반적으로 영향을 주지 않음
  • Ubuntu 23.10 이상에서는 다음 설정이 필요함
    • sudo sysctl -w kernel.apparmor_restrict_unprivileged_unconfined=0
    • sudo 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 엔드포인트를 확인할 수 있음
  • 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 출력

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.65127.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을 종료해야 함
  • --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됨

댓글과 토론

it was developed at the Monastic Academy in Vermont in the US. We believe that a monastic schedule, and the practice of the Buddhist spiritual path more generally, provide ideal conditions for technological development.

테스트하면서 깃헙을 보니. 수도원 수련? 하시는 분들이 영적 성취의 일환으로 만들었나 싶기도 합니다.

Hacker News 의견들
  • README의 “How it was made” 섹션이 도구 자체만큼이나 흥미로웠음
    100에이커가 조금 넘는 땅에서 함께 살고 수행하며, 아침저녁으로 함께 염불하고 명상하고, 매달 약 1주일은 명상 리트릿을 운영하고 참여한다고 함. 나머지 시간에는 땅 관리, 건물 유지보수, 요리, 청소, 계획, 모금, 그리고 지난 몇 년간은 소프트웨어 개발까지 함께 한다는 내용임

    • “Soul of a new machine”의 한 구절이 떠오름
      마이크로코드와 논리가 나노초 단위로 문제를 일으키던 시기에, 과로한 엔지니어 한 명이 퇴사하면서 터미널에 사직서로 이런 메모를 남겼다고 함: “나는 Vermont의 코뮌으로 가서 계절보다 짧은 시간 단위는 다루지 않겠다”
    • 솔직히 말하면, 서구권 곳곳에 이미 많은 요가/영성 컬트 중 하나처럼 들림
    • “지난 몇 년간 우리는 Buddhism for AI라는 강의 시리즈를 녹화해 왔습니다. AI 시스템이 직접 소비할 수 있도록 불교에 기반한 종교, 네, 종교를 설계하려는 노력에 관한 것입니다. 세계 상황을 고려하면 우리는 이 일이 매우 중요하다고 느낍니다”라는 부분이 지금 우리가 사는 시대가 얼마나 이상한지를 보여주는 지표처럼 느껴짐
      좋은 아이디어인지, 그들이 상상하는 결과로 이어질지는 별개의 문제임
    • 첫 시골 사진이 생성 이미지라고 생각했는데, 이제는 실제 사진인 듯함
      기술과 명상의 조합은 끌림. 아이디어 자체는 매력적이지만 실제로 하는 건 아마 어려울 것 같음. 일종의 불교식 Recurse처럼 보임
  • httptap은 루트 권한 없이 실행할 수 있는 프로세스 범위의 HTTP 추적기임
    httptap <프로그램>처럼 리눅스 프로그램을 실행하면 표준 출력으로 HTTP/HTTPS 요청과 응답 추적을 볼 수 있음

    httptap -- python -c "import requests; requests.get('https://monasticacademy.org')"
    ---> GET https://monasticacademy.org/
    <--- 308 https://monasticacademy.org/ (15 bytes)
    ---> GET https://www.monasticacademy.org/
    <--- 200 https://www.monasticacademy.org/ (5796 bytes)

    격리된 네트워크 네임스페이스 안에서 실행하는 방식이고, 자체 TCP/IP 스택으로 gVisor를 사용함. HTTP 프록시가 아니라서 프록시 설정에 의존하지 않음. TLS 트래픽은 즉석에서 CA를 생성해 복호화하고, iptables 규칙을 설치하거나 전역 시스템 변경을 하지 않음

    • macOS에서도 동작하게 할 수 있는지 궁금함. Tailscale이 macOS의 일부 기능에서 gVisor의 TCP/IP 라이브러리를 netstack 라이브러리로 쓰는 것으로 알고 있음
    • 요청이나 응답을 수정할 수 있는지 궁금함. 현재 웹이 점점 사용자에게 적대적으로 변하면서 이런 도구의 필요성이 어느 때보다 커졌음
      특히 프록시 설정이 필요 없다면 더 유용함
    • 루트 없이도 실행할 수 있는 Wireshark를 다들 잊은 건가 싶음
      https://blog.wireshark.org/2010/02/running-wireshark-as-you/
  • 프로세스를 격리된 네트워크 네임스페이스에서 실행하는 아이디어가 천재적임
    HTTPS 부분이 더 흥미로움. 임시 디렉터리의 CA 번들을 쓰도록 프로그램에 공통 환경 변수[1]를 설정하는 것으로 보이는데, http_proxy 변형들과 비슷하게 프로그램이 그 변수를 그냥 무시할 수 있다는 문제가 있음

    /etc/resolv.conf에 오버레이 파일시스템을 마운트하는 것도 보임[2]. httptap이 /etc/ca-certificates 디렉터리를 임시 CA 번들로 마운트하면 도움이 될지 궁금함

    [1] https://github.com/monasticacademy/httptap/blob/cb92ee3acfb2...
    [2] https://github.com/monasticacademy/httptap/blob/cb92ee3acfb2...

    • 임의의 프로세스에 CA 루트를 지정하는 합의된 방식이나 시스템이 강제하는 방식이 사실상 없어서 답답하다는 데 동의함
      httptap이 /etc/resolv.conf에 오버레이를 마운트하는 건 DNS 해석도 CA 루트와 비슷하게 임의 프로세스에 어떤 DNS 서버를 쓰라고 확실히 말할 방법이 없기 때문임. 그래도 /etc/resolv.conf는 꽤 신뢰할 만한 선택지임. 프로세스를 네트워크 네임스페이스에 넣는 순간, 데스크톱 리눅스에서 가장 흔한 설정인 systemd 리졸버 localhost:53에 더는 접근할 수 없으므로 DNS 해석을 제공해야 함
      /etc/ca-certificates를 오버레이로 마운트하는 것도 도움이 될 수 있음. 다만 그 디렉터리 구조를 살펴보니 배포판마다 너무 일관성이 없어 당황스러웠음. 그래도 가능은 함. 적어도 일부 TLS 구현이 인식할 방식으로 그 디렉터리에 인증서를 추가하는 법에 대한 지식이 있으면 듣고 싶음
    • HTTPS 부분에는 모든 종류의 프로그램과 긴 꼬리의 인증서 고정 구현까지 포괄하는 일반 해법은 없다고 봄
      반례로, TLS로 통신하고 컴파일된 코드를 강하게 난독화한 악성코드를 상상할 수 있음. 고정된 CA 인증서 묶음을 바이너리에 포함하고 파일시스템을 전혀 열지 않는 프로그램일 수 있음. 그래도 대부분의 루트 CA 인증서가 만료되기 전까지 약 10년 정도는 유효하고 안전한 TLS 연결을 만들 수 있음. TLS는 전부 사용자 공간에서 처리되며 OpenSSL이나 다른 공통 라이브러리를 쓴다는 보장이 없으므로 특정 OpenSSL 함수에 후킹하는 방식도 기대할 수 없음. 서버가 자체 서명 인증서를 쓰고 클라이언트가 어떤 이유로든 이를 받아들이면 더 나빠짐
      그래도 약간의 작업으로 99% 사례를 안정적으로 처리하는 건 분명 가능함. 아무것도 없는 것보다는 낫다
  • 여기에 TUN 장치를 쓰는 건 정말 멋진 아이디어임. README의 “How it was made” 섹션도 GitHub README에서 읽은 것 중 최고 수준임
    Subtrace[1]라는 것을 만들고 있는데, 들어오는 요청과 나가는 요청을 모두 자동으로 가로챌 수 있음. 프로그램을 시작하는 인터페이스도 같은 형태로 수렴한 것 같아 웃김[2]. 다만 Subtrace의 목적은 httptap과 약간 다르고, 클라우드 백엔드 서비스의 관측성/모니터링 쪽에 더 가까워서 양방향 요청을 강조함. 접근 방식도 다름. Seccomp BPF로 socket, connect, listen, accept 등 약 10개의 시스템 호출을 가로채 모든 TCP 연결을 Subtrace를 통해 프록시함. 이후 TCP 스트림에서 HTTP 요청을 파싱하고, Chrome DevTools의 Network 탭을 일반 웹앱처럼 브라우저에서 동작하도록 재활용해 사용자에게 보여줌

    httptap 아래에서 프로그램을 실행하면서 나온 재미있는 일화가 있는지 궁금함. 어느 프로그램이 가장 많이 집에 전화하는지도 궁금함

    [1] https://github.com/subtrace/subtrace
    [2] https://docs.subtrace.dev/quickstart

    • Android의 VPN 서비스를 사용해 패킷 필터링을 하는 NetGuard가 떠오름. 원시 TUN 대신 Android VPN 서비스를 씀
      https://github.com/M66B/NetGuard
    • 캡처한 내용을 Chrome DevTools에 연결하는 것도 흥미롭고, eBPF를 쓰는 것도 흥미로움. 개발자 도구를 독립형 웹앱으로 실행되게 만든 것도 훌륭함
      믿기 어렵겠지만 Firefox 네트워크 탭에 대해 같은 일을 하려던 반쯤 만든 시도가 저장소의 networktab 디렉터리에 있음. 아주 멋진 프로젝트라 더 배우고 싶고, 더 이야기해도 좋음
  • 권한 없는 사용자가 네트워크 트래픽을 분석하는 또 다른 도구로 rootless Podman과 Pasta를 쓸 수 있음
    podman run 옵션에 다음을 추가하면 됨

    --network=pasta:--pcap,myfile.pcap

    그러면 Pasta가 네트워크 트래픽을 PCAP 파일로 기록하고, 나중에 분석할 수 있음. tshark로 기록된 PCAP 파일을 분석하는 간단한 예제도 작성해 둠
    https://github.com/eriksjolund/podman-networking-docs?tab=re...

    • 알아두면 아주 좋지만, 여전히 TLS 트래픽 복호화 문제가 남음
  • 꽤 흥미로움. Go 애플리케이션에서 비슷한 “탭” 기능을 하는 라이브러리를 작성한 적이 있음: https://github.com/henvic/httpretty
    https://asciinema.org/a/297429

    임의의 프로그램에 대해 이런 식으로 해볼 생각도 했지만 실제로 구현 방법을 깊게 파보지는 않았음. 누군가 만들어낸 걸 보니 반가움

  • eBPF를 쓰지 않는지 궁금함. 그러면 이미 실행 중인 것까지 포함해 모든 프로세스의 HTTP 요청을 한꺼번에 볼 수 있을 텐데. 게다가 TLS도 신경 쓸 필요 없이 예를 들어 write(2)에 후킹하면 될 것 같음

    • write(2)에 후킹하는 게 TLS를 어떻게 해결하는지 모르겠음. 암호문을 읽고 수정할 수는 있겠지만, 프로세스가 평문 바이트로 write(2)를 호출하지 않으니 실제 HTTP 요청은 읽을 수 없음. 결국 네트워크에 올라가는 암호화된 바이트만 보게 되고, 그건 NSA도 볼 수 있음
      httptap이 쓰는 것 같은 CA 인증서 트릭이 필요함. 물론 인증서 고정 같은 주의점이 있지만, 대부분의 실용적인 시나리오에서는 안정적으로 동작하게 만들 수 있음
      Subtrace[1]를 만들면서 이 특정 문제를 말이 안 될 정도로 많이 생각해 봐서, 더 단순하거나 우아한 접근이 있다면 진심으로 관심이 있음
      [1] https://github.com/subtrace/subtrace
    • 안타깝게도 TLS는 커널이 아니라 애플리케이션 내부에서 일어나므로, eBPF로 write 시스템 호출을 후킹해도 TLS 복호화에는 도움이 안 됨
    • SSL 라이브러리에 uprobe를 걸면, 복호화된 HTTP 응답 같은 내용을 검사하고 수정해 콘텐츠를 필터링할 수 있을지 궁금함
    • eBPF는 아마 루트 권한이 필요하지 않나 싶음
    • 이 방식은 루트가 필요하지 않을까? httptap의 큰 “판매 포인트”는 정확히 루트 권한이 필요 없다는 점으로 보임
      어쨌든 선택지가 많을수록 좋음
  • 멋짐. nginx 설정 디버깅에 바로 써볼 것 같음
    지금은 curl -v를 쓰고 출력에서 뭐가 잘못됐는지 수동으로 훑어봐야 하는데, 이 도구라면 리다이렉트 루프 같은 것이 바로 드러날 듯함

    • 실제 사용 맥락에서 어떻게 동작하는지, 특히 어떤 기능이 유용할지 듣고 싶음
  • 앱의 HTTP/S 호출 스택을 빠르고 거칠게 살펴봐야 할 때 아주 좋아 보임
    개인적으로는 모든 것을 보려고 eBPF를 선호하지만, 이 유틸리티는 eBPF 추적에서 중요한 부분을 좁혀 보는 데 도움이 될 수 있음

  • 좋아 보임
    GitHub 프로필이 https://www.monasticacademy.org/about를 가리키는데, 그 자체에 특별한 의견은 없지만 이들의 수도원식 훈련 리트릿과 GitHub 프로젝트가 어떻게 연결되는지 궁금했음
    README 맨 아래를 보니 연결이 설명되어 있었음: https://github.com/monasticacademy/httptap?tab=readme-ov-fil...

    • 이 스레드를 보는 사람들을 위해 말하자면, 연결점은 단순히 httptap이 Monastic Academy 프로젝트라는 것임
      그 의미는 Vermont의 123에이커 땅에서 사람들이 비교적 전통적인 불교 수도원 구조에 따라 함께 살고 있다는 것임. 다만 정식 수계를 받은 승려는 아님. 낮에는 여러 기술/비기술 프로젝트를 함께 진행함. 위에 올라온 README 링크가 좋은 개요임
      https://github.com/monasticacademy/httptap?tab=readme-ov-fil...