[HN Gopher] Httptap: View HTTP/HTTPS requests made by any Linux ...
       ___________________________________________________________________
        
       Httptap: View HTTP/HTTPS requests made by any Linux program
        
       Author : alexflint
       Score  : 312 points
       Date   : 2025-02-03 16:28 UTC (6 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | alexflint wrote:
       | httptap is a process-scoped http tracer that you can run without
       | root priveleges. You can run `httptap <command>` where <command>
       | is a linux program and you get a trace of http/https requests and
       | responses in standard output:                   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)
       | 
       | It works by running <command> in an isolated network namespace.
       | It has its own TCP/IP stack (for which it uses gVisor). It is not
       | an HTTP proxy and so does not rely on <command> being configured
       | to use an HTTP proxy. It decrypts TLS traffic by generating a CA
       | on the fly. It won't install any iptables rules or make other
       | global system changes.
        
         | gear54rus wrote:
         | can it modify requests or responses? with the current web
         | getting increasingly user-hostile a need for tool like this was
         | never more apparent
         | 
         | especially if it doesn't require proxy configuration
        
           | alexflint wrote:
           | Agreed! So there isn't any interface for modifying
           | requests/responses at present, but it's definitely possible
           | given the underlying approach. If you consider [this line of 
           | code](https://github.com/monasticacademy/httptap/blob/main/ht
           | tp.go...) where you have an HTTP request parsed from the
           | <command> that ran and are about to send it out to the public
           | internet: you could modify the request (or the response that
           | is received a few lines further) in just the way that you
           | would modify a normal http.Request in Go.
        
             | _boffin_ wrote:
             | Injecting random data into telemetry requests to mess up
             | someone's pretty dashboard?
        
               | gear54rus wrote:
               | There's at least https://adnauseam.io/ for that already
        
           | pcpuser wrote:
           | You might find mitmproxy useful.
        
             | alexflint wrote:
             | Yep, mitmproxy is fantastic IMO.
        
               | gear54rus wrote:
               | Apparently there's JS interface for it too:
               | https://www.npmjs.com/package/mitmproxy
               | 
               | But the problem with it is that you have to configure
               | proxy in the app (they do got transparent and wireguard
               | modes but there's still quite a bit of configuration).
        
           | knome wrote:
           | if the program doesn't pin certificates, you should be able
           | to intercept them by telling your machine to trust a
           | certificate authority of your own creation and performing a
           | mitm attack on the process's traffic. if it does do
           | certificate pinning, then it won't trust your home issued
           | cert, and will refuse to send data through your proxy.
        
         | maxmcd wrote:
         | Do you know if it's possible to get this working on macos? I
         | believe Tailscale uses gvisor's tcp/ip lib (as their netstack
         | lib) on macos for certain things.
        
           | mdaniel wrote:
           | Does Darwin have network namespaces like the Linux kernel
           | does? I get the impression that's an important component of
           | this approach
        
             | maxmcd wrote:
             | Yes, good point, maybe that is the blocker.
        
               | jshier wrote:
               | No network namespaces, but the various Network Extension
               | APIs might be able to do this, though it's difficult.
               | RocketSim (I'm unaffiliated, just an example) recently
               | added a simulator-specific network throttle (to replace
               | the system-wide Network Link Conditioner Apple ships)
               | using a content filter extension. Even though this is a
               | system-wide API, it seems you can limit its impact to a
               | single app. And it seemed to properly compose with
               | Proxyman and Cloudflare's Warp VPN at the same time, so
               | perhaps it could be a general solution.
        
               | alexflint wrote:
               | Woah, this is super helpful info. Thanks. That sounds
               | like a real possibility for a macOS port actually.
        
         | wutwutwat wrote:
         | Did everyone forget about wireshark, which can totally be ran
         | as non-root?
         | 
         | https://blog.wireshark.org/2010/02/running-wireshark-as-you/
        
           | lights0123 wrote:
           | It certainly doesn't provide automated, process-scoped HTTPS
           | interception.
        
           | boobsbr wrote:
           | It's still more setup than just installing this tool.
           | 
           | Also, can Wireshark/libpcap decrypt SSL/TLS traffic this
           | easily?
        
           | alexflint wrote:
           | Wireshark is awesome but yeah as others mentioned it's the
           | TLS decryption piece that is difficult in that workflow
        
       | progforlyfe wrote:
       | very helpful for inspection and testing!
        
       | yoavm wrote:
       | The "How it was made" section of the README was not less
       | interesting than the tool itself:
       | 
       | > The way we have set things up is that we live and practice
       | together on a bit over a hundred acres of land. In the mornings
       | and evenings we chant and meditate together, and for about one
       | week out of every month we run and participate in a meditation
       | retreat. The rest of the time we work together on everything from
       | caring for the land, maintaining the buildings, cooking,
       | cleaning, planning, fundraising, and for the past few years
       | developing software together.
        
         | erdii wrote:
         | To be honest: This sounds like just another of the many many
         | other yoga/spiritual cults that currently exist all over the
         | western world.
         | 
         | EDIT: typos and slight wording changes
        
           | quesera wrote:
           | There is absolutely nothing in their README to suggest that
           | you are using the word "cult" properly.
        
             | MisterTea wrote:
             | Did you visit their website?
             | https://www.monasticacademy.org/
             | 
             | While I cannot judge them outright, their article "Cyborgs
             | Need a Trustworthy Religion" can appear cultist as they try
             | to intertwine technology and religion.
        
               | 2030ai wrote:
               | The fine line between futurism and cult.
        
               | MisterTea wrote:
               | I feel that spirituality does not concern itself with the
               | material world making it immune to societal progress.
               | Whereas organized religion becomes mired by societal
               | progress as it's trapped in its own zeitgeist. I believe
               | that trying to tie the two together is a misguided
               | attempt at creating something when there is nothing that
               | needs to be created.
        
           | yoavm wrote:
           | I believe I grew up in a cult myself, and one of the things
           | I've concluded from that experience, and from leaving it, is
           | that everywhere is a cult. Humans have a tendency towards
           | cult-ish life, and if the cult is big enough we just refer to
           | it as "society". People were as afraid (more or less) to
           | leave the cult I was at, as people are around me now when
           | they consider doing anything that is out of the norm.
           | 
           | By no mean am I trying to hint towards some conspiracy, or to
           | say that all cults are equally bad (or good); Just to say
           | that sometimes the word cult simply means "a less popular way
           | of life than the one most people around me live by".
        
         | abraae wrote:
         | Reminds me of a quote from "Soul of a new machine":
         | 
         | > During one period, when the microcode and logic were
         | glitching at the nanosecond level, one of the overworked
         | engineers departed the company, leaving behind a note on his
         | terminal as his letter of resignation: "I am going to a commune
         | in Vermont and will deal with no unit of time shorter than a
         | season."
        
           | alexflint wrote:
           | Wow that's an incredible quote! It feels like that to me too.
        
           | why_at wrote:
           | Great quote, although the nitpicky part of my brain
           | immediately thought "They must have days though?"
        
         | 2030ai wrote:
         | I sadly assumed the first countryside photo was generated but I
         | assume now it is real!
         | 
         | The mix of tech and meditation would appeal to me. Maybe the
         | idea does (actually doing it is probably hard!).
         | 
         | It seems like a "Buddhist Recurse"
        
           | alexflint wrote:
           | Yeah that photo is real! That's where I live!
           | 
           | Yes, it's true, actually doing it is hard, but to be honest
           | not as hard as a lot of other stuff (getting a phd for
           | example, or goodness gracious buying a house in San
           | Francisco). I love getting up early. I love living out in
           | nature. I love chanting and eating meals together and making
           | a version of Buddhism for AI systems!
           | 
           | If you're interested in what it's like, we have written a
           | bunch of very short few-paragraph stories about our time at
           | MAPLE here: https://tales.monasticacademy.org/
        
       | sevg wrote:
       | This looks great!
       | 
       | The GitHub profile points to
       | https://www.monasticacademy.org/about which I have no particular
       | opinion on but it did leave me wondering what the connection is
       | between their monastic training retreat and their projects on
       | GitHub.
       | 
       | Edit: Oh, I didn't go to the bottom of the readme
       | https://github.com/monasticacademy/httptap?tab=readme-ov-fil...
        
         | alexflint wrote:
         | Yeah, for other readers who are looking at this thread, the
         | connection is just that this (httptap) is a Monastic Academy
         | project, and what that means is that there is a group of people
         | living on 123 acres in Vermont according to a fairly
         | traditional Buddhist monastic structure (though we are not
         | ordained monks), and during the day we work on a number of
         | technology and non-technology projects together. The link to
         | the readme that sevg posted above is a good overview:
         | 
         | https://github.com/monasticacademy/httptap?tab=readme-ov-fil...
        
       | tacone wrote:
       | Whoa, great!
       | 
       | Questions:
       | 
       | - What's the performance impact?
       | 
       | - Does it allow payload/headers inspection?
        
         | alexflint wrote:
         | Thanks!
         | 
         | Haven't measured performance at all. However when I decided on
         | the approach I looked at the performance benchmarks from
         | tun2socks, which uses the same gVisor code that httptap uses,
         | and it seems that pretty great performance is possible with
         | that code. Still need to do the work of actually achieving
         | comparable performance.
         | 
         | Payloads and headers can be dumped with --body and --header
         | respectively. There is an example in the readme of doing this
         | (just search for --body) and I'll work more on documenting this
         | in the coming days.
        
           | abracadaniel wrote:
           | I see it supports .har, but .warc support would be amazing.
           | It's the iso standard for web archives, which would give you
           | the ability to replay archived websites via multiple tools.
        
             | alexflint wrote:
             | Fascinating, I hadn't heard of WARC - thanks for the
             | pointer and I'll consider it.
        
       | emcell wrote:
       | This is gold! Thank you!
        
       | notepad0x90 wrote:
       | I really like their approach. other methods that might use
       | something like LD_PRELOAD fail on statically linked ELF's, like
       | golang binaries.
        
       | quinnjh wrote:
       | This is something I've needed more than a handful of times - and
       | each time slowly figured out a cobbled together solution with
       | wireshark / pcap
       | 
       | Fun reading about the authors too.
       | 
       | Thank you for sharing !
        
         | alexflint wrote:
         | Same here actually -- have wanted this from time to time for
         | years. Finally sat down and worked it out.
        
       | maxmcd wrote:
       | Amazing, such a great use of the gvisor userspace tcp/ip stack!
        
         | alexflint wrote:
         | Yeah learning about gVisor was one of the most fun parts of
         | this project. The gVisor devs are incredibly helpful. If you
         | look through the gvisor-users mailing list you'll see me asking
         | them various questions about this and they really helped out a
         | bunch with some incredibly thorough answers.
        
       | adtac wrote:
       | Using a TUN device for this is a really cool idea! And the "How
       | it was made" section is one of the best things I've read in a
       | Github README.
       | 
       | I'm building something called Subtrace [1] but it can intercept
       | both incoming and outgoing requests automatically. Looks like we
       | converged on the same interface for starting the program too lol
       | [2]. Subtrace's purpose is kinda different from httptap's though
       | (more observability / monitoring for cloud backend services,
       | hence the emphasis on both incoming _and_ outgoing). Also, it
       | uses a different approach -- using Seccomp BPF to intercept the
       | socket, connect, listen, accept, and ~10 other syscalls, all TCP
       | connections get proxied through Subtrace. We then parse the HTTP
       | requests out of the TCP stream and then show it to the user in
       | the Chrome DevTools Network tab, which we repurposed to work in
       | the browser like a regular webapp.
       | 
       | Any fun stories there from running programs under httptap? Who
       | phones home the most?
       | 
       | [1] https://github.com/subtrace/subtrace
       | 
       | [2] https://docs.subtrace.dev/quickstart
        
         | afarah1 wrote:
         | Reminds me of NetGuard, which uses Android's VPN service
         | (instead of raw TUN) for packet filtering.
         | https://github.com/M66B/NetGuard
        
           | alexflint wrote:
           | Wow, did not know about this!
        
         | alexflint wrote:
         | Super cool! Connecting what you capture to Chrome DevTools is
         | fascinating, as is using eBPF. Great work getting the devtools
         | to run as a standalone web app. You won't believe it but I have
         | a half-finished attempt of the same thing for the firefox
         | network tab - in the "networktab" dir of the repo!
         | 
         | Very cool project, would love to learn more and happy to chat
         | more about it.
        
           | adtac wrote:
           | Thanks! Subtrace uses BPF, not eBPF :) I think eBPF could be
           | made to work with the same approach, but there's a few
           | differences:
           | 
           | - eBPF requires root privileges or at least CAP_BPF. Subtrace
           | uses seccomp_unotify [1], so it works even in unprivileged
           | environments.
           | 
           | - eBPF requires using eBPF maps as the data channel + weird
           | restrictions in the code because of the eBPF verifier. IMO
           | these two things make it way harder to work with for the kind
           | of networking logic that both httptap and Subtrace have in
           | userspace. Everything is perfectly possible, just harder to
           | reason about and debug.
           | 
           | >half-finished attempt of the same thing for the firefox
           | network tab
           | 
           | Hahahah this is incredible. Something something great minds.
           | 
           | [1] https://man.archlinux.org/man/seccomp_unotify.2.en
        
       | ranger_danger wrote:
       | Why not use eBPF instead? Then you could see all http requests
       | from all processes at once, including ones that are already
       | running. Plus you wouldn't need to bother with TLS at all, just
       | hook on e.g. write(2).
        
         | TacticalCoder wrote:
         | Wouldn't this require root? A big "selling point" of httptap
         | seems to be that precisely it doesn't require root.
         | 
         | Anyway the more options we have, the better.
        
         | somanyphotons wrote:
         | Presumably eBPF requires root privs?
        
           | trallnag wrote:
           | I'm having a hard time coming up with a use case where I want
           | to use a tool like that but I'm also lacking root privileges
        
             | freedomben wrote:
             | Inside most production environments. I could use this today
             | inside a Pod that isn't allowed root privs.
        
               | zamubafoo wrote:
               | In production environments that won't give you root
               | access, you won't be exec'ing inside of a pod if you
               | aren't an operator or sysadmin.
        
               | imcritic wrote:
               | No, you are wrong. I would. The pod would be mine though.
        
         | adtac wrote:
         | How would hooking on write(2) solve TLS? You'll be able to read
         | and modify the ciphertext, but the process will never call
         | write(2) with the plaintext bytes, so you can't actually read
         | the HTTP request. You'll just see the encrypted bytes that go
         | on the wire, but so does the NSA :)
         | 
         | You need the kind of CA certificate trick that httptap uses. It
         | comes with its own set of caveats (e.g. certificate pinning),
         | but it can be made to work reliably in most practical
         | scenarios.
         | 
         | I've spent an unjustifiable amount of time thinking about this
         | specific problem building Subtrace [1], so I'm genuinely very
         | interested in a simpler / more elegant approach.
         | 
         | [1] https://github.com/subtrace/subtrace
        
         | alexflint wrote:
         | Unfortunately TLS happens inside the the application, not in
         | the kernel, so using eBPF to hook syscalls to write won't help
         | with TLS decryption.
        
       | eriksjolund wrote:
       | Another tool that can be used by an unprivileged user for
       | analysing network traffic is rootless Podman with Pasta.
       | 
       | Just add the podman run option
       | 
       | --network=pasta:--pcap,myfile.pcap
       | 
       | Pasta then records the network traffic into a PCAP file that
       | could later be analysed.
       | 
       | I wrote a simple example where I used tshark to analyse the
       | recorded PCAP file https://github.com/eriksjolund/podman-
       | networking-docs?tab=re...
        
         | alexflint wrote:
         | Very good to know about. But you still have the problem of
         | decrypting TLS traffic.
        
           | mdaniel wrote:
           | I don't know if it's a _standard_ but I believe a lot of tls
           | libraries honor the SSLKEYLOGFILE env-var https://wiki.wiresh
           | ark.org/TLS#:~:text=and%20curl%20when-,th...
        
             | 2030ai wrote:
             | That seems like an unnecessary vulnerability waiting to
             | happen.
        
       | ranger_danger wrote:
       | does not seem to support SOCKS proxies which I rely on
        
         | alexflint wrote:
         | Interesting. Care to share any info about your setup? Would it
         | be a matter of httptap reading a certain environment variable
         | and then forwarding traffic to a SOCKS proxy?
         | 
         | FWIW there is also the excellent tun2socks
         | (https://github.com/xjasonlyu/tun2socks), which was a
         | significant inspiration for this project, and is specifically
         | designed to forward traffic from a TUN device to a SOCKS proxy.
        
       | freedomben wrote:
       | Neat! This will immediately be used by me to debug nginx configs.
       | Currently I use curl -v and have to manually skim the output to
       | figure out what's wrong, but this would immediately make redirect
       | loops and other things apparent. Cool tool!
        
         | alexflint wrote:
         | Very cool! Would love to hear how it goes, especially any
         | features that would be useful in the context of real-world
         | usage.
        
       | wzyboy wrote:
       | It's a genius idea to run the process in a isolated network
       | namespace!
       | 
       | I'm more interested in the HTTPS part. I see that it sets some
       | common environment variables [1] to instruct the program to use
       | the CA bundle in the temporary directory. This seems to pose a
       | similar issue like all the variants of `http_proxy`: the program
       | may simply choose to ignore the variable.
       | 
       | I see it also mounts an overlay fs for `/etc/resolv.conf` [2].
       | Does it help if httptap mounts `/etc/ca-certificates` directory
       | with the temporary CA bundle?
       | 
       | [1]
       | https://github.com/monasticacademy/httptap/blob/cb92ee3acfb2...
       | 
       | [2]
       | https://github.com/monasticacademy/httptap/blob/cb92ee3acfb2...
        
         | alexflint wrote:
         | Thanks! But yep I agree, you're exactly right, it's
         | ultimately... frustrating that there isn't really an agreed-
         | upon or system-enforced way to specify CA roots to an arbitrary
         | process.
         | 
         | It's true that httptap mounts an overlay on /etc/resolv.conf.
         | This is, as you'd expect, due to the also-sort-of-frustrating
         | situation with respect to DNS resolution in which, like CA
         | roots, there isn't a truly reliable way to tell an arbitrary
         | process what DNS server to use, but /etc/resolv.conf is a
         | pretty good bet. As soon as you put a process into a network
         | namespace you have to provide it with DNS resolution because it
         | can no longer access localhost:53, which is the systemd
         | resolver, which is the most common setup now on desktop linux
         | systems.
         | 
         | I do think it might help to mount /etc/ca-certificates as an
         | overlay. When I started looking into the structure of that
         | directory I was kind of dismayed... it's incredibly
         | inconsistent from one distro to the next. Still, it's doable.
         | Interested in any knowledge you might be able to share about
         | how to add a cert to that directory in a way that would be
         | picked up by at least some TLS implementations.
        
           | xorcist wrote:
           | It's a bit thin solution though, isn't it? As you say, it's
           | dependent on both specific CA store and resolver behaviour.
           | It's probably going to be robust enough on the most common
           | SSL libraries, such as OpenSSL. But if we're going that
           | route, why not just run the software against a patched SSL
           | library which dumps the traffic?
           | 
           | That also doesn't require any elevated privileges (as opposed
           | to other methods of syscall interception) and is likely much
           | easier to do. It has the added benefit of being robust
           | against applications either pinning certificates outright or
           | just being particular about serial numbers, client
           | certificates, and anything like that.
        
         | adtac wrote:
         | IMO there's no general solution to the HTTPS part that will
         | work for all kinds of programs and the long tail of certificate
         | pinning implementations.
         | 
         | As a proof by counterexample, imagine malware that uses TLS for
         | communication and goes to great lengths to obfuscate its
         | compiled code. It could be a program that bundles a fixed set
         | of CA certificates into its binary and never open any files on
         | the filesystem. It can still create valid, secure TLS
         | connections (at least for ~10 years or so, until most root CA
         | certificates expire). TLS is all userspace and there's no
         | guarantee that it uses OpenSSL (or any other common library),
         | so you can't rely on hooking into specific OpenSSL functions
         | either. If the server uses a self-signed certificate and the
         | client accepts it for whatever reason, it's worse.
         | 
         | With that said, it's definitely possible to handle 99% of the
         | cases reliably with some work. That's better than nothing.
        
       | josephcsible wrote:
       | Is this implementing TCP in userspace?
        
         | aerzen wrote:
         | Yes
        
         | alexflint wrote:
         | Yep. This is the first time I've mentioned this but there are
         | actually two implementations of this in the codebase -- one
         | uses gVisor and one is an incredibly bare-bones TCP
         | implementation that I wrote myself in 550 lines of Go code
         | (tcp.go). The home-grown one isn't used by default and it
         | doesn't support much of TCP proper, but it actually works
         | pretty well. You can use it with `--stack=homegrown`.
        
       | q2dg wrote:
       | Mitmproxy v11.1 can do a similar thing
        
         | alexflint wrote:
         | Yeah mitmproxy is great. The main difference with httptap is
         | that it's an HTTP proxy server, so you have to configure your
         | program to use a proxy server. When I wrote httptap I wanted to
         | be able to run `httptap <command>` and see the httptraces right
         | there in standard output. There is an absolute ton of cool
         | things that mitmproxy can do that httptap is not even close to,
         | like interactively modifying HTTP requests and such. Very cool
         | project.
        
           | mhils wrote:
           | > so you have to configure your program to use a proxy
           | server.
           | 
           | That's not true for local capture mode:
           | https://mitmproxy.org/posts/local-capture/linux/. :)
        
       | extraduder_ire wrote:
       | Does this work with larger more complicated software like web
       | browsers, skype, or discord?
       | 
       | I know I'd have to run firefox with --no-remote.
       | 
       | Very cool idea though, love tools with this sort of UX. I look
       | forward to a V1 release in the future.
        
         | alexflint wrote:
         | Thanks!
         | 
         | I did try this with firefox but it doesn't work right now due
         | to (I think) the user namespace messing with user IDs. I think
         | I should be able to fix this, though. I will have to try it
         | with other desktop apps soon too...
        
       | wslh wrote:
       | That's a great DX! I wonder if an alternative way is to just hook
       | functions like read, and write, and other functions linked to the
       | SSL libs. It is true that you should be aware of the SSL libs in
       | place but OpenSSL is the most popular.
        
         | alexflint wrote:
         | This is a very interesting possibility actually. Not 100% sure
         | what the implication would be but maybe there is something
         | here.
        
           | wslh wrote:
           | You can use a hooking library like these [1].
           | 
           | [1] https://github.com/frida/frida/wiki/Comparison-of-
           | function-h...
        
       | concerndc1tizen wrote:
       | Which privileges are required? CAP_NET_ADMIN? Or nothing at all?
        
         | alexflint wrote:
         | Nothing at all!
         | 
         | You _do_ need write access to  /dev/net/tun. This is standard
         | for all users for the distros that I've looked into, but it is
         | ultimately a distro-specific thing.
        
       | mhils wrote:
       | This is really cool, thank you for sharing! We've built a similar
       | feature for mitmproxy lately, but with different tradeoffs. Our
       | approach does require root and we don't have automated
       | certificate install (yet), but we don't require apps to run in a
       | dedicated namespace (so you can capture already-running
       | processes). Super awesome to see this now, excited to dive into
       | the code and see how you do TCP reassembly etc. :)
        
       | xyst wrote:
       | Very cool if you need a quick and dirty way to inspect the http/s
       | call stack of an app. Personally prefer eBPF to get _everything_
       | but using this utility can help drill down what is important in
       | the eBPF trace
        
       ___________________________________________________________________
       (page generated 2025-02-03 23:00 UTC)