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
Rename --background to -D/--daemon, to match other programs (like smbd).
You can now have --syslog even without --daemon.
Avoid using atexit(); try/finally is better.
Don't just close stderr; we'll end up eating error output from ssh!
Instead, redirect stderr to a 'logger' subprocess that will send to syslog.
Delay redirecting stderr until after we know we're daemonizing, so handy
error messages can go to stderr instead of syslog.
Make pidfile stuff more resilient: support already-existing files, files
with strict permissions, outdated files containing an already-dead pid. Add
a --pidfile option to let you specify the pidfile path.
chdir("/") while daemonizing, so that the filesystem containing $PWD can
later be unmounted without killing the daemon.
fw.done() can't wait on the firewall subprocess on exit when daemonized; we
no longer are the parent of that process.
If hostwatch has a lot of stuff to say all at once, it would come in more
than one recv() packet, and server.py would send each packet individually as
a CMD_HOST_LIST message. Unfortunately, client.py (rightly) expects each
CMD_HOST_LIST message to be complete, ie. a correct sequence of rows.
So now server.py makes sure of this. If there's a leftover bit (ie. an
unterminated line), it saves it for later.
Bug reported by user "Duke" on the mailing list.
Apparently left-shift in python 2.3 just *always* prints a warning, even if
we weren't doing anything wrong. Or maybe it only prints the warning
sometimes. Anyway, let's just multiply by 2**x instead of using <<x, since
we're not performance-sensitive anyway.
That only really stops --auto-nets from working; it's mostly harmless
otherwise. And apparently some locked-down shared hosts don't let you get
the list of routes.
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.
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.
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.
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.