New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unify proxy modes, introduce UDP protocol detection. #5556
Conversation
@mhils: Before I'm adjusting and (re-)adding tests, could you maybe have a quick look as to whether the way the "new" modes are implemented is something you'd sign off on? Thanks :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall this looks great, mostly dumb clarification questions below! Please don't read any judgement/sentiment into these comments, reviewing on mobile is tricky and they might be stupid questions. 😅
mitmproxy/proxy/mode.py
Outdated
@@ -0,0 +1,173 @@ | |||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reason for moving this out of mode_specs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Python and it's cyclic dependencies 😅
But I'll restore the 1:1 ServerInstance
s, which will move the layers
-dependency to mode_servers.py
again, so I can move mode.py
back into mode_specs.py
.
@@ -40,40 +39,37 @@ class DNSLayer(layer.Layer): | |||
Layer that handles resolving DNS queries. | |||
""" | |||
|
|||
flow: dns.DNSFlow | |||
flows: dict[int, dns.DNSFlow] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How/why do we end up having multiple DNS flows here now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the history here is: We had that before, in the DNS draft. Then we moved the ID into the connection_id of proxyserver (i.e. essentially the dict
). However, if we want to do protocol detection and fancy transparent stuff, DNS might not be at the top layer, so the layer itself will have to do it.
It's the same with QUIC. We've talked about connection migration (which currently also uses connection_id in proxyserver) and the change of SendData
and DataReceived
to include the remote address, that ideally should not happen. So there we will also need a layer that does the routing instead, keeping the old SendData
and not using custom connection_id
.
And that's actually a good thing: Having uniform connection id's is the only way to reliably do inject_udp
in the future.
mitmproxy/proxy/mode.py
Outdated
raise RuntimeError("Proxy modes are frozen.") | ||
|
||
|
||
class AsyncioProxyMode(ProxyMode, metaclass=ABCMeta): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel this complicates things more than it helps. Maybe we can move description
into ProxyMode itself and then keep the layer information as part of individual server instance subclasses? That avoids the special-casing in ServerInstance.make
, keeps all modes as immediate subclasses of ProxyMode, retains a dumb 1-1 mapping between modes and instances, and avoids any circular spec -> layer -> spec dependencies. This may entirely be "code I wrote myself is easier to understand" bias, so feel free to go ahead with this approach if you feel it's more straightforward. Just a subjective impression. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it's just my code-compressing attitude, but you're right. Having 1:1 ServerInstance
s removes all the if TYPE_CHECKING
stuff, so I'll undo the changes.
Looks fantastic now! 🍰 😃 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice! 🍰
In case you want to inspect raw traffic only for some hosts and HTTP for | ||
others, have a look at the [tcp_hosts]({{< relref "concepts-options" >}}#tcp_hosts) | ||
and [udp_hosts]({{< relref "concepts-options" >}}#udp_hosts) options. | ||
- Say you want to capture DNS traffic to Google's Public DNS server? Then you |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at this it probably would make sense to make the default port scheme-specific for reverse proxy mode. DNS should be on 53 by default. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, here's the PR: #5563 :)
Description
Contains changes for #5535.
udp.py
and is not even used/enabled.Together with add Windows OS proxy mode #5543, I'll plan to do re-add transparent UDP mode later in a similar fashion, i.e. a separate process, asking for sudo if necessary, setting everything up for the user. In the meantime,
udp.py
has now full coverage.AsyncioServerInstance
andProxyMode
to support both protocols for oneProxyMode
. In the process, the need for additionalServerInstances
disappeared, soProxyMode
s now fully describe proto, port and layer.make_connection_id
. Since we don't know on what layer we'll detect what protocol, we can't use the DNS-ID inServerManager
connection-ID trick anymore - same as goes for QUIC, if we don't want to alterSendData
andDataReceived
(see Add QUIC support. #5435 (review)).--mode reverse:dns://8.8.8.8
if used with an upstream,--mode dns
will launch a local-resolve server.ServerManager
connection-IDs, but if we detect DNS higher up, or in the future use some transparent mode, this can't be done this way anymore.