haitao-wang / badvpn

Automatically exported from code.google.com/p/badvpn
Other
0 stars 0 forks source link

Ignore certain ports? #14

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
I realise this is more of a request than a bug but I am not sure where requests 
should be posted?

What I'd really like to be able to do is exclude certain ports from the system. 
So for example a mail client connecting to IMAP or SMTP would bypass tun2socks 
and use the default gateway.

This is fairly easy to do in Linux but Windows does not offer any sort of per 
port routing.

I'm fairly sure it would be easy enough to have tun2socks detect those ports 
and do something different with them in case they are part of the exclusion 
list but where I'm getting stuck is the what..

Say a connection for port 25 comes in and tun2socks decides it should not send 
this connection through the SOCKS as far as I can tell there is no way for it 
to establish the connection as any attempt to make the connection directly will 
end up right back into tun2socks due to the system routing rules?

The only way I can think of is perhaps intercepting the packets with dest port 
25 from within tun2socks and forwarding them to another gateway kind of like an 
ip tables packet filter in linux..

That is where I'm getting stuck as packet processing goes beyond my knowledge 
of badvpn.

Is what I'm suggesting even possible?

I'm happy to look at the code if you could point me in the right direction?

Many thanks

Original issue reported on code.google.com by mike...@gmail.com on 3 Dec 2013 at 9:36

GoogleCodeExporter commented 8 years ago
I've been thinking before about this, because it really would be useful. But 
I've reached similar conclusions. There doesn't seem to be an easy way to 
redirect connections to where they would go in the absence of tun2socks. So I 
see making the OS route them to where you want the only way to go.

But that is highly platform dependent. Unfortunately, from my googling, it 
doesn't seem possible on Windows, at least on the network layer. It may be 
possible on the socket layer using the "Layered Service Provider" interface.

But it's fair to say it would be a great undertaking, and at least I don't have 
the time or need for such a feature.

Original comment by ambr...@gmail.com on 15 Dec 2013 at 9:26

GoogleCodeExporter commented 8 years ago
Thanks for your reply. Actually I figured out how to do it very easily on 
Windows!

It works by checking the ports on new connections and when it sees a port it 
should ignore it does not connect to the SOCKS server but instead connects 
directly to the destination IP and of course does not do any of the socks 
initialization stuff, it just sends and receives the data directly.

The problem of course is that with routing setup the new connection will just 
go straight back to tun2socks again and end up in a never ending loop. The 
trick is before connecting to the destination IP/port you bind the new socket 
to the main interface IP, that forces Windows to use that interface therefore 
bypassing the routing table.

Because I get tun2socks to connect to a local proxy before that proxy connects 
out to a remote server I do this myself locally without changing the tun2socks 
code but I'm sure it can be done very easily in that code too.

So currently the code goes something like...

1) New connection received by tun2socks
2) Connect to provided socks server
3) Authenticate with socks & send dest info
4) Start tunnelling data between source and proxy

For ports to be ignored

1) New connection received by tun2socks
2) New socket created and bound to main interface IP (not TAP)
3) Socket connects to destination IP/port
4) Start tunnelling data between source and dest

Works beautifully here!

Original comment by mike...@gmail.com on 16 Dec 2013 at 9:21

GoogleCodeExporter commented 8 years ago
Wow, that's wonderful. Such a nice trick!

From what I understand, you've already gotten it to work? In that case would 
you mind sharing the code? If it's that easy it just may get into "official" 
tun2socks distribution ;)

Original comment by ambr...@gmail.com on 16 Dec 2013 at 9:27

GoogleCodeExporter commented 8 years ago
Oh sorry I missed the bit about your local proxy.

Original comment by ambr...@gmail.com on 16 Dec 2013 at 9:43

GoogleCodeExporter commented 8 years ago
I can yeah but as I said I made the change in my local socks code, not in 
tun2socks.. I know my way around my code so I implemented the change in a few 
minutes.. changing tun2socks would take me quite a bit longer!

The binding code is simple enough:

struct sockaddr_in sa_loc;
memset(&sa_loc, 0, sizeof(struct sockaddr_in));
sa_loc.sin_family = PF_INET;
sa_loc.sin_port = htons(0);
sa_loc.sin_addr.s_addr = inet_addr((const char*)localIP);
bind(handle, (struct sockaddr *)&sa_loc, sizeof(struct sockaddr));

Getting the main interface IP is a little more tricky and the way I do it has 
to be done BEFORE the routing table is modified so I do it when my app starts 
up.

1) GetIpForwardTable() to get the routing table
2) Look for the route with 0.0.0.0
3) Call GetIpAddrTable() and using the IFIndex from GetIpForwardTable return 
the first (address) field

Sorry I don't have this as a complete code solution as I'm doing half of it in 
my C++ socks code and the other have in my C# service code.

Original comment by mike...@gmail.com on 16 Dec 2013 at 9:43

GoogleCodeExporter commented 8 years ago
Oh, I forgot to mention that an entry needs to exist in the routing table for 
0.0.0.0 using the main interface, just with a higher metric than the route for 
tun2socks

Original comment by mike...@gmail.com on 16 Dec 2013 at 10:11