matrix-org / complement-crypto

Apache License 2.0
11 stars 5 forks source link

MITM servers for fun tests #1

Closed kegsay closed 1 year ago

kegsay commented 1 year ago

There are concrete test cases which require us to fudge connectivity to the server or fudge responses the server sends back. We cannot currently do this using complement-crypto, because we lack the necessary tooling. This issue tracks the addition of such tooling.

NB: This is different to mock federation servers which Complement natively supports well.

Option A: Mock Client Server

Extend mock federation server support in Complement to support mock client server support. This would allow us to mock up registration, message sending, etc.

Pros:

Cons:

Option B: Reverse Proxy MITM

Shove nginx/apache/traefik in front of the real HS, and write reverse proxy configuration to send back mocked responses, reject endpoints, etc.

Pros:

Cons:

Option C: Go reverse proxy MITM

Use Go's httputil package to write a reverse proxy in the test.

Pros:

Cons:

Option D: Transparent(ish) RPC

Use something like https://github.com/hashicorp/go-plugin/ to write a plugin which can then communicate over some kind of RPC channel that we don't care about.

Pros:

Cons:

dkasak commented 1 year ago

Option E: mitmproxy DSL module for writing Matrix attack MITM proxies

Write a module for mitmproxy exposing a DSL for easily modifying:

a. Requests flowing into the homeserver, simulating malicious or faulty clients. b. Responses flowing out of the homeserver, simulating malicious or faulty homeservers.

Place this in front of either Synapse, Dendrite or Conduit.

Pros:

Cons:

kegsay commented 1 year ago

Additional cons for option E:

kegsay commented 1 year ago

I ended up doing a blend of option C and D.

The pros/cons end up being:

Pros:

Cons:

poljar commented 1 year ago

Additional cons for option E:

  • It's python, so language context switch problems the same as with reverse proxy configuration files.

But you can write Python using Rust. Actually, people already do that https://github.com/mitmproxy/mitmproxy_rs.

kegsay commented 1 year ago

Hmm, I do like the ability to have the web UI, and if it's a thing other people already use / have familiarity with then there is benefit to trying to make use of that.

In terms of configuration, these look to be equivalent (handrolled vs mitmproxy):

$ mitmdump --mode reverse:http://hs1@3000 --mode reverse:http://hs2@3001
$ REVERSE_PROXY_HOSTS=http://hs1,3000;http://hs2,3001 ./reverseproxy

Controlling what happens during the MITM process is the tricky bit I'm currently fleshing out. I want the API to look something like:

// stop /keys/query requests from working for alice, one time.
cancelInterception := tc.Deployment.ReverseProxyController.InterceptResponses(
    t, rp.RespondWithError(504, "Gateway Timeout"),
    rp.WithUserInfo(t, tc.Alice.BaseURL, tc.Alice.UserID, tc.Alice.DeviceID),
    rp.WithPathSuffix("/keys/query"),
    rp.WithRepititions(1),
)
defer cancelInterception()

so provided mitmproxy has the flexibility to do this then even if it is a custom DSL, it would be abstracted from the test. That way, those who do like mitmproxy can then make use of it.

kegsay commented 1 year ago

So it sounds like I want a custom add-on, which seems to be able to manipulate the request/response e.g https://docs.mitmproxy.org/stable/addons-examples/#http-add-header

However, I need this to be modifiable at runtime so each test can tweak what things get set. This probably means I need to have a port exposed on the mitmproxy container to accept arbitrary(?) addons.

poljar commented 1 year ago

So it sounds like I want a custom add-on, which seems to be able to manipulate the request/response e.g https://docs.mitmproxy.org/stable/addons-examples/#http-add-header

Yes, you will most certainly want to write an extension, or multiple ones.

This probably means I need to have a port exposed on the mitmproxy container to accept arbitrary(?) addons.

Would it perhaps work if have a master addon/extension which then picks which extension to actually execute and having it listen on a UNIX socket so you can control this behavior?

kegsay commented 1 year ago

That would compose pretty well if people then want to roll their own addons, it would just require the mitmproxy container to have all the addons preloaded in the image. It's also more secure than arbitrary code execution :D

dkasak commented 1 year ago

Also gives a nice foundation for reimplementing the Polyjuice tests in a potentially more robust way, due to not requiring a fake homeserver reimplementation.

kegsay commented 1 year ago

This now exists, but is missing contextual information to say "only do X for alice/device requests".

kegsay commented 1 year ago

We can go a long way just with mimproxy filters so using that for now. Will expand this when needed. Proof of concept: https://github.com/matrix-org/complement-crypto/blob/main/tests/client_connectivity_test.go#L34