tproxy support

309 views
Skip to first unread message

Brian May

unread,
May 21, 2011, 9:03:28 PM5/21/11
to sshuttle
Hello,

Now I have got tproxy working for UDP/TCP and IPv4/IPv6 support, some of the stickier issues:

* The sock.setsockopt(socket.SOL_IP, IP_TRANSPARENT, 1) function calls requires root access.

* The following routes are required:

ip route add local default dev lo table 100
ip rule add fwmark 1 lookup 100
ip -6 route add local default dev lo table 100
ip -6 rule add fwmark 1 lookup 100

Yes, we could add this manually, we can't remove them though, because of the possibility there is another sshuttle process running that is using them.

* The code uses recvmsg function, a POSIX standard function, that isn't available as part of standard python. Might try to prod the python developers on this.

* The code requires a git version of iptables.

* Does require a recent kernel version; however the version is Ubuntu natty is fine.

Brian May

unread,
May 22, 2011, 9:19:26 PM5/22/11
to sshuttle
I moved your response from another thread here, as I think it is more relevant to this thread. 

On 22 May 2011 11:58, Avery Pennarun <apen...@gmail.com> wrote:
Yes, and you seem to have discovered, it has a tonne of weird other
behaviours too, such as requiring root and having weird ioctls and
requiring weird routes and so on.  I don't like any of those things.
Divert sockets on BSD are simple and easy; hopefully the iptables
equivalent turns out to also be.

Like it or not, I think the current solution for divert sockets on Linux is tproxy. Everything else I could find was very old and no longer relevant.

I don't think it is as bad as you make out. Just need to receive a packet and find its src,dst addresses, and also send a packet with a given src,dst address.

Obviously being able to fake src addresses needs to have root access. Root access is already needed to set up the firewall tables. Still need to investigate if there are better ways of doing this. Root access, as before, is not required at the server however.

There isn't anything special about the recvmsg() function either, it is a POSIX standard function that has been implemented for years in BSD and Linux. It is just unfortunate that the Python developers haven't considered it important enough to implement these functions.

It is reasonably new I think, and as such good documentation is sadly lacking.
-- 
Brian May <br...@microcomaustralia.com.au>

Avery Pennarun

unread,
May 29, 2011, 10:35:30 PM5/29/11
to Brian May, sshuttle
On Sun, May 22, 2011 at 9:19 PM, Brian May
<br...@microcomaustralia.com.au> wrote:
> On 22 May 2011 11:58, Avery Pennarun <apen...@gmail.com> wrote:
>> Yes, and you seem to have discovered, it has a tonne of weird other
>> behaviours too, such as requiring root and having weird ioctls and
>> requiring weird routes and so on.  I don't like any of those things.
>> Divert sockets on BSD are simple and easy; hopefully the iptables
>> equivalent turns out to also be.
>
> Like it or not, I think the current solution for divert sockets on Linux is
> tproxy.
> Everything else I could find was very old and no longer relevant.

Well, no; tproxy is the equivalent of the ipfw 'fwd' rules. The
actual Linux equivalent of divert is libipq or libnetfilter_queue
(which supposedly replaces libipq).

Unfortunately, both of them seem to have kind of wonky APIs that would
be a bit of a pain to fake up using python. (I guess we'd have to use
the 'struct' module and whatnot.)

But they're definitely not irrelevant, and they do seem pretty handy,
and they're the "right" way to approach this sort of problem. In
particular, I think chaining should be possible.

> I don't think it is as bad as you make out. Just need to receive a packet
> and find its src,dst addresses, and also send a packet with a given src,dst
> address.
>
> Obviously being able to fake src addresses needs to have root access. Root
> access is already needed to set up the firewall tables. Still need to
> investigate if there are better ways of doing this. Root access, as before,
> is not required at the server however.

Okay, I'm starting to get confused by this whole thread. Why do we
need all this fancy TPROXY stuff again? Why do we need to fake the
source address?

Can't we just say "if the requested domain matches, then ask the
sshuttle server, else forward it to our normal DNS server"? The
source address will be the sshuttle client instead of the original
client, but I don't know why that would cause a problem.

Of course, I might like to proxy more UDP than just DNS someday. For
that, we need something smarter than what we have today. (And anyway,
UDP-over-TCP is a bad idea, so we'd have to get *much* smarter.)

But this TPROXY stuff seems like trouble to me, especially the need
for a really recent kernel. I don't want to make sshuttle require a
new kernel just to do fancy stuff with DNS that most people don't want
to do. I also don't want to support some kind of "if your kernel is
new, do it this way, if old, do it that way" fallback stuff.

So can't we just make the minimal changes to use the existing code,
but redirect to a different DNS server under some conditions?

> There isn't anything special about the recvmsg() function either, it is a
> POSIX standard function that has been implemented for years in BSD and
> Linux. It is just unfortunate that the Python developers haven't considered
> it important enough to implement these functions.
> It is reasonably new I think, and as such good documentation is sadly
> lacking.

Well yes, sendmsg() is part of the original BSD sockets specification,
as far as I know. But I've written a lot of networking code, and I've
never needed it, and it's not available in plain python, all of which
seem to be reasons to avoid things that require it.

Thanks,

Avery

Brian May

unread,
Jun 16, 2011, 1:47:09 AM6/16/11
to Avery Pennarun, sshuttle
Just catching up on my old emails ...

On 30 May 2011 12:35, Avery Pennarun <apen...@gmail.com> wrote:
> Okay, I'm starting to get confused by this whole thread.  Why do we
> need all this fancy TPROXY stuff again?  Why do we need to fake the
> source address?
>
> Can't we just say "if the requested domain matches, then ask the
> sshuttle server, else forward it to our normal DNS server"?  The
> source address will be the sshuttle client instead of the original
> client, but I don't know why that would cause a problem.

DNS isn't the application.

UDP and IPv6 are the applications.

The issue is that we (C) receive a packet from A to B. We forward the
packet down the tunnel. We get a response from the tunnel. The
response has a source of B and a destination of A. We can't just send
this to A (unlike with NAT) because the client we get the packet with
a source address of C. The client expected a source address of B.
Clients typically don't like this, and will discard the packet.

> Of course, I might like to proxy more UDP than just DNS someday.  For
> that, we need something smarter than what we have today.  (And anyway,
> UDP-over-TCP is a bad idea, so we'd have to get *much* smarter.)

Out of curiosity why do you consider UDP-over-TCP a bad idea?

I think it is better then TCP-over-TCP that a lot of people seem to
like (don't ask... I disagree). Not talking about what sshuttle does
here, that isn't really TCP-over-TCP.

Ok, so maybe it isn't appropriate for all applications (I think you
may get bad results with SIP for example), but I think there are
applications were it works fine.

There is also the sticky problem of how to know when to expire the
connection. No easy answer here, it depends on the application.

> But this TPROXY stuff seems like trouble to me, especially the need
> for a really recent kernel.  I don't want to make sshuttle require a
> new kernel just to do fancy stuff with DNS that most people don't want
> to do.  I also don't want to support some kind of "if your kernel is
> new, do it this way, if old, do it that way" fallback stuff.

You getting my TPROXY proposal and the DNS proposals confused. The DNS
changes I proposed (and put on hold for now) don't need the TPROXY
changes.

> So can't we just make the minimal changes to use the existing code,
> but redirect to a different DNS server under some conditions?

Yes. Just need to resurrect my old patch. However that will probably
need changing to make it work with my latest patches I just sent.

> Well yes, sendmsg() is part of the original BSD sockets specification,
> as far as I know.  But I've written a lot of networking code, and I've
> never needed it, and it's not available in plain python, all of which
> seem to be reasons to avoid things that require it.

I am working on getting it included in python. I have Debian packages
for Python 2.7 version containing the patch.

Unfortunately, it seems like the chances of getting it into the
official Python 2.x are nil.

I am also guessing that you may not be to happy in accepting patches
for Python 3.x at this stage. I think these would break compatibility
for Python less then 2.7, unfortunately.
--
Brian May <br...@microcomaustralia.com.au>

Reply all
Reply to author
Forward
0 new messages