Skip to content

Commit 5bac768

Browse files
committed
add mitmproxy 11.1 blogpost
1 parent b9fc03d commit 5bac768

File tree

2 files changed

+136
-0
lines changed

2 files changed

+136
-0
lines changed
416 KB
Loading
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
---
2+
title: "Intercepting Linux Applications"
3+
date: 2025-01-12
4+
weight: 10
5+
tags:
6+
- releases
7+
- local-capture
8+
authors:
9+
- maximilian-hils
10+
- emanuele-micheletti
11+
- gaurav-jain
12+
- fabio-valentini
13+
---
14+
15+
Following Windows and macOS, mitmproxy's local capture mode is now available on Linux as well!
16+
mitmproxy 11.1 can seamlessly intercept local applications on all three major platforms.
17+
18+
<!--more-->
19+
20+
## Windows, macOS, ...and now Linux!
21+
22+
After debuting local capture mode for [macOS]
23+
and [Windows] about a year ago, we're happy to report that our eBPF-based Linux implementation
24+
is now ready for testing. On all three platforms, users can now intercept specific applications without
25+
setting system-wide proxy settings.
26+
27+
[macOS]: {{< relref "./macos" >}}
28+
[Windows]: {{< relref "./windows" >}}
29+
30+
You can try it out as follows:
31+
32+
```shell
33+
# Capture all local traffic
34+
mitmproxy --mode local
35+
# Capture cURL only
36+
mitmproxy --mode local:curl
37+
```
38+
39+
## How it works
40+
41+
mitmproxy's traditional proxying modes (HTTP/SOCKS/reverse proxy) are platform-independent, but
42+
local capture mode requires a unique approach for every operating system.
43+
macOS tormented us with hard-to-debug code-signing requirements for system extensions,
44+
but it provided us with relatively nice [APIs for traffic redirection] in return.
45+
Windows did not bring such comforts, but it had [external libraries] to make up for it.
46+
Finally, Linux offered us a plethora of solutions that *almost* met our requirements, but
47+
most of them turned out to have one or two crucial gaps.
48+
49+
#### Road to eBPF
50+
51+
We initially looked at iptables/nftables to redirect traffic. While both tools work great to capture connections
52+
for a particular IP address or pid, they fall short of redirecting traffic for a particular
53+
process name. However, we wanted to capture by process name to have the same capture mechanism across platforms.
54+
Network namespaces would have been equally wonderful to use, but we found them very hard to package into a
55+
good user experience.
56+
To cut a long story short, we eventually decided to write an [eBPF] program to redirect traffic.
57+
58+
eBPF is a technology that allows us to run a program within the Linux kernel at a low level,
59+
but --- in contrast to a kernel extension --- does not require us to modify the kernel.
60+
This is promising in theory, but development proved to be harder than expected. Official documentation for eBPF is sparse
61+
and the kernel's eBPF verifier, which ensures that our program is safe to run, likes to complain in
62+
mysterious ways. With [kernel/bpf/verifier.c] clocking in at 22.801 lines of C code at the time of writing, making sense
63+
of errors sometimes isn't easy. Fortunately, tools like [Aya] make eBPF development significantly easier and
64+
Isovalent's [docs.ebpf.io] fills a lot of the documentation gaps.
65+
66+
#### Redirection
67+
68+
{{<
69+
figure src="architecture.png"
70+
caption="mitmproxy_rs architecture"
71+
width="90%"
72+
>}}
73+
74+
To implement the actual redirection, mitmproxy does the following:
75+
76+
1. mitmproxy_rs spawns the redirector as a privileged subprocess with `sudo`.
77+
This is necessary so that the redirector can invoke the `bpf()` syscall.
78+
2. The redirector...
79+
1. Creates a new virtual network device (typically `/dev/tun0`).
80+
2. Loads our [BPF_PROG_TYPE_CGROUP_SOCK] BPF [program].
81+
3. Connects back to mitmproxy_rs to learn which programs to intercept.
82+
4. Passes this information to the BPF program via a shared map.
83+
3. Every time a new socket is created, the BPF program determines whether it should be intercepted.
84+
If that's the case, it re-routes the socket to mitmproxy by assigning it to our virtual network device.
85+
4. The redirector now reads all packets from `/dev/tun0` and forwards them to mitmproxy_rs (and vice versa).
86+
5. mitmproxy_rs reassembles raw packets into TCP/UDP streams using our existing user-space network stack and then
87+
passes them on to mitmproxy.
88+
89+
This method is considerably more complex than a simple iptables rule, but we gain fine-grained control
90+
over what to intercept.
91+
92+
[APIs for traffic redirection]: {{< relref "./macos#how-does-it-work" >}}
93+
[external libraries]: {{< relref "./windows#how-it-works" >}}
94+
[eBPF]: https://docs.ebpf.io/
95+
[WireGuard® mode]: {{< relref "wireguard-mode" >}}
96+
[WinDivert]: https://github.com/Rubensei/windivert-rust
97+
[kernel/bpf/verifier.c]: https://github.com/torvalds/linux/blame/master/kernel/bpf/verifier.c
98+
[Aya]: https://aya-rs.dev/
99+
[docs.ebpf.io]: https://docs.ebpf.io/
100+
[BPF_PROG_TYPE_CGROUP_SOCK]: https://docs.ebpf.io/linux/program-type/BPF_PROG_TYPE_CGROUP_SOCK/
101+
[program]: https://github.com/mitmproxy/mitmproxy_rs/blob/8f9372fc5bde5eb1910fc7e773a60132a17319b5/mitmproxy-linux-ebpf/src/main.rs#L17-L27
102+
103+
#### Limitations
104+
105+
Local capture mode on Linux comes with a few limitations:
106+
107+
- **Egress only:** mitmproxy will capture outbound connections only.
108+
For inbound connections, we recommend reverse proxy mode.
109+
- **Root privileges:** To load the BPF program, mitmproxy needs to spawn a privileged subprocess using `sudo`.
110+
For the web UI, this means that mitmweb needs to be started directly with `--mode local` on the command line
111+
to get a sudo password prompt.
112+
- **Kernel compatibility:** Our eBPF instrumentation requires a reasonably recent kernel.
113+
We officially support Linux 6.8 and above, which matches Ubuntu 22.04.
114+
- **Intercept specs:** Program names are matched on the first 16 characters only (based on the kernel's [TASK_COMM_LEN]).
115+
- **Containers:** Capturing traffic from containers will fail unless they use the host network.
116+
For example, containers can be started with `docker/podman run --network host`.
117+
- **Windows Subsystem for Linux (WSL 1/2):** WSL is unsupported as eBPF is disabled by default.
118+
119+
120+
[TASK_COMM_LEN]: https://github.com/torvalds/linux/blob/fbfd64d25c7af3b8695201ebc85efe90be28c5a3/include/linux/sched.h#L306
121+
122+
## Next Steps
123+
124+
Local redirect mode is now available for Windows, Linux, and macOS users in mitmproxy 11.1.
125+
We have more plans to improve the user experience,
126+
but we already want to make the current state available for everyone to try.
127+
If you are curious about contributing, please join us on [GitHub]!
128+
129+
[GitHub]: https://github.com/mitmproxy/mitmproxy/issues/6531
130+
131+
## Acknowledgments
132+
133+
This work was supported by the [NGI0 Entrust fund] established by [NLnet].
134+
135+
[NGI0 Entrust fund]: https://nlnet.nl/entrust/
136+
[NLnet]: https://nlnet.nl/

0 commit comments

Comments
 (0)