Skip to content
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

Add support for transparent proxying on Linux #197

Merged
merged 2 commits into from
Mar 27, 2020
Merged

Conversation

alxbl
Copy link
Collaborator

@alxbl alxbl commented Mar 23, 2020

This feature adds the ability to tell PyRDP to perform a transparent connection to the server by using the source IP of the client. This cannot be fully supported by PyRDP and relies on firewall configuration to properly route traffic.

The PR adds documentation of an example scenario and configuration, along with the required PyRDP code to create a transparent socket.

README.md Show resolved Hide resolved
pyrdp/core/twisted.py Outdated Show resolved Hide resolved
@Res260
Copy link
Collaborator

Res260 commented Mar 23, 2020

Very cool 👍

@alxbl alxbl added this to the vNext milestone Mar 24, 2020
Copy link
Member

@obilodeau obilodeau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's well documented and well written (non-invasive).

  • It should be documented as incompatible with docker images. It could probably work with --privileged and probably --net=host but lets just say untested or unsupported.

There's one thing I don't understand. Packets meant for 10.2.2.2 are rewritten to hit localhost on the mitm. The process receives them, creates a connection with tansparent mode. So far so good. But what about after? When the process replies to the original host, shouldn't a transparent socket be used there also? Otherwise you can detect in a packet capture that your server is not the one you expect. Am I missing something?

@alxbl
Copy link
Collaborator Author

alxbl commented Mar 25, 2020

should be documented as incompatible with docker images.

I remember writing something about that. I can't remember if it was in the code or decided to not include it after, but yes, I agree. I'll clarify.

what about after? When the process replies to the original host, shouldn't a transparent socket be used there also? Otherwise you can detect in a packet capture that your server is not the one you expect. Am I missing something?

The packets coming from the target server (replies) are marked using a PREROUTING rule. Then an ip routing rule is saying that all of the packets marked with that mark must be routed using a custom routing table, which contains a single rule: route through loopback. This effectively forces the packets to hit loopback, and thus the transparent socket opened during the connection receives the data. PyRDP has all of the state to forward back to the client socket.

It is kind of mind-bending, but it works :)

@obilodeau
Copy link
Member

I think I wasn't clear enough. I don't see how packets coming back from the MITM to the client are being source rewritten so that to the client it's the real server that replied and not the MITM. I'll diagram it:

             DNAT happens here  +  transparent socket is here
                  +             |
                  |             |
+--------+        v  +--------+ v        +---------+
| Client +--------+->+  MITM  +-+-------->  Server |
|        |           |        |          |         |
|        +<-+--------+        +<---------+         |
+--------+  ^        +--------+          +---------+
            |
            |
            + I don't see how this flow could have the right
              source IP (10.2.2.2). Nothing in the iptable
              rules or the code does anything to do so.

If you don't have a pcap from the client's perspective, I'll checkout the branch and try to create one to verify. Or maybe you can answer me directly too.

@alxbl
Copy link
Collaborator Author

alxbl commented Mar 26, 2020

I'm pretty sure it's because the socket is already opened with the intended destination of 10.2.2.2 when being prerouted, so the source IP on replies is set to 10.2.2.2 by the MITM's linux kernel.

here's a PCAP: proxy.tar.gz
10.6.66.24: Client (priv0)
10.2.0.126: Server (qemu0)
10.2.0.1: MITM (Gateway) (qemu0)

Follow streams 2 and 3

I do not have a PCAP from the client's PoV, but feel free to grab one if you want to confirm

Copy link
Member

@obilodeau obilodeau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alxbl performed another capture from the client's perspective to satisfy my curiosity.

image (15)

This is good to go!

@obilodeau obilodeau merged commit 8708918 into master Mar 27, 2020
@obilodeau obilodeau deleted the transparent-proxy branch August 6, 2021 17:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants