3P by GN⁺ | ★ favorite | 댓글 1개
  • QUIC와 HTTP/3 트래픽 비중이 커지면서 mitmproxy 11은 HTTP/3를 기본 활성화해 최신 웹 트래픽 분석 범위를 넓힘
  • 투명 프록시와 리버스 프록시뿐 아니라 WireGuardlocal mode에서도 HTTP/3가 동작해 다양한 캡처 환경에 적용 가능함
  • Chrome은 QUIC에서 사용자가 추가한 Certificate Authority를 신뢰하지 않아 공개 신뢰 인증서, 명령줄 스위치, HTTP/2 폴백 중 하나를 선택해야 함
  • DNS 구현은 Hickory DNS 기반으로 바뀌며 A/AAAA 외 쿼리, HTTPS records, DNS-over-TCP, hosts 파일 제어, ECH 키 제거를 다룸
  • ECH 같은 프라이버시 기능은 중간자 프록시의 인증서 생성 흐름을 어렵게 만들지만, mitmproxy는 DNS 응답 조정으로 동작 가능성을 유지함

HTTP/3 지원 범위

  • mitmproxy 11은 HTTP/3를 투명 프록시와 리버스 프록시 모드에서 지원함
  • 리버스 프록시에서는 하나의 mitmproxy 인스턴스가 TCP와 UDP 패킷을 모두 수신하고, 전달되는 HTTP 버전을 처리함
  • WireGuardlocal mode에서도 HTTP/3를 사용할 수 있음
    • 예시 명령:
      mitmproxy --mode wireguard
      mitmproxy --mode local
      
  • Firefox, Chrome, 여러 cURL 빌드와 다른 클라이언트로 테스트해 호환성 문제를 줄임
  • HTTP/3 지원 작업은 2022년에 Manuel Meitinger와 Maximilian Hils가 시작했으며, mitmproxy 11에서 기본 활성화됨

Chrome의 QUIC 인증서 제약

  • 현재 알려진 주요 제한은 Chrome이 QUIC에서 사용자가 추가한 Certificate Authority를 신뢰하지 않는다는 점임
  • Chrome에서 HTTP/3 트래픽을 다루려면 다음 중 하나가 필요함
    • Let’s Encrypt 같은 공개적으로 신뢰되는 인증서 제공
    • Chrome을 관련 명령줄 스위치와 함께 실행
    • HTTP/2로 폴백되는 동작 수용
  • Firefox는 이와 같은 동작을 하지 않음
  • HTTP/3 문제 해결 팁은 #7025에서 확인할 수 있음

Hickory DNS 기반 재구현

  • DNS HTTPS records와 Encrypted Client Hello(ECH) 같은 프라이버시 기능이 등장하면서 mitmproxy의 DNS 처리 중요도가 커짐
  • 기존 DNS 구현은 getaddrinfo를 사용했기 때문에 한계가 있었음
    • IPv4와 IPv6 주소용 A/AAAA 쿼리만 지원함
    • HTTP/3 지원을 알리는 HTTPS records 같은 쿼리에 응답할 수 없었음
  • mitmproxy 11은 DNS 지원을 Rust 기반 DNS 라이브러리인 Hickory DNS 위에 다시 구현함
  • Hickory를 통해 Windows, Linux, macOS에서 운영체제의 기본 네임서버를 얻고, A/AAAA가 아닌 쿼리를 해당 네임서버로 전달함
  • dns_name_servers 옵션으로 전달 대상 네임서버를 지정할 수 있음
    mitmdump --mode dns --set dns_name_servers=8.8.8.8
    

hosts 파일 제어와 DNS-over-TCP

  • Hickory 전환과 함께 시스템 hosts 파일을 무시하는 옵션이 추가됨
  • dns_use_hosts_file 옵션을 사용하면 Linux의 /etc/hosts 같은 hosts 파일 반영 여부를 제어할 수 있음
  • mitmproxy의 내부 DNS 해석도 Hickory로 옮길 계획이며, 이후에는 같은 머신에서 특정 도메인을 투명 리디렉션할 때 이 기능이 유용해짐
    • 현재는 hosts 파일을 항상 고려하기 때문에 같은 머신 리디렉션 설정에서 mitmproxy가 자기 자신으로 재귀 연결될 수 있음
  • 예시 동작:
    echo "192.0.2.1 mitmproxy.org" >> /etc/hosts
    mitmdump --mode dns
    dig @127.0.0.1 +short mitmproxy.org
    192.0.2.1
    mitmdump --mode dns --set dns_use_hosts_file=false
    dig @127.0.0.1 +short mitmproxy.org
    3.161.82.13
    
  • DNS는 기본적으로 UDP를 사용하지만, 단일 UDP 패킷에 들어가지 않는 레코드를 처리할 때 TCP가 필요할 수 있음
  • mitmproxy 11은 임의 쿼리 타입을 지원하면서 메시지 크기와 TCP 처리의 중요도가 커졌고, DNS-over-TCP도 동작함

ECH 키 제거와 인증서 생성

  • mitmproxy는 사용자 지정 인증서가 없을 때 TLS ClientHello의 Server Name Indication(SNI) 를 사용해 유효한 인증서를 구성함
  • SNI가 없으면 클라이언트가 신뢰할 인증서를 생성하지 못할 수 있음
  • Encrypted Client Hello(ECH)는 클라이언트가 DNS HTTPS records로 ECH 키를 얻은 뒤, 초기 ClientHello 핸드셰이크 메시지를 그 키로 암호화하는 방식임
  • DNS 쿼리와 핸드셰이크가 모두 암호화되면 수동 중간자는 대상 도메인을 알 수 없고, 대상 IP 주소만 확인할 수 있음
    • 공유 호스팅과 Content Delivery Networks에서는 IP 주소만으로 대상 도메인을 확정하기 어려움
  • 이 프라이버시 개선은 mitmproxy의 인증서 생성 방식과 충돌함
  • mitmproxy 11은 HTTPS records에서 ECH 키를 제거해 인증서 생성에 필요한 도메인 정보를 확보함
    • 클라이언트는 초기 핸드셰이크 메시지를 암호화할 키를 얻지 못함
    • mitmproxy는 대상 도메인을 파악하고 일치하는 인증서를 구성할 수 있음
  • ECH는 mitmproxy 사용을 더 어렵게 만들 수 있지만, 웹 전반의 프라이버시를 높이는 변화로 볼 수 있음

댓글과 토론

Hacker News 의견들
  • Mitmproxy가 아직 개발되고 있다니 반가움. 이 도구가 간접적으로 내 커리어를 만들어 줬음
    2011년에 모바일 앱 요청을 가로채며 API 개발을 배우다가, Airbnb API가 Rails 대량 할당 취약점(https://github.com/rails/rails/issues/5228)에 노출돼 있다는 걸 발견함. 무해한 속성 몇 개를 바꿔 본 뒤 회사에 연락했고, 그게 면접으로 이어졌으며 이후는 말 그대로 역사가 됨

    • 그 이슈에서 핵심 개발자들이 변경에 반대하던 수가 정말 말도 안 될 정도였음
    • 지금도 나한테는 엄청 유용한데, 알 만한 사람들도 의외로 Mitmproxy를 잘 모르는 경우가 많음
      가끔은 문서를 읽는 것보다 기존 구현에 mitmproxy를 붙여 보는 편이 더 쉬움
  • Chrome이 QUIC에서 사용자가 추가한 인증 기관을 신뢰하지 않는다는 부분이 흥미로움
    연결된 이슈에서 Chrome 팀은 “QUIC 가로채기 소프트웨어/하드웨어 배포를 막기 위해 공개적으로 신뢰되지 않는 인증서를 명시적으로 허용하지 않는다. 그렇지 않으면 장기적으로 QUIC 프로토콜의 진화 가능성을 해친다. 공개 신뢰 인증서가 아닌 인증서에 의존하는 용도는 QUIC 대신 TLS+TCP를 쓰면 된다”고 함
    프로토콜 진화를 따라가진 않지만, 사용자 지정 인증서를 막는 게 어떻게 진화 가능성과 연결되는지는 잘 모르겠음. 이유를 아는 사람이 있는지 궁금함

    • 추측하자면 Google이 클라이언트와 대형 서버 엔드포인트(Google Search, Youtube 등)를 모두 통제하므로 QUIC 변경 실험을 자유롭게 하려는 것 같음
      Chrome에 약간 수정한 QUIC 버전을 넣고 Youtube 같은 곳에서 지원한 뒤, 그 지표를 바탕으로 “진짜” 표준 변경을 제안하거나 자기 서비스에서만 특수 버전을 계속 돌릴 수 있음
      사용자 지정 인증서를 허용하면 ZScaler ZIA 같은 걸로 직원 트래픽을 중간자 방식으로 검사하는 기업들이 프로토콜 변경 때 깨질 위험이 생김. 데이터 스트림이 완전히 암호화되어 중간 장비에 불투명하면 Google은 거의 원하는 대로 할 수 있음
      관련 개념: https://en.wikipedia.org/wiki/Protocol_ossification
    • 중간 장비(https://en.m.wikipedia.org/wiki/Middlebox)는 프로토콜 정체의 잘 알려진 원인임
      확장 가능한 프로토콜은 보통 클라이언트와 서버만 업그레이드하면 되지만, 중간 장비가 있으면 잠재적으로 N개의 장비도 함께 업데이트해야 함. 사용자와 서비스 제공자는 새 기능 도입 동기가 있지만, 중간 장비 소유자는 그렇지 않을 수 있음. 결과적으로 프로토콜이 진화하기 어려워짐
    • 금융기관들이 TLS 1.3에 반대했던 유명한 사례를 가리키는 걸 수도 있음. 규정 준수를 위해 필요한 중간자 소프트웨어를 업데이트하고 싶지 않았던 게 동기였음: https://mailarchive.ietf.org/arch/msg/tls/CzjJB1g0uFypY8UDdr6P9SCQBqA/
    • HTTP 2와 3을 만든 이유 중 하나도 HTTP 1.1 변경이 너무 어려웠기 때문임
      구현 세부 사항에 강하게 의존하는 미들웨어가 많아서, 뭔가를 조금 바꾸면 의도치 않게 사용자 환경을 깨뜨리기 쉬웠음. 새 버전에서는 비슷한 상황을 피하려는 것으로 보임
    • QUIC은 광고 전달률을 높이기 위해 존재하므로, 사용자에게 자유를 주는 건 그 목표와 충돌함
  • HTTP/2나 HTTP/3가 리버스 프록시에서만 지원되고 실제 웹 서버에서는 지원되지 않아도 이점이 있는지 궁금함
    JS/Python/Ruby의 주류 프레임워크 대부분은 새 HTTP 표준을 지원하지 않음. 그러면 웹 서버가 리버스 프록시 연결의 병목이 되지 않을까?

    • 있음. HTTP/2나 HTTP/3는 클라이언트와 리버스 프록시 사이 연결의 신뢰성을 높여 줌
      리버스 프록시와 실제 웹 서버 사이 연결은 보통 훨씬 빠르고 안정적이라, 그 구간을 HTTP/2나 HTTP/3로 올려도 얻는 이득이 훨씬 작음
    • 리버스 프록시와 백엔드 사이 전송이 항상 HTTP인 것도 아님. 예를 들어 Python은 uWSGI, PHP는 FastCGI를 쓰기도 함
      HTTP를 쓰는 경우에도, 리버스 프록시는 실제 원격 클라이언트보다 백엔드와 훨씬 빠르게 연결을 맺을 수 있음. 그래서 느린 구간에서 HTTP/2 스트림을 쓰는 게 여전히 유리함
    • 아마 큰 의미는 없겠지만, mitmproxy는 운영 환경용 리버스 프록시가 아님
      로컬 머신에서 실행하면서 저수준 프로토콜이나 웹 보안 관련 테스트를 하는 도구임
    • 빠진 점이 하나 있음. 웹 브라우저는 도메인당 연결 수를 6개로 제한함
      HTTP/2 이상에서는 여러 동시 요청을 하나의 연결로 처리함
    • 있음. 다른 성능 이점도 있지만, HTTP/3는 TCP와 TLS 핸드셰이크를 결합해 연결 시 왕복 1회를 줄여 줌
  • 아직 지문 인식 문제가 남아 있음. 일반적인 브라우저의 TLS 핸드셰이크를 흉내 낼 수 있기 전까지는 웹의 80% 정도에서 “Just a quick check...”나 “Sorry, it looks like you're a bot” 같은 페이지를 보게 됨
    https://github.com/mitmproxy/mitmproxy/issues/4575

    • 그렇다면 Firefox는 더 이상 일반적인 브라우저가 아닌 모양임
  • Hickory를 언급해 줘서 고마움. 사람들이 그걸로 뭘 만드는지 보는 건 늘 재미있고, 잘 만든 작업임

    • Hickory 작업에 감사함. PyO3의 Python↔Rust 상호 운용 덕분에 Hickory 같은 운영급 DNS 라이브러리와 smoltcp 같은 탄탄한 사용자 공간 네트워킹 스택을 Python에서 쓸 수 있게 된 점이 정말 흥미로움
      이런 것들은 원래 Python만으로는 얻기 어려웠을 것임
  • Mitmproxy를 Privoxy/Proxomitron/Yarip처럼 쓸 수 있는지 궁금함
    예를 들어 Ungoogled Chromium에서 브라우징할 때 Mitmproxy를 프록시로 두고, 특정 사이트의 script 태그를 제거할 수 있을까? 성능에는 어떤 영향이 있을까?

    • 이론상으로는 가능함. 실제로는 mitmproxy가 Python으로 작성되어 있어서 언어가 아주 빠르지 않은 만큼 지연이 생김
      웹 페이지를 볼 때 작은 지연이 수백 번 쌓이면 체감될 수 있음
      그래도 이런 용도에 관심 있는 사람들에게는 선택지가 될 수 있음. 기술적으로 막는 건 없음
      JavaScript 파일을 다시 쓸 때 하위 리소스 무결성 검사를 건드릴 작은 위험이 있지만, 실제로 문제가 생기면 해시도 다시 써서 해결할 수 있을 것 같음
  • mitmproxy가 Fiddler의 대안이 될 수 있나?

  • 음: https://github.com/mitmproxy/mitmproxy/issues/4170