-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Description
Problem Description
A large volume of QUIC requests to multiple hosts leads to lots of requests failing.
When transparently intercepting process traffic with mitmproxy, requests error out with "stream already ended" (compared to consistently flawless execution otherwise). Error is thrown from the following lines.
mitmproxy/mitmproxy/proxy/layers/http/_http_h3.py
Lines 230 to 245 in e6aa924
| elif isinstance(event, QuicStreamDataReceived): | |
| # Discard contents if we have already sent STOP_SENDING on this stream. | |
| if event.stream_id in self._closed_streams: | |
| return [] | |
| elif self._get_or_create_stream(event.stream_id).ended: | |
| # aioquic will not send us any data events once a stream has ended. | |
| # Instead, it will close the connection. We simulate this here for H3 tests. | |
| self.close_connection( | |
| error_code=QuicErrorCode.PROTOCOL_VIOLATION, | |
| reason_phrase="stream already ended", | |
| ) | |
| return [] | |
| else: | |
| return self.handle_event( | |
| StreamDataReceived(event.data, event.end_stream, event.stream_id) | |
| ) |
My guess is this is due to the large volume of QUERY requests / DNS queries - by the time the proxy starts processing the HTTP3 requests, the server has transmitted the proper data and closed the connection. I've made a minimal repo for reproduction.
Steps to reproduce the behavior:
- I have created a repo that sends ~300 requests to multiple hosts (Googleapis, and each is for a document. This won't cause any disruption, it's pretty static. And they're a big company) for reproduction purposes in https://github.com/bedros-p/quicmess - it is easy to review the source, as there isn't much to it.
go buildcreates a binaryquicmess. Run withquicmess multidomain.txtand confirm that there aren't any errors. This should take ~30 seconds and produce "All requests completed" at the end.- mitmproxy -> Local Applications -> Intercept traffic for process
quicmess - Run the binary with
./quicmess multidomain.txt, see the errorsstream already ended - Run the binary with
./quicmess samedomain.txt, see the lack of errors.
Here is what it looks like, with the highlighting indicating the moment I start intercepting it.

Here's mitmweb. After all the QUERYs, some make it through, then a couple don't. I couldn't find any patterns with the timings or size. Couldn't find any patterns to link with the entry preceding each error either.
System Information
Mitmproxy: 12.2.1 binary
Python: 3.14.0
OpenSSL: OpenSSL 3.5.4 30 Sep 2025
Platform: Linux-6.8.0-90-generic-x86_64-with-glibc2.35
Checklist
- This bug affects the latest mitmproxy release.