Commit Graph

36 Commits

Author SHA1 Message Date
Avery Pennarun
a81972b2b5 Add --wrap option to force channel number wrapping at a lower number.
This makes it easier to actually test what happens when channel numbers wrap
around.  The good news: it works.

However, I did find a bug where sshuttle would die if we completely ran out
of available channel numbers because so many of them were open.  This would
never realistically happen at the default of 65535 channels (we'd run out of
file descriptors first), but it's still a bug, so let's handle it by just
dropping the connection when it happens.
2011-02-02 02:32:46 -08:00
Avery Pennarun
a2fcb08a2d Extremely basic, but functional, DNS proxying support (--dns option)
Limitations:
- uses a hardcoded DNS server IP on both client and server
- never expires request/response objects, so leaks memory and sockets
- works only with iptables, not with ipfw
2011-01-26 02:34:46 -08:00
Avery Pennarun
d4c9d31068 Oops, we were being overzealous about calling nowrite().
We were doing it as soon as the other end was shut_read, but we didn't
confirm first that the other end's read buffer had been totally emptied.
This caused problems on twitter.com, at least, where they create a zillion
short-lived connections.

I don't actually need these lines at all, as it turns out, because we were
already calling nowrite() correctly on the other end after a buffer got
emptied.
2011-01-12 09:33:56 -08:00
Avery Pennarun
38bb7f3c21 If we get EPIPE on uwrite(), don't close, just do nowrite().
EPIPE doesn't mean the whole socket is dead, it just means we can't write to
it.  Maybe there's still data waiting to be read, though.
2011-01-12 09:19:43 -08:00
Avery Pennarun
b7f1530aef Remember which syscall got a particular stream-killing error. 2011-01-12 09:18:46 -08:00
Avery Pennarun
c3204d2728 Correctly close server connection when client disconnects.
When the server disconnected, we were forwarding that information to the
client.  But we weren't forwarding back the other way when the client
disconnected since there was no callback in place to do that.

Relatedly, when we failed entirely to connect to the server, we didn't notify the
client right away.  Now we do.

Thanks to 'Roger' on the mailing list for pointing out these bugs.
2010-12-31 21:59:36 -08:00
Avery Pennarun
41fd0348eb Fix a bug when packets are received on a channel after it closes.
Reported by cbowns.
2010-12-11 17:27:12 -08:00
Avery Pennarun
1907048dad Remove the never-used and misleading CMD_CLOSE. 2010-12-09 19:20:09 -08:00
Roger
82e1d1c166 Fix memory leak of MuxWrapper object.
(Note by apenwarr: I used Roger's original patch as the basis for this one,
but implemented it a different way.  All errors are thus my fault, but Roger
gets the credit for actually tracking down the circular reference that
caused the memory leak.)
2010-12-09 19:20:07 -08:00
Avery Pennarun
a497132c01 Add debug messages for counting SockWrapper objects.
You can use this to confirm that a memory leak exists.
2010-12-09 19:20:06 -08:00
Roger
7354600849 Fix a socket leak: delete object after close on both direction.
(Note by apenwarr: seems to still work for me.  The reason the
problem occurred is that reassigning 'handlers' doesn't change it in its
parent; it creates a whole new list, and the caller still owns the old one
with all the dead sockets in it.  The problem seems to have been introduced
in commit 84376284db when I factored the
runonce() functionality out of the client and server but didn't notice this
reassignment.)
2010-12-09 19:20:01 -08:00
Avery Pennarun
b219b523c2 socket.SHUT_RD and socket.SHUT_WR don't exist in python 2.3.
Mercifully, socket.socket.shutdown() still does, but it uses hardcoded
integer parameters - and the integers correspond to the SHUT_RD and SHUT_WR
definitions in later versions - so let's just hardcode them ourselves.

See the carnage for yourself:
http://docs.python.org/release/2.3.5/lib/socket-objects.html
2010-10-02 15:24:04 -07:00
Avery Pennarun
76d576a375 _nb_clean: don't catch EPIPE after all.
EPIPE is a serious error from these places, so we have to actually do
something.  Otherwise the client ends up busy waiting when the server
disconnects by surprise.

Bug noticed in a log from Chetan Kunte.
2010-10-01 18:25:03 -07:00
Avery Pennarun
f6e6515a3c Fix busy-waiting in two situations:
- If you tried to connect to a server that didn't exist, then disconnected
  the client during the 60-second connection timeout, the server would
  busy wait for 60 seconds.

- If you connected to a server and then sent data, but then the server
  disconnected before reading all your data, the server would busy wait.
    (example:  yes | telnet servername 80)
2010-10-01 18:22:36 -07:00
Avery Pennarun
84376284db Factor out common mainloop code between client and server.
Also improve the socket message output a bit.
2010-10-01 17:36:09 -07:00
Avery Pennarun
c403a83ab8 Don't use set() since it's not in python 2.3.
Just use a plain list instead.  Technically probably slightly worse
asymptotic behaviour, but it's not like we'll have a million sockets anyway.
2010-10-01 14:38:08 -07:00
Avery Pennarun
7d3028dee2 Remove list comprehensions for python 2.3 compatibility. 2010-10-01 11:55:45 -07:00
Avery Pennarun
4bf4f70c67 ssnet: recover slightly more gracefully from an infinite forwarding loop.
If you 'telnet localhost 12300' weird things happen; someday we should
probably auto-detect and avoid that altogether.  But meanwhile, catch EPIPE
if it happens (it's irrelevant) and don't barf with a %d data type for a
value that can apparently sometimes be None.
2010-10-01 00:05:49 -07:00
Avery Pennarun
33efa5ac62 Added new --auto-hosts and --seed-hosts options to the client.
Now if you use --auto-hosts (-H), the client will ask the server to spawn a
hostwatcher to add names.  That, in turn, will send names back to the
server, which sends them back to the client, which sends them to the
firewall subprocess, which will write them to /etc/hosts.  Whew!

Only the firewall process can write to /etc/hosts, of course, because only
he's running as root.

Since the name discovery process is kind of slow, we cache the names in
~/.sshuttle.hosts on the remote server.

Right now, most of the names are discovered using nmblookup and smbclient,
as well as by reading the existing entries in /etc/hosts.  What would really
be nice would be to query active directory or mdns somehow... but I don't
really know how those work, so this is what you get for now :)  It's pretty
neat, at least.
2010-05-08 03:32:30 -04:00
Avery Pennarun
7043195043 Add -N (--auto-nets) option for auto-discovering subnets.
Now if you do

	./sshuttle -Nr username@myservername

It'll automatically route the "local" subnets (ie., stuff in the routing
table) from myservername.  This is (hopefully a reasonable default setting
for most people.
2010-05-07 20:02:04 -04:00
Avery Pennarun
77935bd110 ssnet: EHOSTUNREACH and ENETUNREACH are non-fatal errors.
Reported by Wayne Scott.
2010-05-07 12:30:03 -04:00
Avery Pennarun
8fe3592be3 Don't require the remote server to have sshuttle installed.
Instead, grab our source code, send it over the link, and have python eval
it and then start the server.py main() function.

Strangely, there's now *less* horrible stuff in ssh.py, because we no longer
have to munge around with the PATH environment variable.  And this
significantly reduces the setup required to get sshuttle going.

Based on a suggestion from Wayne Scott.
2010-05-04 23:42:36 -04:00
Avery Pennarun
096bbcc576 Client "almost" works on MacOS and maybe FreeBSD.
Basic forwarding now works on MacOS, assuming you set up ipfw correctly
(ha ha).  I wasted a few hours today trying to figure this out, and I'm *so
very close*, but unfortunately it just didn't work.  Think you can figure it
out?

Related changes:
- don't die if iptables is unavailable
- BSD uses getsockname() instead of SO_ORIGINAL_DST
- non-blocking connect() returns EISCONN once it's connected
- you can't setsockopt IP_TTL more than once
2010-05-04 22:06:22 -04:00
Avery Pennarun
7d674e9e37 ssnet: throw a nicer-looking Fatal when the mux connection dies.
When it happens, it's probably because the client died and the server hasn't
noticed yet.
2010-05-02 20:53:29 -04:00
Avery Pennarun
ca14231aae Whoops, we were spinning in the server when the mux outbuf was full.
Once again, the buffering gets mixed up with the selecting.  Seems to be the
story of my life.
2010-05-02 06:17:43 -04:00
Avery Pennarun
6c2dc54b9e More latency fixes: use a PING/PONG pair to limit queue length.
It seems ssh is kind of stupid and uses a really big SO_SNDBUF (hundreds of
kbytes).  Thus, we can't depend on the socket's output buffer to limit our
latency down to something reasonable.  Instead, limit the amount of data we
can send in a single round trip.
2010-05-02 05:39:17 -04:00
Avery Pennarun
5d1390927d Don't overfill the mux's output buffer.
Otherwise a single busy stream can ruin it for everybody.
2010-05-02 05:06:51 -04:00
Avery Pennarun
da06286427 ssnet: when a connection error occurs, stop trying to connect. 2010-05-02 03:52:46 -04:00
Avery Pennarun
9b23fd2c01 Do non-blocking connect().
This way we don't freeze the entire proxy when someone tries to connect to a
nonexistent IP address (oops).
2010-05-02 02:43:10 -04:00
Avery Pennarun
2dd328ada4 Add a -v (and -vv) flag and decrease default message verbosity. 2010-05-02 02:14:20 -04:00
Avery Pennarun
10069f99e2 Clean up SockWrapper.peername stuff.
Some fds don't have peernames, and sometimes the peername isn't very
helpful, so let's fill it in by hand when appropriate.
2010-05-02 01:52:05 -04:00
Avery Pennarun
bfd506dcdc Improve some debugging information to find the weird data problem.
Turns out list.pop() removes the *last* item, not the first one.  Oops.  It
all works great for queues of only one item... :)
2010-05-02 01:25:09 -04:00
Avery Pennarun
915a96b0ec We now have a server that works... some of the time.
There still seem to be some weird timing and/or closing-related bugs, since
I can't load the eqldata project correctly unless I use --noserver.
2010-05-02 00:52:06 -04:00
Avery Pennarun
d435c41bdb stdin and stdout have different fds, so make SockWrapper take *two* socks.
We'll need this when we have a SockWrapper pointing at a Mux on a subprocess
pipe.
2010-05-01 23:32:30 -04:00
Avery Pennarun
5f0bfb5d9e Basic implementation of a multiplex protocol - client side only.
Currently the 'server' is just a pipe to run 'hd' (hexdump) for looking at
the client-side results.  Lame, but true.
2010-05-01 23:14:42 -04:00
Avery Pennarun
550048370e Move some code that'll be useful for the server into ssnet.py. 2010-05-01 20:48:11 -04:00