Compare commits

...

28 Commits

Author SHA1 Message Date
57e744dadd ./do: use the latest minimal/do from the redo project. 2011-05-03 14:19:45 -07:00
c13be0b817 ui-macos/bits/runpython.do: auto-determine arches to build for.
Some people don't have all of them installed, so auto-detect them by
looking at the available arches in /usr/libexec.
2011-05-03 14:18:37 -07:00
da2c6273f6 Add some friendly info to the README 2011-05-03 14:03:19 -07:00
7712c60c36 Insert two binary NUL bytes (\0) before SSHUTTLE0001 sync string.
...and search for those null bytes before looking for the sync string.

This helps when people have misconfigured .bashrc to print messages even in
non-interactive mode.  (On my Debian Lenny system, .bashrc doesn't seem to
run when you do 'ssh localhost ls', but on MacOS servers, it does.  Hmm...)
2011-05-03 13:59:25 -07:00
65b0390fe9 ssh.py: use 'exec python -c' instead of just 'python -c'.
This gets rid of an extra intermediate sh process on the server that we were
keeping for no good reason, since it would exit as soon as python exited
anyway.
2011-05-03 13:51:09 -07:00
c5834a9773 Handle EHOSTDOWN, ENETDOWN.
Someone on the mailing list reported getting these.

Also centralize the list of these errors, so we don't have different parts
of the code supporting a different subset of them.  Now just use
ssnet.NET_ERRS.
2011-05-03 13:32:25 -07:00
e2474543fc runpython.do: also compile for ppc architecture. 2011-04-24 22:51:27 -04:00
8636378870 Dereference symlink for sshuttle launch script
(Modified slightly by apenwarr)
2011-04-24 22:42:50 -04:00
f5eed4c809 Don't try to connect to remote IPs that start with zero.
For some reason, on Linux servers this returns EINVAL.  I don't like just
treating EINVAL as non-fatal in general, so let's catch this specific case
and ignore it.

Reported by Reza Mohammadi on the mailing list.  Interestingly, it's kind of
hard to trigger this crash since the client would have to request the
connection, and that connection shouldn't exist because the original client
program would have already gotten EINVAL.  But my MacOS machine can generate
such a connection, so a MacOS->Linux sshuttle could trigger this.
2011-04-24 22:15:20 -04:00
783d33cada DNS: auto-retry if we get an error on send/recv to DNS server.
A few people have reported that they have one or more invalid DNS servers in
/etc/resolv.conf, which they don't notice because the normal resolver
library just skips the broken ones.  sshuttle would abort because it got an
unexpected socket error, which isn't so good.
2011-04-06 12:30:12 -04:00
94241b938b On FreeBSD, avoid a crash caused by buggy socket.connect() in python pre-2.5.
Bug reported by Ed Maste.  The fix in later versions of python is documented
here:
http://mail.python.org/pipermail/python-bugs-list/2006-August/034667.html

We're basically just doing the same thing when we see EINVAL.  Note that
this doesn't happen on Linux because connect() is more forgiving.
2011-03-21 03:15:11 -07:00
9031de1527 repr(socket.error) is useless in some versions of python.
So let's use %s instead of %r to print it, so that log messages can be more
useful.  This only affects one message at debug3 for now, so it's not too
exciting.
2011-03-21 03:15:11 -07:00
cfb2592346 server.py: handle (throw away) ECONNREFUSED from the DNS server.
This might happen occasionally on a flakey network.  Reported by Ed Maste.
2011-03-19 22:48:15 -07:00
2e8381ecda hostwatch.py: avoid using /dev/null on the server.
According to at least one report, there are some slightly insane servers out
there that have /dev/null set to non-user-writable.  This is totally broken,
but we want sshuttle to work with as many servers as possible, so let's fake
it up a bit instead.

We don't try to avoid /dev/null on the client; sshuttle needs root access
anyway, and if you're root, you can just fix your stupid /dev/null
permissions.
2011-03-14 18:57:06 -07:00
7d35690e41 ui-macos/clean: fix a GNUism in usage of the 'find' command. 2011-02-28 02:43:00 -08:00
141d9760b9 all.do: add some hints about how to run sshuttle.
This is mostly so that people know how to find the MacOS GUI app, which was
previously rather non-obvious.
2011-02-26 18:16:44 -08:00
0658c85ffe Replace make-based build with redo-based build.
Including a copy of minimal/do as 'do' in the top directory.  To build, just
run './do' or 'make'.

This also builds the ui-macos directory automatically if you're on MacOS.
2011-02-26 18:16:44 -08:00
90a55a33a2 firewall.py: make it super clear when we apply the MacOS fix.
Print a message to stderr, then abort.  But only the first time.
2011-02-26 17:45:27 -08:00
c3399595d2 README/sshuttle.1: add a note about the MacOS kernel bug.
And its side effects.

Reported by David Held / Antonio d'Souza.
2011-02-26 17:23:11 -08:00
6ef9ae1796 firewall.py: iptables: failure to delete a rule isn't always fatal.
If the previous run of sshuttle didn't manage to clean up after itself, it
might have left the sshuttle-12300 chain intact, but the OUTPUT chain might
not refer to it anymore.  That would cause the *next* run of sshuttle to
barf when trying to delete the OUTPUT entry, and then never get to the part
where it just tries to delete the old chain so it can continue.

Now only the last delete command (the one that actually deletes the chain)
is fatal if it fails; the others just print a scary message, but that should
only happen once in your life if you're unlucky.
2011-02-21 03:04:00 -08:00
1ca8aa5b89 server: workaround for idiotic ArchLinux renaming of python to python2.
First try running under python2, then python if that doesn't exist.
2011-02-07 17:18:30 -08:00
a62975e0ce client: workaround for idiotic ArchLinux renaming of python to python2.
First try running under python2, then python if that doesn't exist.
2011-02-07 00:18:58 -08:00
4fde980f46 firewall.py: MacOS: permanently set the net.inet.ip.scopedroute sysctl.
If this sysctl isn't set to 0 at the time your network interface is brought
up, and we later change it, then the MacOS (10.6.6 at least) ARP table gets
totally confused and networking stops working about 15 minutes later, until
you down and re-up the interface.  The symptom is that pings outside your
LAN would give results like this:

    ping: sendto: no route to host

and "arp -a -n" would show *two* entries for your default gateway instead of
just one.

sshuttle was helpfully putting the sysctl back the way it was when it shuts
down, so you would fix your network by downing the interface, so sshuttle
would abort and change the sysctl back, then you would re-up the interface,
then restart sshuttle, and sshuttle would change the sysctl back and restart
the cycle: it would break again a few minutes later.

That's annoying, and it gives sshuttle a bad reputation for being the thing
that breaks your network.  I can't find a *really* good workaround for the
bug, so barring that, let's just permanently set the sysctl to 0 and not
change it back on exit.  That should just leave your computer back how it
worked in MacOS 10.5, as far as I know, which seems harmless.  At least I've
been running my Mac that way for a few days and I haven't seen any
weirdness.

Now, doing *that* would still mean that the first sshuttle session after a
reboot would still break the network, since sysctl changes are lost on
reboot.  Thus, let's be extra hardcore and write it to /etc/sysctl.conf so
that it goes the way we want it after a reboot.  Thus, sshuttle should break
your network at most once.  Which still sucks, but hopefully nobody will
notice.
2011-02-04 21:55:40 -08:00
621997b279 ui-macos: move the noLatencyControl setting to a per-connection setting.
I think some connections you'll want to optimize for latency, and others for
bandwidth.  Probably.

Also, use a dropdown box instead of a checkbox; that way we can make it more
clear what each of the settings means.

While we're here, adjust all the anchor settings for the different display
items so that resizing the dialog box works sensibly.
2011-02-04 21:40:44 -08:00
ca7d38dc1a stresstest.py: a program to create lots and lots of TCP connections.
This version is a bit limited: it always only connects back to itself, which
is always on 127.0.0.1.  It also doesn't really find any problems, other
than odd behaviour when Linux runs out of available port numbers after a
while.
2011-02-04 21:37:22 -08:00
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
a238f7636c ui-macos: include routing type in each connection title.
This makes it extra clear when a connection is for "all routes" vs. custom
vs. auto.
2011-02-01 03:55:19 -08:00
62e1ac4b46 ui-macos: add checkboxes for --no-latency-control and --dns options. 2011-02-01 03:55:19 -08:00
23 changed files with 915 additions and 163 deletions

3
.gitignore vendored
View File

@ -1,3 +1,6 @@
*.pyc
*~
*.8
/.do_built
/.do_built.dir
/.redo

View File

@ -1,19 +1,10 @@
PANDOC:=$(shell \
if pandoc </dev/null 2>/dev/null; then \
echo pandoc; \
else \
echo "Warning: pandoc not installed; can't generate manpages." >&2; \
echo '@echo Skipping: pandoc'; \
fi)
all:
default: all
Makefile:
@
all: sshuttle.8
%: FORCE
+./do $@
sshuttle.8: sshuttle.md
.PHONY: FORCE
%.8: %.md
$(PANDOC) -s -r markdown -w man -o $@ $<
clean:
rm -f *~ */*~ .*~ */.*~ *.8 *.tmp */*.tmp *.pyc */*.pyc

View File

@ -1,3 +1,14 @@
WARNING:
On MacOS 10.6 (at least up to 10.6.6), your network will
stop responding about 10 minutes after the first time you
start sshuttle, because of a MacOS kernel bug relating to
arp and the net.inet.ip.scopedroute sysctl. To fix it,
just switch your wireless off and on. Sshuttle makes the
kernel setting it changes permanent, so this won't happen
again, even after a reboot.
sshuttle: where transparent proxy meets VPN meets ssh
=====================================================
@ -52,7 +63,19 @@ This is how you use it:
on your client machine. You'll need root or sudo
access, and python needs to be installed.
- <tt>./sshuttle -r username@sshserver 0.0.0.0/0 -vv</tt>
- The most basic use of sshuttle looks like:
<tt>./sshuttle -r username@sshserver 0.0.0.0/0 -vv</tt>
- There is a shortcut for 0.0.0.0/0 for those that value
their wrists
<tt>./sshuttle -r username@sshserver 0/0 -vv</tt>
- If you would also like your DNS queries to be proxied
through the DNS server of the server you are connect to:
<tt>./sshuttle --dns -rvv username@sshserver 0/0</tt>
The above is probably what you want to use to prevent
local network attacks such as Firesheep and friends.
(You may be prompted for one or more passwords; first, the
local password to become root using either sudo or su, and

11
all.do Normal file
View File

@ -0,0 +1,11 @@
exec >&2
UI=
[ "$(uname)" = "Darwin" ] && UI=ui-macos/all
redo-ifchange sshuttle.8 $UI
echo
echo "What now?"
[ -z "$UI" ] || echo "- Try the MacOS GUI: open ui-macos/Sshuttle*.app"
echo "- Run sshuttle: ./sshuttle --dns -r HOSTNAME 0/0"
echo "- Read the README: less README.md"
echo "- Read the man page: less sshuttle.md"

2
clean.do Normal file
View File

@ -0,0 +1,2 @@
redo ui-macos/clean
rm -f *~ */*~ .*~ */.*~ *.8 *.tmp */*.tmp *.pyc */*.pyc

View File

@ -102,7 +102,7 @@ class FirewallClient:
self.subnets_include = subnets_include
self.subnets_exclude = subnets_exclude
self.dnsport = dnsport
argvbase = ([sys.argv[0]] +
argvbase = ([sys.argv[1], sys.argv[0], sys.argv[1]] +
['-v'] * (helpers.verbose or 0) +
['--firewall', str(port), str(dnsport)])
if ssyslog._p:
@ -198,7 +198,14 @@ def _main(listener, fw, ssh_cmd, remotename, python, latency_control,
handlers.append(mux)
expected = 'SSHUTTLE0001'
try:
v = 'x'
while v and v != '\0':
v = serversock.recv(1)
v = 'x'
while v and v != '\0':
v = serversock.recv(1)
initstring = serversock.recv(len(expected))
except socket.error, e:
if e.args[0] == errno.ECONNRESET:
@ -273,6 +280,10 @@ def _main(listener, fw, ssh_cmd, remotename, python, latency_control,
sock.close()
return
chan = mux.next_channel()
if not chan:
log('warning: too many open channels. Discarded connection.\n')
sock.close()
return
mux.send(chan, ssnet.CMD_CONNECT, '%s,%s' % dstip)
outwrap = MuxWrapper(mux, chan)
handlers.append(Proxy(SockWrapper(sock, sock), outwrap))

7
default.8.do Normal file
View File

@ -0,0 +1,7 @@
exec >&2
if pandoc </dev/null 2>/dev/null; then
pandoc -s -r markdown -w man -o $3 $1.md
else
echo "Warning: pandoc not installed; can't generate manpages."
redo-always
fi

175
do Executable file
View File

@ -0,0 +1,175 @@
#!/bin/sh
#
# A minimal alternative to djb redo that doesn't support incremental builds.
# For the full version, visit http://github.com/apenwarr/redo
#
# The author disclaims copyright to this source file and hereby places it in
# the public domain. (2010 12 14)
#
# By default, no output coloring.
green=""
bold=""
plain=""
if [ -n "$TERM" -a "$TERM" != "dumb" ] && tty <&2 >/dev/null 2>&1; then
green="$(printf '\033[32m')"
bold="$(printf '\033[1m')"
plain="$(printf '\033[m')"
fi
_dirsplit()
{
base=${1##*/}
dir=${1%$base}
}
dirname()
(
_dirsplit "$1"
dir=${dir%/}
echo "${dir:-.}"
)
_dirsplit "$0"
export REDO=$(cd "${dir:-.}" && echo "$PWD/$base")
DO_TOP=
if [ -z "$DO_BUILT" ]; then
DO_TOP=1
[ -n "$*" ] || set all # only toplevel redo has a default target
export DO_BUILT=$PWD/.do_built
: >>"$DO_BUILT"
echo "Removing previously built files..." >&2
sort -u "$DO_BUILT" | tee "$DO_BUILT.new" |
while read f; do printf "%s\0%s.did\0" "$f" "$f"; done |
xargs -0 rm -f 2>/dev/null
mv "$DO_BUILT.new" "$DO_BUILT"
DO_PATH=$DO_BUILT.dir
export PATH=$DO_PATH:$PATH
rm -rf "$DO_PATH"
mkdir "$DO_PATH"
for d in redo redo-ifchange; do
ln -s "$REDO" "$DO_PATH/$d";
done
[ -e /bin/true ] && TRUE=/bin/true || TRUE=/usr/bin/true
for d in redo-ifcreate redo-stamp redo-always; do
ln -s $TRUE "$DO_PATH/$d";
done
fi
_find_dofile_pwd()
{
dofile=default.$1.do
while :; do
dofile=default.${dofile#default.*.}
[ -e "$dofile" -o "$dofile" = default.do ] && break
done
ext=${dofile#default}
ext=${ext%.do}
base=${1%$ext}
}
_find_dofile()
{
local prefix=
while :; do
_find_dofile_pwd "$1"
[ -e "$dofile" ] && break
[ "$PWD" = "/" ] && break
target=${PWD##*/}/$target
tmp=${PWD##*/}/$tmp
prefix=${PWD##*/}/$prefix
cd ..
done
base=$prefix$base
}
_run_dofile()
{
export DO_DEPTH="$DO_DEPTH "
export REDO_TARGET=$PWD/$target
local line1
set -e
read line1 <"$PWD/$dofile"
cmd=${line1#"#!/"}
if [ "$cmd" != "$line1" ]; then
/$cmd "$PWD/$dofile" "$@" >"$tmp.tmp2"
else
:; . "$PWD/$dofile" >"$tmp.tmp2"
fi
}
_do()
{
local dir=$1 target=$2 tmp=$3
if [ ! -e "$target" ] || [ -d "$target" -a ! -e "$target.did" ]; then
printf '%sdo %s%s%s%s\n' \
"$green" "$DO_DEPTH" "$bold" "$dir$target" "$plain" >&2
echo "$PWD/$target" >>"$DO_BUILT"
dofile=$target.do
base=$target
ext=
[ -e "$target.do" ] || _find_dofile "$target"
if [ ! -e "$dofile" ]; then
echo "do: $target: no .do file" >&2
return 1
fi
[ ! -e "$DO_BUILT" ] || [ ! -d "$(dirname "$target")" ] ||
: >>"$target.did"
( _run_dofile "$base" "$ext" "$tmp.tmp" )
rv=$?
if [ $rv != 0 ]; then
printf "do: %s%s\n" "$DO_DEPTH" \
"$dir$target: got exit code $rv" >&2
rm -f "$tmp.tmp" "$tmp.tmp2"
return $rv
fi
mv "$tmp.tmp" "$target" 2>/dev/null ||
! test -s "$tmp.tmp2" ||
mv "$tmp.tmp2" "$target" 2>/dev/null
rm -f "$tmp.tmp2"
else
echo "do $DO_DEPTH$target exists." >&2
fi
}
# Make corrections for directories that don't actually exist yet.
_dir_shovel()
{
local dir base
xdir=$1 xbase=$2 xbasetmp=$2
while [ ! -d "$xdir" -a -n "$xdir" ]; do
_dirsplit "${xdir%/}"
xbasetmp=${base}__$xbase
xdir=$dir xbase=$base/$xbase
echo "xbasetmp='$xbasetmp'" >&2
done
}
redo()
{
for i in "$@"; do
_dirsplit "$i"
_dir_shovel "$dir" "$base"
dir=$xdir base=$xbase basetmp=$xbasetmp
( cd "$dir" && _do "$dir" "$base" "$basetmp" ) || return 1
done
}
set -e
redo "$@"
if [ -n "$DO_TOP" ]; then
echo "Removing stamp files..." >&2
[ ! -e "$DO_BUILT" ] ||
while read f; do printf "%s.did\0" "$f"; done <"$DO_BUILT" |
xargs -0 rm -f 2>/dev/null
fi

View File

@ -7,6 +7,13 @@ from helpers import *
IPPROTO_DIVERT = 254
def nonfatal(func, *args):
try:
func(*args)
except Fatal, e:
log('error: %s\n' % e)
def ipt_chain_exists(name):
argv = ['iptables', '-t', 'nat', '-nL']
p = ssubprocess.Popen(argv, stdout = ssubprocess.PIPE)
@ -57,9 +64,9 @@ def do_iptables(port, dnsport, subnets):
# basic cleanup/setup of chains
if ipt_chain_exists(chain):
ipt('-D', 'OUTPUT', '-j', chain)
ipt('-D', 'PREROUTING', '-j', chain)
ipt('-F', chain)
nonfatal(ipt, '-D', 'OUTPUT', '-j', chain)
nonfatal(ipt, '-D', 'PREROUTING', '-j', chain)
nonfatal(ipt, '-F', chain)
ipt('-X', chain)
if subnets or dnsport:
@ -131,11 +138,11 @@ def _fill_oldctls(prefix):
def _sysctl_set(name, val):
argv = ['sysctl', '-w', '%s=%s' % (name, val)]
debug1('>> %s\n' % ' '.join(argv))
rv = ssubprocess.call(argv, stdout = open('/dev/null', 'w'))
return ssubprocess.call(argv, stdout = open('/dev/null', 'w'))
_changedctls = []
def sysctl_set(name, val):
def sysctl_set(name, val, permanent=False):
PREFIX = 'net.inet.ip'
assert(name.startswith(PREFIX + '.'))
val = str(val)
@ -143,11 +150,20 @@ def sysctl_set(name, val):
_fill_oldctls(PREFIX)
if not (name in _oldctls):
debug1('>> No such sysctl: %r\n' % name)
return
return False
oldval = _oldctls[name]
if val != oldval:
rv = _sysctl_set(name, val)
if rv==0 and permanent:
debug1('>> ...saving permanently in /etc/sysctl.conf\n')
f = open('/etc/sysctl.conf', 'a')
f.write('\n'
'# Added by sshuttle\n'
'%s=%s\n' % (name, val))
f.close()
else:
_changedctls.append(name)
return _sysctl_set(name, val)
return True
def _udp_unpack(p):
@ -206,7 +222,18 @@ def do_ipfw(port, dnsport, subnets):
if subnets or dnsport:
sysctl_set('net.inet.ip.fw.enable', 1)
sysctl_set('net.inet.ip.scopedroute', 0)
changed = sysctl_set('net.inet.ip.scopedroute', 0, permanent=True)
if changed:
log("\n"
" WARNING: ONE-TIME NETWORK DISRUPTION:\n"
" =====================================\n"
"sshuttle has changed a MacOS kernel setting to work around\n"
"a bug in MacOS 10.6. This will cause your network to drop\n"
"within 5-10 minutes unless you restart your network\n"
"interface (change wireless networks or unplug/plug the\n"
"ethernet port) NOW, then restart sshuttle. The fix is\n"
"permanent; you only have to do this once.\n\n")
sys.exit(1)
ipfw('add', sport, 'check-state', 'ip',
'from', 'any', 'to', 'any')

View File

@ -13,7 +13,11 @@ _nmb_ok = True
_smb_ok = True
hostnames = {}
queue = {}
null = open('/dev/null', 'rb+')
try:
null = open('/dev/null', 'wb')
except IOError, e:
log('warning: %s\n' % e)
null = os.popen("sh -c 'while read x; do :; done'", 'wb', 4096)
def _is_ip(s):

9
main.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python
import sys, os, re
import helpers, options, client, server, firewall, hostwatch
import compat.ssubprocess as ssubprocess
@ -55,13 +54,14 @@ l,listen= transproxy to this ip address and port number [127.0.0.1:0]
H,auto-hosts scan for remote hostnames and update local /etc/hosts
N,auto-nets automatically determine subnets to route
dns capture local DNS requests and forward to the remote DNS server
python= path to python interpreter on the remote server [python]
python= path to python interpreter on the remote server
r,remote= ssh hostname (and optional username) of remote sshuttle server
x,exclude= exclude this subnet (can be used more than once)
v,verbose increase debug message verbosity
e,ssh-cmd= the command to use to connect to the remote [ssh]
seed-hosts= with -H, use these hostnames for initial scan (comma-separated)
no-latency-control sacrifice latency to improve bandwidth benchmarks
wrap= restart counting channel numbers after this number (for testing)
D,daemon run in the background as a daemon
syslog send log messages to syslog (default if you use --daemon)
pidfile= pidfile name (only if using --daemon) [./sshuttle.pid]
@ -70,10 +70,13 @@ firewall (internal use only)
hostwatch (internal use only)
"""
o = options.Options(optspec)
(opt, flags, extra) = o.parse(sys.argv[1:])
(opt, flags, extra) = o.parse(sys.argv[2:])
if opt.daemon:
opt.syslog = 1
if opt.wrap:
import ssnet
ssnet.MAX_CHANNEL = int(opt.wrap)
helpers.verbose = opt.verbose
try:

View File

@ -110,16 +110,51 @@ class DnsProxy(Handler):
def __init__(self, mux, chan, request):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
Handler.__init__(self, [sock])
self.sock = sock
self.timeout = time.time()+30
self.mux = mux
self.chan = chan
self.tries = 0
self.peer = None
self.request = request
self.sock = sock
self.sock.setsockopt(socket.SOL_IP, socket.IP_TTL, 42)
self.sock.connect((resolvconf_random_nameserver(), 53))
self.sock.send(request)
self.try_send()
def try_send(self):
if self.tries >= 3:
return
self.tries += 1
self.peer = resolvconf_random_nameserver()
self.sock.connect((self.peer, 53))
debug2('DNS: sending to %r\n' % self.peer)
try:
self.sock.send(self.request)
except socket.error, e:
if e.args[0] in ssnet.NET_ERRS:
# might have been spurious; try again.
# Note: these errors sometimes are reported by recv(),
# and sometimes by send(). We have to catch both.
debug2('DNS send to %r: %s\n' % (self.peer, e))
self.try_send()
return
else:
log('DNS send to %r: %s\n' % (self.peer, e))
return
def callback(self):
try:
data = self.sock.recv(4096)
except socket.error, e:
if e.args[0] in ssnet.NET_ERRS:
# might have been spurious; try again.
# Note: these errors sometimes are reported by recv(),
# and sometimes by send(). We have to catch both.
debug2('DNS recv from %r: %s\n' % (self.peer, e))
self.try_send()
return
else:
log('DNS recv from %r: %s\n' % (self.peer, e))
return
debug2('DNS response: %d bytes\n' % len(data))
self.mux.send(self.chan, ssnet.CMD_DNS_RESPONSE, data)
self.ok = False
@ -138,7 +173,7 @@ def main():
debug1(' %s/%d\n' % r)
# synchronization header
sys.stdout.write('SSHUTTLE0001')
sys.stdout.write('\0\0SSHUTTLE0001')
sys.stdout.flush()
handlers = []

11
ssh.py
View File

@ -73,16 +73,23 @@ def connect(ssh_cmd, rhostport, python, stderr, options):
if not rhost:
argv = [python, '-c', pyscript]
# ignore the --python argument when running locally; we already know
# which python version works.
argv = [sys.argv[1], '-c', pyscript]
else:
if ssh_cmd:
sshl = ssh_cmd.split(' ')
else:
sshl = ['ssh']
if python:
pycmd = "'%s' -c '%s'" % (python, pyscript)
else:
pycmd = ("P=python2; $P -V 2>/dev/null || P=python; "
"exec \"$P\" -c '%s'") % pyscript
argv = (sshl +
portl +
ipv6flag +
[rhost, '--', "'%s' -c '%s'" % (python, pyscript)])
[rhost, '--', pycmd])
(s1,s2) = socket.socketpair()
def setup():
# runs in the child process

View File

@ -1 +0,0 @@
main.py

12
sshuttle Executable file
View File

@ -0,0 +1,12 @@
#!/bin/sh
EXE=$0
for i in 1 2 3 4 5 6 7 8 9 10; do
[ -L "$EXE" ] || break
EXE=$(readlink "$EXE")
done
DIR=$(dirname "$EXE")
if python2 -V 2>/dev/null; then
exec python2 "$DIR/main.py" python2 "$@"
else
exec python "$DIR/main.py" python "$@"
fi

View File

@ -253,6 +253,17 @@ between the two separate streams, so a tcp-based tunnel is
fine.
# BUGS
On MacOS 10.6 (at least up to 10.6.6), your network will
stop responding about 10 minutes after the first time you
start sshuttle, because of a MacOS kernel bug relating to
arp and the net.inet.ip.scopedroute sysctl. To fix it,
just switch your wireless off and on. Sshuttle makes the
kernel setting it changes permanent, so this won't happen
again, even after a reboot.
# SEE ALSO
`ssh`(1), `python`(1)

View File

@ -2,6 +2,8 @@ import struct, socket, errno, select
if not globals().get('skip_imports'):
from helpers import *
MAX_CHANNEL = 65535
# these don't exist in the socket module in python 2.3!
SHUT_RD = 0
SHUT_WR = 1
@ -40,6 +42,10 @@ cmd_to_name = {
}
NET_ERRS = [errno.ECONNREFUSED, errno.ETIMEDOUT,
errno.EHOSTUNREACH, errno.ENETUNREACH,
errno.EHOSTDOWN, errno.ENETDOWN]
def _add(l, elem):
if not elem in l:
@ -84,7 +90,7 @@ class SockWrapper:
def __init__(self, rsock, wsock, connect_to=None, peername=None):
global _swcount
_swcount += 1
debug3('creating new SockWrapper (%d now exist\n)' % _swcount)
debug3('creating new SockWrapper (%d now exist)\n' % _swcount)
self.exc = None
self.rsock = rsock
self.wsock = wsock
@ -99,7 +105,7 @@ class SockWrapper:
_swcount -= 1
debug1('%r: deleting (%d remain)\n' % (self, _swcount))
if self.exc:
debug1('%r: error was: %r\n' % (self, self.exc))
debug1('%r: error was: %s\n' % (self, self.exc))
def __repr__(self):
if self.rsock == self.wsock:
@ -122,20 +128,34 @@ class SockWrapper:
return # already connected
self.rsock.setblocking(False)
debug3('%r: trying connect to %r\n' % (self, self.connect_to))
if socket.inet_aton(self.connect_to[0])[0] == '\0':
self.seterr(Exception("Can't connect to %r: "
"IP address starts with zero\n"
% (self.connect_to,)))
self.connect_to = None
return
try:
self.rsock.connect(self.connect_to)
# connected successfully (Linux)
self.connect_to = None
except socket.error, e:
debug3('%r: connect result: %r\n' % (self, e))
debug3('%r: connect result: %s\n' % (self, e))
if e.args[0] == errno.EINVAL:
# this is what happens when you call connect() on a socket
# that is now connected but returned EINPROGRESS last time,
# on BSD, on python pre-2.5.1. We need to use getsockopt()
# to get the "real" error. Later pythons do this
# automatically, so this code won't run.
realerr = self.rsock.getsockopt(socket.SOL_SOCKET,
socket.SO_ERROR)
e = socket.error(realerr, os.strerror(realerr))
debug3('%r: fixed connect result: %s\n' % (self, e))
if e.args[0] in [errno.EINPROGRESS, errno.EALREADY]:
pass # not connected yet
elif e.args[0] == errno.EISCONN:
# connected successfully (BSD)
self.connect_to = None
elif e.args[0] in [errno.ECONNREFUSED, errno.ETIMEDOUT,
errno.EHOSTUNREACH, errno.ENETUNREACH,
errno.EACCES, errno.EPERM]:
elif e.args[0] in NET_ERRS + [errno.EACCES, errno.EPERM]:
# a "normal" kind of error
self.connect_to = None
self.seterr(e)
@ -300,7 +320,7 @@ class Mux(Handler):
# channel 0 is special, so we never allocate it
for timeout in xrange(1024):
self.chani += 1
if self.chani > 65535:
if self.chani > MAX_CHANNEL:
self.chani = 1
if not self.channels.get(self.chani):
return self.chani

86
stresstest.py Executable file
View File

@ -0,0 +1,86 @@
#!/usr/bin/env python
import sys, os, socket, select, struct, time
listener = socket.socket()
listener.bind(('127.0.0.1', 0))
listener.listen(500)
servers = []
clients = []
remain = {}
NUMCLIENTS = 50
count = 0
while 1:
if len(clients) < NUMCLIENTS:
c = socket.socket()
c.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
c.bind(('0.0.0.0', 0))
c.connect(listener.getsockname())
count += 1
if count >= 16384:
count = 1
print 'cli CREATING %d' % count
b = struct.pack('I', count) + 'x'*count
remain[c] = count
print 'cli >> %r' % len(b)
c.send(b)
c.shutdown(socket.SHUT_WR)
clients.append(c)
r = [listener]
time.sleep(0.1)
else:
r = [listener]+servers+clients
print 'select(%d)' % len(r)
r,w,x = select.select(r, [], [], 5)
assert(r)
for i in r:
if i == listener:
s,addr = listener.accept()
servers.append(s)
elif i in servers:
b = i.recv(4096)
print 'srv << %r' % len(b)
if not i in remain:
assert(len(b) >= 4)
want = struct.unpack('I', b[:4])[0]
b = b[4:]
#i.send('y'*want)
else:
want = remain[i]
if want < len(b):
print 'weird wanted %d bytes, got %d: %r' % (want, len(b), b)
assert(want >= len(b))
want -= len(b)
remain[i] = want
if not b: # EOF
if want:
print 'weird: eof but wanted %d more' % want
assert(want == 0)
i.close()
servers.remove(i)
del remain[i]
else:
print 'srv >> %r' % len(b)
i.send('y'*len(b))
if not want:
i.shutdown(socket.SHUT_WR)
elif i in clients:
b = i.recv(4096)
print 'cli << %r' % len(b)
want = remain[i]
if want < len(b):
print 'weird wanted %d bytes, got %d: %r' % (want, len(b), b)
assert(want >= len(b))
want -= len(b)
remain[i] = want
if not b: # EOF
if want:
print 'weird: eof but wanted %d more' % want
assert(want == 0)
i.close()
clients.remove(i)
del remain[i]
listener.accept()

View File

@ -2,17 +2,17 @@
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
<data>
<int key="IBDocument.SystemTarget">1060</int>
<string key="IBDocument.SystemVersion">10H574</string>
<string key="IBDocument.SystemVersion">10J567</string>
<string key="IBDocument.InterfaceBuilderVersion">762</string>
<string key="IBDocument.AppKitVersion">1038.35</string>
<string key="IBDocument.HIToolboxVersion">461.00</string>
<string key="IBDocument.HIToolboxVersion">462.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">762</string>
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
<integer value="233"/>
<integer value="237"/>
</object>
<object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
@ -41,9 +41,9 @@
<string key="NSClassName">NSApplication</string>
</object>
<object class="NSWindowTemplate" id="411825121">
<int key="NSWindowStyleMask">3</int>
<int key="NSWindowStyleMask">11</int>
<int key="NSWindowBacking">2</int>
<string key="NSWindowRect">{{157, 116}, {611, 369}}</string>
<string key="NSWindowRect">{{324, 171}, {611, 469}}</string>
<int key="NSWTFlags">1886913536</int>
<string key="NSWindowTitle">Sshuttle VPN Preferences</string>
<string key="NSWindowClass">NSWindow</string>
@ -51,16 +51,16 @@
<characters key="NS.bytes">View</characters>
</object>
<string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string>
<string key="NSWindowContentMinSize">{213, 107}</string>
<string key="NSWindowContentMinSize">{611, 469}</string>
<object class="NSView" key="NSWindowView" id="174067038">
<reference key="NSNextResponder"/>
<int key="NSvFlags">256</int>
<int key="NSvFlags">274</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSTabView" id="389252804">
<reference key="NSNextResponder" ref="174067038"/>
<int key="NSvFlags">12</int>
<string key="NSFrame">{{-8, -10}, {627, 373}}</string>
<int key="NSvFlags">18</int>
<string key="NSFrame">{{-8, -10}, {627, 473}}</string>
<reference key="NSSuperview" ref="174067038"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<object class="NSMutableArray" key="NSTabViewItems">
@ -68,13 +68,13 @@
<object class="NSTabViewItem" id="762265164">
<string key="NSIdentifier">1</string>
<object class="NSView" key="NSView" id="60314308">
<nil key="NSNextResponder"/>
<int key="NSvFlags">256</int>
<reference key="NSNextResponder" ref="389252804"/>
<int key="NSvFlags">274</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSButton" id="26015719">
<reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{17, 17}, {25, 23}}</string>
<reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -103,7 +103,7 @@
</object>
<object class="NSButton" id="244571541">
<reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{41, 17}, {25, 23}}</string>
<reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -128,7 +128,7 @@
</object>
<object class="NSScrollView" id="776974664">
<reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int>
<int key="NSvFlags">274</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSClipView" id="8658574">
@ -139,7 +139,7 @@
<object class="NSTableView" id="849333466">
<reference key="NSNextResponder" ref="8658574"/>
<int key="NSvFlags">256</int>
<string key="NSFrameSize">{224, 282}</string>
<string key="NSFrameSize">{224, 372}</string>
<reference key="NSSuperview" ref="8658574"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
@ -275,7 +275,7 @@
<int key="NSTableViewDraggingDestinationStyle">0</int>
</object>
</object>
<string key="NSFrame">{{1, 1}, {223, 282}}</string>
<string key="NSFrame">{{1, 1}, {223, 372}}</string>
<reference key="NSSuperview" ref="776974664"/>
<reference key="NSNextKeyView" ref="849333466"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -306,7 +306,7 @@
<double key="NSPercent">0.91812865497076024</double>
</object>
</object>
<string key="NSFrame">{{17, 40}, {225, 284}}</string>
<string key="NSFrame">{{17, 40}, {225, 374}}</string>
<reference key="NSSuperview" ref="60314308"/>
<reference key="NSNextKeyView" ref="8658574"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -318,8 +318,8 @@
</object>
<object class="NSButton" id="538356055">
<reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{296, 254}, {273, 18}}</string>
<int key="NSvFlags">265</int>
<string key="NSFrame">{{291, 356}, {273, 18}}</string>
<reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
@ -341,8 +341,8 @@
</object>
<object class="NSTextField" id="889877302">
<reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{341, 292}, {249, 22}}</string>
<int key="NSvFlags">265</int>
<string key="NSFrame">{{341, 392}, {249, 22}}</string>
<reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
@ -369,8 +369,8 @@
</object>
<object class="NSPopUpButton" id="801412726">
<reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{273, 185}, {320, 26}}</string>
<int key="NSvFlags">265</int>
<string key="NSFrame">{{273, 193}, {320, 26}}</string>
<reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
@ -440,10 +440,77 @@
<int key="NSArrowPosition">2</int>
</object>
</object>
<object class="NSPopUpButton" id="451647466">
<reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">265</int>
<string key="NSFrame">{{273, 257}, {320, 26}}</string>
<reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSPopUpButtonCell" key="NSCell" id="970826243">
<int key="NSCellFlags">-2076049856</int>
<int key="NSCellFlags2">2048</int>
<reference key="NSSupport" ref="696441443"/>
<reference key="NSControlView" ref="451647466"/>
<int key="NSButtonFlags">112869631</int>
<int key="NSButtonFlags2">129</int>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
<int key="NSPeriodicDelay">400</int>
<int key="NSPeriodicInterval">75</int>
<object class="NSMenuItem" key="NSMenuItem" id="903120255">
<reference key="NSMenu" ref="790880658"/>
<string key="NSTitle">Choose one</string>
<string key="NSKeyEquiv"/>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<int key="NSState">1</int>
<reference key="NSOnImage" ref="615977438"/>
<reference key="NSMixedImage" ref="445532764"/>
<string key="NSAction">_popUpItemAction:</string>
<reference key="NSTarget" ref="970826243"/>
</object>
<bool key="NSMenuItemRespectAlignment">YES</bool>
<object class="NSMenu" key="NSMenu" id="790880658">
<string key="NSTitle">OtherViews</string>
<object class="NSMutableArray" key="NSMenuItems">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="903120255"/>
<object class="NSMenuItem" id="778262848">
<reference key="NSMenu" ref="790880658"/>
<string key="NSTitle">Item 2</string>
<string key="NSKeyEquiv"/>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="615977438"/>
<reference key="NSMixedImage" ref="445532764"/>
<string key="NSAction">_popUpItemAction:</string>
<reference key="NSTarget" ref="970826243"/>
</object>
<object class="NSMenuItem" id="195135854">
<reference key="NSMenu" ref="790880658"/>
<string key="NSTitle">Item 3</string>
<string key="NSKeyEquiv"/>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="615977438"/>
<reference key="NSMixedImage" ref="445532764"/>
<string key="NSAction">_popUpItemAction:</string>
<reference key="NSTarget" ref="970826243"/>
</object>
</object>
<reference key="NSMenuFont" ref="696441443"/>
</object>
<int key="NSPreferredEdge">1</int>
<bool key="NSUsesItemFromMenu">YES</bool>
<bool key="NSAltersState">YES</bool>
<int key="NSArrowPosition">2</int>
</object>
</object>
<object class="NSTextField" id="753545988">
<reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{261, 294}, {75, 17}}</string>
<int key="NSvFlags">265</int>
<string key="NSFrame">{{261, 394}, {75, 17}}</string>
<reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
@ -459,8 +526,8 @@
</object>
<object class="NSTextField" id="840157770">
<reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{261, 217}, {105, 17}}</string>
<int key="NSvFlags">265</int>
<string key="NSFrame">{{261, 226}, {105, 17}}</string>
<reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
@ -474,9 +541,26 @@
<reference key="NSTextColor" ref="399750419"/>
</object>
</object>
<object class="NSTextField" id="459566505">
<reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">265</int>
<string key="NSFrame">{{261, 290}, {105, 17}}</string>
<reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="534245320">
<int key="NSCellFlags">68288064</int>
<int key="NSCellFlags2">272630784</int>
<string key="NSContents">Optimize for:</string>
<reference key="NSSupport" ref="696441443"/>
<reference key="NSControlView" ref="459566505"/>
<reference key="NSBackgroundColor" ref="965844506"/>
<reference key="NSTextColor" ref="399750419"/>
</object>
</object>
<object class="NSButton" id="962924480">
<reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int>
<int key="NSvFlags">289</int>
<string key="NSFrame">{{276, 40}, {25, 23}}</string>
<reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -498,7 +582,7 @@
</object>
<object class="NSButton" id="705215911">
<reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int>
<int key="NSvFlags">289</int>
<string key="NSFrame">{{300, 40}, {25, 23}}</string>
<reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -520,7 +604,7 @@
</object>
<object class="NSScrollView" id="610703353">
<reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int>
<int key="NSvFlags">273</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSClipView" id="844110079">
@ -531,7 +615,7 @@
<object class="NSTableView" id="714838401">
<reference key="NSNextResponder" ref="844110079"/>
<int key="NSvFlags">256</int>
<string key="NSFrameSize">{312, 95}</string>
<string key="NSFrameSize">{312, 102}</string>
<reference key="NSSuperview" ref="844110079"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
@ -623,7 +707,7 @@
<int key="NSTableViewDraggingDestinationStyle">0</int>
</object>
</object>
<string key="NSFrame">{{1, 17}, {312, 95}}</string>
<string key="NSFrame">{{1, 17}, {312, 102}}</string>
<reference key="NSSuperview" ref="610703353"/>
<reference key="NSNextKeyView" ref="714838401"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -639,7 +723,7 @@
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<reference key="NSTarget" ref="610703353"/>
<string key="NSAction">_doScroller:</string>
<double key="NSPercent">0.8529411764705882</double>
<double key="NSPercent">0.96938775510204078</double>
</object>
<object class="NSScroller" id="522064761">
<reference key="NSNextResponder" ref="610703353"/>
@ -669,7 +753,7 @@
</object>
<reference ref="188199142"/>
</object>
<string key="NSFrame">{{276, 63}, {314, 113}}</string>
<string key="NSFrame">{{276, 63}, {314, 120}}</string>
<reference key="NSSuperview" ref="60314308"/>
<reference key="NSNextKeyView" ref="844110079"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -681,8 +765,32 @@
<reference key="NSCornerView" ref="188199142"/>
<bytes key="NSScrollAmts">QSAAAEEgAABBmAAAQZgAAA</bytes>
</object>
<object class="NSButton" id="160987209">
<reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">265</int>
<string key="NSFrame">{{291, 323}, {285, 18}}</string>
<reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="565787077">
<int key="NSCellFlags">-2080244224</int>
<int key="NSCellFlags2">0</int>
<string key="NSContents">Send DNS requests through this server</string>
<reference key="NSSupport" ref="696441443"/>
<reference key="NSControlView" ref="160987209"/>
<int key="NSButtonFlags">1211912703</int>
<int key="NSButtonFlags2">2</int>
<reference key="NSNormalImage" ref="581816235"/>
<reference key="NSAlternateImage" ref="753862261"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
<int key="NSPeriodicDelay">200</int>
<int key="NSPeriodicInterval">25</int>
</object>
<string key="NSFrame">{{10, 33}, {607, 327}}</string>
</object>
</object>
<string key="NSFrame">{{10, 33}, {607, 427}}</string>
<reference key="NSSuperview" ref="389252804"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
</object>
<string key="NSLabel">SSH Servers</string>
@ -692,14 +800,14 @@
<object class="NSTabViewItem" id="740075218">
<string key="NSIdentifier">2</string>
<object class="NSView" key="NSView" id="187214803">
<reference key="NSNextResponder" ref="389252804"/>
<int key="NSvFlags">256</int>
<nil key="NSNextResponder"/>
<int key="NSvFlags">274</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSButton" id="625816566">
<reference key="NSNextResponder" ref="187214803"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{189, 287}, {177, 29}}</string>
<int key="NSvFlags">269</int>
<string key="NSFrame">{{195, 374}, {236, 29}}</string>
<reference key="NSSuperview" ref="187214803"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
@ -721,8 +829,8 @@
</object>
<object class="NSButton" id="633518934">
<reference key="NSNextResponder" ref="187214803"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{189, 256}, {270, 29}}</string>
<int key="NSvFlags">269</int>
<string key="NSFrame">{{195, 343}, {236, 29}}</string>
<reference key="NSSuperview" ref="187214803"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
@ -744,15 +852,15 @@
</object>
<object class="NSButton" id="625121428">
<reference key="NSNextResponder" ref="187214803"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{189, 225}, {270, 29}}</string>
<int key="NSvFlags">269</int>
<string key="NSFrame">{{195, 312}, {236, 29}}</string>
<reference key="NSSuperview" ref="187214803"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="132399775">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">0</int>
<string key="NSContents">Send debug information to log</string>
<string key="NSContents">Enable debug messages</string>
<reference key="NSSupport" ref="696441443"/>
<reference key="NSControlView" ref="625121428"/>
<int key="NSButtonFlags">1211912703</int>
@ -766,8 +874,7 @@
</object>
</object>
</object>
<string key="NSFrame">{{10, 33}, {607, 327}}</string>
<reference key="NSSuperview" ref="389252804"/>
<string key="NSFrame">{{10, 33}, {607, 427}}</string>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
</object>
<string key="NSLabel">Options</string>
@ -783,7 +890,7 @@
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSScrollView" id="486362220">
<reference key="NSNextResponder" ref="311013698"/>
<int key="NSvFlags">256</int>
<int key="NSvFlags">274</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSClipView" id="708990027">
@ -794,7 +901,7 @@
<object class="NSTextView" id="758761310">
<reference key="NSNextResponder" ref="708990027"/>
<int key="NSvFlags">2322</int>
<string key="NSFrameSize">{596, 14}</string>
<string key="NSFrameSize">{596, 114}</string>
<reference key="NSSuperview" ref="708990027"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<object class="NSTextContainer" key="NSTextContainer" id="548968659">
@ -874,7 +981,7 @@
<nil key="NSDelegate"/>
</object>
</object>
<string key="NSFrame">{{1, 1}, {596, 310}}</string>
<string key="NSFrame">{{1, 1}, {596, 410}}</string>
<reference key="NSSuperview" ref="486362220"/>
<reference key="NSNextKeyView" ref="758761310"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -889,7 +996,7 @@
<object class="NSScroller" id="794963499">
<reference key="NSNextResponder" ref="486362220"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{597, 1}, {15, 310}}</string>
<string key="NSFrame">{{597, 1}, {15, 410}}</string>
<reference key="NSSuperview" ref="486362220"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<reference key="NSTarget" ref="486362220"/>
@ -900,7 +1007,7 @@
<object class="NSScroller" id="324242772">
<reference key="NSNextResponder" ref="486362220"/>
<int key="NSvFlags">256</int>
<string key="NSFrame">{{1, 311}, {596, 15}}</string>
<string key="NSFrame">{{1, 411}, {596, 15}}</string>
<reference key="NSSuperview" ref="486362220"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<int key="NSsFlags">1</int>
@ -910,7 +1017,7 @@
<double key="NSPercent">0.94565218687057495</double>
</object>
</object>
<string key="NSFrame">{{-3, -3}, {613, 327}}</string>
<string key="NSFrame">{{-3, -3}, {613, 427}}</string>
<reference key="NSSuperview" ref="311013698"/>
<reference key="NSNextKeyView" ref="708990027"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -920,7 +1027,7 @@
<reference key="NSContentView" ref="708990027"/>
</object>
</object>
<string key="NSFrame">{{10, 33}, {607, 327}}</string>
<string key="NSFrame">{{10, 33}, {607, 427}}</string>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
</object>
<string key="NSLabel">Log Messages</string>
@ -928,17 +1035,17 @@
<reference key="NSTabView" ref="389252804"/>
</object>
</object>
<reference key="NSSelectedTabViewItem" ref="740075218"/>
<reference key="NSSelectedTabViewItem" ref="762265164"/>
<reference key="NSFont" ref="696441443"/>
<int key="NSTvFlags">0</int>
<bool key="NSDrawsBackground">YES</bool>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="187214803"/>
<reference ref="60314308"/>
</object>
</object>
</object>
<string key="NSFrameSize">{611, 369}</string>
<string key="NSFrameSize">{611, 469}</string>
<reference key="NSSuperview"/>
<object class="NSDictionary" key="NSViewAnimations">
<string key="NS.key.0">subviews</string>
@ -962,8 +1069,8 @@
</object>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
</object>
<string key="NSScreenRect">{{0, 0}, {800, 578}}</string>
<string key="NSMinSize">{213, 129}</string>
<string key="NSScreenRect">{{0, 0}, {1280, 778}}</string>
<string key="NSMinSize">{611, 491}</string>
<string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string>
</object>
<object class="NSArrayController" id="678105904">
@ -979,10 +1086,6 @@
<string key="NSClassName">SshuttleController</string>
</object>
<object class="NSUserDefaultsController" id="582889489">
<object class="NSMutableArray" key="NSDeclaredKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>debug</string>
</object>
<bool key="NSSharedInstance">YES</bool>
</object>
<object class="NSCustomObject" id="735871403">
@ -1000,6 +1103,9 @@
<string>statusMsg</string>
<string>status</string>
<string>isValid</string>
<string>useDns</string>
<string>title</string>
<string>latencyControl</string>
</object>
<string key="NSObjectClassName">SshuttleServer</string>
<bool key="NSEditable">YES</bool>
@ -1109,35 +1215,6 @@
</object>
<int key="connectionID">480</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: arrangedObjects.host</string>
<reference key="source" ref="807059746"/>
<reference key="destination" ref="59237012"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="807059746"/>
<reference key="NSDestination" ref="59237012"/>
<string key="NSLabel">value: arrangedObjects.host</string>
<string key="NSBinding">value</string>
<string key="NSKeyPath">arrangedObjects.host</string>
<object class="NSDictionary" key="NSOptions">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>NSConditionallySetsEditable</string>
<string>NSNullPlaceholder</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<boolean value="YES"/>
<string>Untitled</string>
</object>
</object>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">495</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">selectedIndex: selection.autoNets</string>
@ -1454,6 +1531,83 @@
</object>
<int key="connectionID">557</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: selection.useDns</string>
<reference key="source" ref="160987209"/>
<reference key="destination" ref="59237012"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="160987209"/>
<reference key="NSDestination" ref="59237012"/>
<string key="NSLabel">value: selection.useDns</string>
<string key="NSBinding">value</string>
<string key="NSKeyPath">selection.useDns</string>
<object class="NSDictionary" key="NSOptions">
<string key="NS.key.0">NSNoSelectionPlaceholder</string>
<integer value="0" key="NS.object.0"/>
</object>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">572</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: arrangedObjects.title</string>
<reference key="source" ref="807059746"/>
<reference key="destination" ref="59237012"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="807059746"/>
<reference key="NSDestination" ref="59237012"/>
<string key="NSLabel">value: arrangedObjects.title</string>
<string key="NSBinding">value</string>
<string key="NSKeyPath">arrangedObjects.title</string>
<object class="NSDictionary" key="NSOptions">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>NSConditionallySetsEditable</string>
<string>NSNullPlaceholder</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<boolean value="YES"/>
<string>Untitled</string>
</object>
</object>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">573</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">selectedIndex: selection.latencyControl</string>
<reference key="source" ref="451647466"/>
<reference key="destination" ref="59237012"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="451647466"/>
<reference key="NSDestination" ref="59237012"/>
<string key="NSLabel">selectedIndex: selection.latencyControl</string>
<string key="NSBinding">selectedIndex</string>
<string key="NSKeyPath">selection.latencyControl</string>
<object class="NSDictionary" key="NSOptions">
<string key="NS.key.0">NSNoSelectionPlaceholder</string>
<real value="1" key="NS.object.0"/>
</object>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">581</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">latencyControlField</string>
<reference key="source" ref="307402018"/>
<reference key="destination" ref="451647466"/>
</object>
<int key="connectionID">582</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
@ -1554,15 +1708,18 @@
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="889877302"/>
<reference ref="753545988"/>
<reference ref="26015719"/>
<reference ref="244571541"/>
<reference ref="776974664"/>
<reference ref="962924480"/>
<reference ref="705215911"/>
<reference ref="610703353"/>
<reference ref="160987209"/>
<reference ref="801412726"/>
<reference ref="840157770"/>
<reference ref="538356055"/>
<reference ref="776974664"/>
<reference ref="610703353"/>
<reference ref="26015719"/>
<reference ref="244571541"/>
<reference ref="962924480"/>
<reference ref="705215911"/>
<reference ref="451647466"/>
<reference ref="459566505"/>
</object>
<reference key="parent" ref="762265164"/>
</object>
@ -1962,6 +2119,78 @@
<reference key="object" ref="132399775"/>
<reference key="parent" ref="625121428"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">561</int>
<reference key="object" ref="160987209"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="565787077"/>
</object>
<reference key="parent" ref="60314308"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">562</int>
<reference key="object" ref="565787077"/>
<reference key="parent" ref="160987209"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">574</int>
<reference key="object" ref="451647466"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="970826243"/>
</object>
<reference key="parent" ref="60314308"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">575</int>
<reference key="object" ref="970826243"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="790880658"/>
</object>
<reference key="parent" ref="451647466"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">576</int>
<reference key="object" ref="790880658"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="195135854"/>
<reference ref="778262848"/>
<reference ref="903120255"/>
</object>
<reference key="parent" ref="970826243"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">577</int>
<reference key="object" ref="195135854"/>
<reference key="parent" ref="790880658"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">578</int>
<reference key="object" ref="778262848"/>
<reference key="parent" ref="790880658"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">579</int>
<reference key="object" ref="903120255"/>
<reference key="parent" ref="790880658"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">583</int>
<reference key="object" ref="459566505"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="534245320"/>
</object>
<reference key="parent" ref="60314308"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">584</int>
<reference key="object" ref="534245320"/>
<reference key="parent" ref="459566505"/>
</object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
@ -2055,6 +2284,18 @@
<string>552.IBAttributePlaceholdersKey</string>
<string>552.IBPluginDependency</string>
<string>553.IBPluginDependency</string>
<string>561.IBAttributePlaceholdersKey</string>
<string>561.IBPluginDependency</string>
<string>562.IBPluginDependency</string>
<string>574.IBAttributePlaceholdersKey</string>
<string>574.IBPluginDependency</string>
<string>575.IBPluginDependency</string>
<string>576.IBPluginDependency</string>
<string>577.IBPluginDependency</string>
<string>578.IBPluginDependency</string>
<string>579.IBPluginDependency</string>
<string>583.IBPluginDependency</string>
<string>584.IBPluginDependency</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
@ -2062,13 +2303,13 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/>
<boolean value="YES"/>
<string>{{317, 387}, {611, 369}}</string>
<string>{{324, 171}, {611, 469}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{317, 387}, {611, 369}}</string>
<string>{{324, 171}, {611, 469}}</string>
<boolean value="YES"/>
<boolean value="NO"/>
<boolean value="YES"/>
<string>{213, 107}</string>
<string>{611, 469}</string>
<object class="NSMutableDictionary">
<string key="NS.key.0">ToolTip</string>
<object class="IBToolTipAttribute" key="NS.object.0">
@ -2232,6 +2473,32 @@
</object>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSMutableDictionary">
<string key="NS.key.0">ToolTip</string>
<object class="IBToolTipAttribute" key="NS.object.0">
<string key="name">ToolTip</string>
<reference key="object" ref="160987209"/>
<string key="toolTip">Search for server names on the remote end and add them to your computer's /etc/hosts file.</string>
</object>
</object>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSMutableDictionary">
<string key="NS.key.0">ToolTip</string>
<object class="IBToolTipAttribute" key="NS.object.0">
<string key="name">ToolTip</string>
<reference key="object" ref="451647466"/>
<string key="toolTip">Choose which network traffic should be routed over the VPN.</string>
</object>
</object>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
</object>
</object>
<object class="NSMutableDictionary" key="unlocalizedProperties">
@ -2250,7 +2517,7 @@
</object>
</object>
<nil key="sourceID"/>
<int key="maxID">557</int>
<int key="maxID">584</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
@ -2280,6 +2547,7 @@
<bool key="EncodedWithXMLCoder">YES</bool>
<string>autoReconnectField</string>
<string>debugField</string>
<string>latencyControlField</string>
<string>logField</string>
<string>prefsWindow</string>
<string>routingField</string>
@ -2295,6 +2563,7 @@
<string>id</string>
<string>id</string>
<string>id</string>
<string>id</string>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">

View File

@ -1,5 +1,10 @@
exec >&2
redo-ifchange runpython.c
gcc -Wall -o $3 runpython.c \
ARCHES=""
for d in /usr/libexec/gcc/darwin/*; do
ARCHES="$ARCHES -arch $(basename $d)"
done
gcc $ARCHES \
-Wall -o $3 runpython.c \
-I/usr/include/python2.5 \
-lpython2.5

View File

@ -1,4 +1,4 @@
exec >&2
find -name '*~' | xargs rm -f
find . -name '*~' | xargs rm -f
rm -rf *.app *.zip *.tar.gz
rm -f bits/runpython *.nib sources.list

View File

@ -2,7 +2,8 @@ import sys, os, pty
from AppKit import *
import my, models, askpass
def sshuttle_args(host, auto_nets, auto_hosts, nets, debug):
def sshuttle_args(host, auto_nets, auto_hosts, dns, nets, debug,
no_latency_control):
argv = [my.bundle_path('sshuttle/sshuttle', ''), '-r', host]
assert(argv[0])
if debug:
@ -11,6 +12,10 @@ def sshuttle_args(host, auto_nets, auto_hosts, nets, debug):
argv.append('--auto-nets')
if auto_hosts:
argv.append('--auto-hosts')
if dns:
argv.append('--dns')
if no_latency_control:
argv.append('--no-latency-control')
argv += nets
return argv
@ -131,6 +136,7 @@ class SshuttleController(NSObject):
prefsWindow = objc.IBOutlet()
serversController = objc.IBOutlet()
logField = objc.IBOutlet()
latencyControlField = objc.IBOutlet()
servers = []
conns = {}
@ -156,11 +162,14 @@ class SshuttleController(NSObject):
manual_nets = ['0/0']
else:
manual_nets = []
noLatencyControl = (server.latencyControl() != models.LAT_INTERACTIVE)
conn = Runner(sshuttle_args(host,
auto_nets = nets_mode == models.NET_AUTO,
auto_hosts = server.autoHosts(),
dns = server.useDns(),
nets = manual_nets,
debug = self.debugField.state()),
debug = self.debugField.state(),
no_latency_control = noLatencyControl),
logfunc=logfunc, promptfunc=promptfunc,
serverobj=server)
self.conns[host] = conn
@ -213,6 +222,7 @@ class SshuttleController(NSObject):
if len(self.servers):
for i in self.servers:
host = i.host()
title = i.title()
want = i.wantConnect()
connected = i.connected()
numnets = len(list(i.nets()))
@ -222,9 +232,9 @@ class SshuttleController(NSObject):
additem('Connect %s (no routes)' % host, None, i)
elif want:
any_conn = i
additem('Disconnect %s' % host, self.cmd_disconnect, i)
additem('Disconnect %s' % title, self.cmd_disconnect, i)
else:
additem('Connect %s' % host, self.cmd_connect, i)
additem('Connect %s' % title, self.cmd_connect, i)
if not want:
msg = 'Off'
elif i.error():
@ -236,12 +246,6 @@ class SshuttleController(NSObject):
msg = 'Connecting...'
any_inprogress = i
addnote(' State: %s' % msg)
if i.autoNets() == 0:
addnote(' Routes: All')
elif i.autoNets() == 2:
addnote(' Routes: Auto')
else:
addnote(' Routes: Custom')
else:
addnote('No servers defined yet')
@ -279,13 +283,17 @@ class SshuttleController(NSObject):
net.setWidth_(width)
nl.append(net)
autoNets = s.get('autoNets', 1)
autoHosts = s.get('autoHosts', 1)
autoNets = s.get('autoNets', models.NET_AUTO)
autoHosts = s.get('autoHosts', True)
useDns = s.get('useDns', autoNets == models.NET_ALL)
latencyControl = s.get('latencyControl', models.LAT_INTERACTIVE)
srv = models.SshuttleServer.alloc().init()
srv.setHost_(host)
srv.setAutoNets_(autoNets)
srv.setAutoHosts_(autoHosts)
srv.setNets_(nl)
srv.setUseDns_(useDns)
srv.setLatencyControl_(latencyControl)
sl.append(srv)
self.serversController.addObjects_(sl)
self.serversController.setSelectionIndex_(0)
@ -303,7 +311,9 @@ class SshuttleController(NSObject):
d = dict(host=s.host(),
nets=nets,
autoNets=s.autoNets(),
autoHosts=s.autoHosts())
autoHosts=s.autoHosts(),
useDns=s.useDns(),
latencyControl=s.latencyControl())
l.append(d)
my.Defaults().setObject_forKey_(l, 'servers')
self.fill_menu()
@ -315,6 +325,11 @@ class SshuttleController(NSObject):
tf('Determine automatically')
tf('Custom...')
self.latencyControlField.removeAllItems()
tf = self.latencyControlField.addItemWithTitle_
tf('Fast transfer')
tf('Low latency')
# Hmm, even when I mark this as !enabled in the .nib, it still comes
# through as enabled. So let's just disable it here (since we don't
# support this feature yet).

View File

@ -58,6 +58,9 @@ NET_ALL = 0
NET_AUTO = 1
NET_MANUAL = 2
LAT_BANDWIDTH = 0
LAT_INTERACTIVE = 1
class SshuttleServer(NSObject):
def init(self):
self = super(SshuttleServer, self).init()
@ -93,10 +96,27 @@ class SshuttleServer(NSObject):
return False
return True
def title(self):
host = self.host()
if not host:
return host
an = self.autoNets()
suffix = ""
if an == NET_ALL:
suffix = " (all traffic)"
elif an == NET_MANUAL:
n = self.nets()
suffix = ' (%d subnet%s)' % (len(n), len(n)!=1 and 's' or '')
return self.host() + suffix
def setTitle_(self, v):
# title is always auto-generated
config_changed()
def host(self):
return getattr(self, '_k_host', None)
def setHost_(self, v):
self._k_host = v
self.setTitle_(None)
config_changed()
@objc.accessor
def validateHost_error_(self, value, error):
@ -109,6 +129,7 @@ class SshuttleServer(NSObject):
return getattr(self, '_k_nets', [])
def setNets_(self, v):
self._k_nets = v
self.setTitle_(None)
config_changed()
def netsHidden(self):
#print 'checking netsHidden'
@ -122,6 +143,8 @@ class SshuttleServer(NSObject):
def setAutoNets_(self, v):
self._k_autoNets = v
self.setNetsHidden_(-1)
self.setUseDns_(v == NET_ALL)
self.setTitle_(None)
config_changed()
def autoHosts(self):
@ -129,3 +152,15 @@ class SshuttleServer(NSObject):
def setAutoHosts_(self, v):
self._k_autoHosts = v
config_changed()
def useDns(self):
return getattr(self, '_k_useDns', False)
def setUseDns_(self, v):
self._k_useDns = v
config_changed()
def latencyControl(self):
return getattr(self, '_k_latencyControl', LAT_INTERACTIVE)
def setLatencyControl_(self, v):
self._k_latencyControl = v
config_changed()

View File

@ -1,3 +1,4 @@
redo-ifchange debug.app
exec >&2
./debug.app/Contents/MacOS/run
./debug.app/Contents/MacOS/Sshuttle