Compare commits

...

6 Commits

Author SHA1 Message Date
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
9 changed files with 545 additions and 121 deletions

View File

@ -273,6 +273,10 @@ def _main(listener, fw, ssh_cmd, remotename, python, latency_control,
sock.close() sock.close()
return return
chan = mux.next_channel() 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) mux.send(chan, ssnet.CMD_CONNECT, '%s,%s' % dstip)
outwrap = MuxWrapper(mux, chan) outwrap = MuxWrapper(mux, chan)
handlers.append(Proxy(SockWrapper(sock, sock), outwrap)) handlers.append(Proxy(SockWrapper(sock, sock), outwrap))

View File

@ -131,11 +131,11 @@ def _fill_oldctls(prefix):
def _sysctl_set(name, val): def _sysctl_set(name, val):
argv = ['sysctl', '-w', '%s=%s' % (name, val)] argv = ['sysctl', '-w', '%s=%s' % (name, val)]
debug1('>> %s\n' % ' '.join(argv)) debug1('>> %s\n' % ' '.join(argv))
rv = ssubprocess.call(argv, stdout = open('/dev/null', 'w')) return ssubprocess.call(argv, stdout = open('/dev/null', 'w'))
_changedctls = [] _changedctls = []
def sysctl_set(name, val): def sysctl_set(name, val, permanent=False):
PREFIX = 'net.inet.ip' PREFIX = 'net.inet.ip'
assert(name.startswith(PREFIX + '.')) assert(name.startswith(PREFIX + '.'))
val = str(val) val = str(val)
@ -146,8 +146,16 @@ def sysctl_set(name, val):
return return
oldval = _oldctls[name] oldval = _oldctls[name]
if val != oldval: if val != oldval:
_changedctls.append(name) rv = _sysctl_set(name, val)
return _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)
def _udp_unpack(p): def _udp_unpack(p):
@ -206,7 +214,7 @@ def do_ipfw(port, dnsport, subnets):
if subnets or dnsport: if subnets or dnsport:
sysctl_set('net.inet.ip.fw.enable', 1) sysctl_set('net.inet.ip.fw.enable', 1)
sysctl_set('net.inet.ip.scopedroute', 0) sysctl_set('net.inet.ip.scopedroute', 0, permanent=True)
ipfw('add', sport, 'check-state', 'ip', ipfw('add', sport, 'check-state', 'ip',
'from', 'any', 'to', 'any') 'from', 'any', 'to', 'any')

View File

@ -62,6 +62,7 @@ v,verbose increase debug message verbosity
e,ssh-cmd= the command to use to connect to the remote [ssh] 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) seed-hosts= with -H, use these hostnames for initial scan (comma-separated)
no-latency-control sacrifice latency to improve bandwidth benchmarks 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 D,daemon run in the background as a daemon
syslog send log messages to syslog (default if you use --daemon) syslog send log messages to syslog (default if you use --daemon)
pidfile= pidfile name (only if using --daemon) [./sshuttle.pid] pidfile= pidfile name (only if using --daemon) [./sshuttle.pid]
@ -74,6 +75,9 @@ o = options.Options(optspec)
if opt.daemon: if opt.daemon:
opt.syslog = 1 opt.syslog = 1
if opt.wrap:
import ssnet
ssnet.MAX_CHANNEL = int(opt.wrap)
helpers.verbose = opt.verbose helpers.verbose = opt.verbose
try: try:

View File

@ -1,6 +1,8 @@
import struct, socket, errno, select import struct, socket, errno, select
if not globals().get('skip_imports'): if not globals().get('skip_imports'):
from helpers import * from helpers import *
MAX_CHANNEL = 65535
# these don't exist in the socket module in python 2.3! # these don't exist in the socket module in python 2.3!
SHUT_RD = 0 SHUT_RD = 0
@ -300,7 +302,7 @@ class Mux(Handler):
# channel 0 is special, so we never allocate it # channel 0 is special, so we never allocate it
for timeout in xrange(1024): for timeout in xrange(1024):
self.chani += 1 self.chani += 1
if self.chani > 65535: if self.chani > MAX_CHANNEL:
self.chani = 1 self.chani = 1
if not self.channels.get(self.chani): if not self.channels.get(self.chani):
return self.chani return self.chani

86
stresstest.py Executable file
View File

@ -0,0 +1,86 @@
#!/usr/bin/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"> <archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
<data> <data>
<int key="IBDocument.SystemTarget">1060</int> <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.InterfaceBuilderVersion">762</string>
<string key="IBDocument.AppKitVersion">1038.35</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"> <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">762</string> <string key="NS.object.0">762</string>
</object> </object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<integer value="233"/> <integer value="237"/>
</object> </object>
<object class="NSArray" key="IBDocument.PluginDependencies"> <object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
@ -41,9 +41,9 @@
<string key="NSClassName">NSApplication</string> <string key="NSClassName">NSApplication</string>
</object> </object>
<object class="NSWindowTemplate" id="411825121"> <object class="NSWindowTemplate" id="411825121">
<int key="NSWindowStyleMask">3</int> <int key="NSWindowStyleMask">11</int>
<int key="NSWindowBacking">2</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> <int key="NSWTFlags">1886913536</int>
<string key="NSWindowTitle">Sshuttle VPN Preferences</string> <string key="NSWindowTitle">Sshuttle VPN Preferences</string>
<string key="NSWindowClass">NSWindow</string> <string key="NSWindowClass">NSWindow</string>
@ -51,16 +51,16 @@
<characters key="NS.bytes">View</characters> <characters key="NS.bytes">View</characters>
</object> </object>
<string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string> <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"> <object class="NSView" key="NSWindowView" id="174067038">
<reference key="NSNextResponder"/> <reference key="NSNextResponder"/>
<int key="NSvFlags">256</int> <int key="NSvFlags">274</int>
<object class="NSMutableArray" key="NSSubviews"> <object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSTabView" id="389252804"> <object class="NSTabView" id="389252804">
<reference key="NSNextResponder" ref="174067038"/> <reference key="NSNextResponder" ref="174067038"/>
<int key="NSvFlags">12</int> <int key="NSvFlags">18</int>
<string key="NSFrame">{{-8, -10}, {627, 373}}</string> <string key="NSFrame">{{-8, -10}, {627, 473}}</string>
<reference key="NSSuperview" ref="174067038"/> <reference key="NSSuperview" ref="174067038"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
<object class="NSMutableArray" key="NSTabViewItems"> <object class="NSMutableArray" key="NSTabViewItems">
@ -68,13 +68,13 @@
<object class="NSTabViewItem" id="762265164"> <object class="NSTabViewItem" id="762265164">
<string key="NSIdentifier">1</string> <string key="NSIdentifier">1</string>
<object class="NSView" key="NSView" id="60314308"> <object class="NSView" key="NSView" id="60314308">
<nil key="NSNextResponder"/> <reference key="NSNextResponder" ref="389252804"/>
<int key="NSvFlags">256</int> <int key="NSvFlags">274</int>
<object class="NSMutableArray" key="NSSubviews"> <object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSButton" id="26015719"> <object class="NSButton" id="26015719">
<reference key="NSNextResponder" ref="60314308"/> <reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int> <int key="NSvFlags">292</int>
<string key="NSFrame">{{17, 17}, {25, 23}}</string> <string key="NSFrame">{{17, 17}, {25, 23}}</string>
<reference key="NSSuperview" ref="60314308"/> <reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -103,7 +103,7 @@
</object> </object>
<object class="NSButton" id="244571541"> <object class="NSButton" id="244571541">
<reference key="NSNextResponder" ref="60314308"/> <reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int> <int key="NSvFlags">292</int>
<string key="NSFrame">{{41, 17}, {25, 23}}</string> <string key="NSFrame">{{41, 17}, {25, 23}}</string>
<reference key="NSSuperview" ref="60314308"/> <reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -128,7 +128,7 @@
</object> </object>
<object class="NSScrollView" id="776974664"> <object class="NSScrollView" id="776974664">
<reference key="NSNextResponder" ref="60314308"/> <reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int> <int key="NSvFlags">274</int>
<object class="NSMutableArray" key="NSSubviews"> <object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSClipView" id="8658574"> <object class="NSClipView" id="8658574">
@ -139,7 +139,7 @@
<object class="NSTableView" id="849333466"> <object class="NSTableView" id="849333466">
<reference key="NSNextResponder" ref="8658574"/> <reference key="NSNextResponder" ref="8658574"/>
<int key="NSvFlags">256</int> <int key="NSvFlags">256</int>
<string key="NSFrameSize">{224, 282}</string> <string key="NSFrameSize">{224, 372}</string>
<reference key="NSSuperview" ref="8658574"/> <reference key="NSSuperview" ref="8658574"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool> <bool key="NSEnabled">YES</bool>
@ -275,7 +275,7 @@
<int key="NSTableViewDraggingDestinationStyle">0</int> <int key="NSTableViewDraggingDestinationStyle">0</int>
</object> </object>
</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="NSSuperview" ref="776974664"/>
<reference key="NSNextKeyView" ref="849333466"/> <reference key="NSNextKeyView" ref="849333466"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -306,7 +306,7 @@
<double key="NSPercent">0.91812865497076024</double> <double key="NSPercent">0.91812865497076024</double>
</object> </object>
</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="NSSuperview" ref="60314308"/>
<reference key="NSNextKeyView" ref="8658574"/> <reference key="NSNextKeyView" ref="8658574"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -318,8 +318,8 @@
</object> </object>
<object class="NSButton" id="538356055"> <object class="NSButton" id="538356055">
<reference key="NSNextResponder" ref="60314308"/> <reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int> <int key="NSvFlags">265</int>
<string key="NSFrame">{{296, 254}, {273, 18}}</string> <string key="NSFrame">{{291, 356}, {273, 18}}</string>
<reference key="NSSuperview" ref="60314308"/> <reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool> <bool key="NSEnabled">YES</bool>
@ -341,8 +341,8 @@
</object> </object>
<object class="NSTextField" id="889877302"> <object class="NSTextField" id="889877302">
<reference key="NSNextResponder" ref="60314308"/> <reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int> <int key="NSvFlags">265</int>
<string key="NSFrame">{{341, 292}, {249, 22}}</string> <string key="NSFrame">{{341, 392}, {249, 22}}</string>
<reference key="NSSuperview" ref="60314308"/> <reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool> <bool key="NSEnabled">YES</bool>
@ -369,8 +369,8 @@
</object> </object>
<object class="NSPopUpButton" id="801412726"> <object class="NSPopUpButton" id="801412726">
<reference key="NSNextResponder" ref="60314308"/> <reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int> <int key="NSvFlags">265</int>
<string key="NSFrame">{{273, 185}, {320, 26}}</string> <string key="NSFrame">{{273, 193}, {320, 26}}</string>
<reference key="NSSuperview" ref="60314308"/> <reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool> <bool key="NSEnabled">YES</bool>
@ -440,10 +440,77 @@
<int key="NSArrowPosition">2</int> <int key="NSArrowPosition">2</int>
</object> </object>
</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"> <object class="NSTextField" id="753545988">
<reference key="NSNextResponder" ref="60314308"/> <reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int> <int key="NSvFlags">265</int>
<string key="NSFrame">{{261, 294}, {75, 17}}</string> <string key="NSFrame">{{261, 394}, {75, 17}}</string>
<reference key="NSSuperview" ref="60314308"/> <reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool> <bool key="NSEnabled">YES</bool>
@ -459,8 +526,8 @@
</object> </object>
<object class="NSTextField" id="840157770"> <object class="NSTextField" id="840157770">
<reference key="NSNextResponder" ref="60314308"/> <reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int> <int key="NSvFlags">265</int>
<string key="NSFrame">{{261, 217}, {105, 17}}</string> <string key="NSFrame">{{261, 226}, {105, 17}}</string>
<reference key="NSSuperview" ref="60314308"/> <reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool> <bool key="NSEnabled">YES</bool>
@ -474,9 +541,26 @@
<reference key="NSTextColor" ref="399750419"/> <reference key="NSTextColor" ref="399750419"/>
</object> </object>
</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"> <object class="NSButton" id="962924480">
<reference key="NSNextResponder" ref="60314308"/> <reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int> <int key="NSvFlags">289</int>
<string key="NSFrame">{{276, 40}, {25, 23}}</string> <string key="NSFrame">{{276, 40}, {25, 23}}</string>
<reference key="NSSuperview" ref="60314308"/> <reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -498,7 +582,7 @@
</object> </object>
<object class="NSButton" id="705215911"> <object class="NSButton" id="705215911">
<reference key="NSNextResponder" ref="60314308"/> <reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int> <int key="NSvFlags">289</int>
<string key="NSFrame">{{300, 40}, {25, 23}}</string> <string key="NSFrame">{{300, 40}, {25, 23}}</string>
<reference key="NSSuperview" ref="60314308"/> <reference key="NSSuperview" ref="60314308"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -520,7 +604,7 @@
</object> </object>
<object class="NSScrollView" id="610703353"> <object class="NSScrollView" id="610703353">
<reference key="NSNextResponder" ref="60314308"/> <reference key="NSNextResponder" ref="60314308"/>
<int key="NSvFlags">268</int> <int key="NSvFlags">273</int>
<object class="NSMutableArray" key="NSSubviews"> <object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSClipView" id="844110079"> <object class="NSClipView" id="844110079">
@ -531,7 +615,7 @@
<object class="NSTableView" id="714838401"> <object class="NSTableView" id="714838401">
<reference key="NSNextResponder" ref="844110079"/> <reference key="NSNextResponder" ref="844110079"/>
<int key="NSvFlags">256</int> <int key="NSvFlags">256</int>
<string key="NSFrameSize">{312, 95}</string> <string key="NSFrameSize">{312, 102}</string>
<reference key="NSSuperview" ref="844110079"/> <reference key="NSSuperview" ref="844110079"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool> <bool key="NSEnabled">YES</bool>
@ -623,7 +707,7 @@
<int key="NSTableViewDraggingDestinationStyle">0</int> <int key="NSTableViewDraggingDestinationStyle">0</int>
</object> </object>
</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="NSSuperview" ref="610703353"/>
<reference key="NSNextKeyView" ref="714838401"/> <reference key="NSNextKeyView" ref="714838401"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -639,7 +723,7 @@
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
<reference key="NSTarget" ref="610703353"/> <reference key="NSTarget" ref="610703353"/>
<string key="NSAction">_doScroller:</string> <string key="NSAction">_doScroller:</string>
<double key="NSPercent">0.8529411764705882</double> <double key="NSPercent">0.96938775510204078</double>
</object> </object>
<object class="NSScroller" id="522064761"> <object class="NSScroller" id="522064761">
<reference key="NSNextResponder" ref="610703353"/> <reference key="NSNextResponder" ref="610703353"/>
@ -669,7 +753,7 @@
</object> </object>
<reference ref="188199142"/> <reference ref="188199142"/>
</object> </object>
<string key="NSFrame">{{276, 63}, {314, 113}}</string> <string key="NSFrame">{{276, 63}, {314, 120}}</string>
<reference key="NSSuperview" ref="60314308"/> <reference key="NSSuperview" ref="60314308"/>
<reference key="NSNextKeyView" ref="844110079"/> <reference key="NSNextKeyView" ref="844110079"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -681,8 +765,32 @@
<reference key="NSCornerView" ref="188199142"/> <reference key="NSCornerView" ref="188199142"/>
<bytes key="NSScrollAmts">QSAAAEEgAABBmAAAQZgAAA</bytes> <bytes key="NSScrollAmts">QSAAAEEgAABBmAAAQZgAAA</bytes>
</object> </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>
</object>
</object> </object>
<string key="NSFrame">{{10, 33}, {607, 327}}</string> <string key="NSFrame">{{10, 33}, {607, 427}}</string>
<reference key="NSSuperview" ref="389252804"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
</object> </object>
<string key="NSLabel">SSH Servers</string> <string key="NSLabel">SSH Servers</string>
@ -692,14 +800,14 @@
<object class="NSTabViewItem" id="740075218"> <object class="NSTabViewItem" id="740075218">
<string key="NSIdentifier">2</string> <string key="NSIdentifier">2</string>
<object class="NSView" key="NSView" id="187214803"> <object class="NSView" key="NSView" id="187214803">
<reference key="NSNextResponder" ref="389252804"/> <nil key="NSNextResponder"/>
<int key="NSvFlags">256</int> <int key="NSvFlags">274</int>
<object class="NSMutableArray" key="NSSubviews"> <object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSButton" id="625816566"> <object class="NSButton" id="625816566">
<reference key="NSNextResponder" ref="187214803"/> <reference key="NSNextResponder" ref="187214803"/>
<int key="NSvFlags">268</int> <int key="NSvFlags">269</int>
<string key="NSFrame">{{189, 287}, {177, 29}}</string> <string key="NSFrame">{{195, 374}, {236, 29}}</string>
<reference key="NSSuperview" ref="187214803"/> <reference key="NSSuperview" ref="187214803"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool> <bool key="NSEnabled">YES</bool>
@ -721,8 +829,8 @@
</object> </object>
<object class="NSButton" id="633518934"> <object class="NSButton" id="633518934">
<reference key="NSNextResponder" ref="187214803"/> <reference key="NSNextResponder" ref="187214803"/>
<int key="NSvFlags">268</int> <int key="NSvFlags">269</int>
<string key="NSFrame">{{189, 256}, {270, 29}}</string> <string key="NSFrame">{{195, 343}, {236, 29}}</string>
<reference key="NSSuperview" ref="187214803"/> <reference key="NSSuperview" ref="187214803"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool> <bool key="NSEnabled">YES</bool>
@ -744,15 +852,15 @@
</object> </object>
<object class="NSButton" id="625121428"> <object class="NSButton" id="625121428">
<reference key="NSNextResponder" ref="187214803"/> <reference key="NSNextResponder" ref="187214803"/>
<int key="NSvFlags">268</int> <int key="NSvFlags">269</int>
<string key="NSFrame">{{189, 225}, {270, 29}}</string> <string key="NSFrame">{{195, 312}, {236, 29}}</string>
<reference key="NSSuperview" ref="187214803"/> <reference key="NSSuperview" ref="187214803"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool> <bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="132399775"> <object class="NSButtonCell" key="NSCell" id="132399775">
<int key="NSCellFlags">67239424</int> <int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">0</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="NSSupport" ref="696441443"/>
<reference key="NSControlView" ref="625121428"/> <reference key="NSControlView" ref="625121428"/>
<int key="NSButtonFlags">1211912703</int> <int key="NSButtonFlags">1211912703</int>
@ -766,8 +874,7 @@
</object> </object>
</object> </object>
</object> </object>
<string key="NSFrame">{{10, 33}, {607, 327}}</string> <string key="NSFrame">{{10, 33}, {607, 427}}</string>
<reference key="NSSuperview" ref="389252804"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
</object> </object>
<string key="NSLabel">Options</string> <string key="NSLabel">Options</string>
@ -783,7 +890,7 @@
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSScrollView" id="486362220"> <object class="NSScrollView" id="486362220">
<reference key="NSNextResponder" ref="311013698"/> <reference key="NSNextResponder" ref="311013698"/>
<int key="NSvFlags">256</int> <int key="NSvFlags">274</int>
<object class="NSMutableArray" key="NSSubviews"> <object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSClipView" id="708990027"> <object class="NSClipView" id="708990027">
@ -794,7 +901,7 @@
<object class="NSTextView" id="758761310"> <object class="NSTextView" id="758761310">
<reference key="NSNextResponder" ref="708990027"/> <reference key="NSNextResponder" ref="708990027"/>
<int key="NSvFlags">2322</int> <int key="NSvFlags">2322</int>
<string key="NSFrameSize">{596, 14}</string> <string key="NSFrameSize">{596, 114}</string>
<reference key="NSSuperview" ref="708990027"/> <reference key="NSSuperview" ref="708990027"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
<object class="NSTextContainer" key="NSTextContainer" id="548968659"> <object class="NSTextContainer" key="NSTextContainer" id="548968659">
@ -874,7 +981,7 @@
<nil key="NSDelegate"/> <nil key="NSDelegate"/>
</object> </object>
</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="NSSuperview" ref="486362220"/>
<reference key="NSNextKeyView" ref="758761310"/> <reference key="NSNextKeyView" ref="758761310"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -889,7 +996,7 @@
<object class="NSScroller" id="794963499"> <object class="NSScroller" id="794963499">
<reference key="NSNextResponder" ref="486362220"/> <reference key="NSNextResponder" ref="486362220"/>
<int key="NSvFlags">256</int> <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"/> <reference key="NSSuperview" ref="486362220"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
<reference key="NSTarget" ref="486362220"/> <reference key="NSTarget" ref="486362220"/>
@ -900,7 +1007,7 @@
<object class="NSScroller" id="324242772"> <object class="NSScroller" id="324242772">
<reference key="NSNextResponder" ref="486362220"/> <reference key="NSNextResponder" ref="486362220"/>
<int key="NSvFlags">256</int> <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"/> <reference key="NSSuperview" ref="486362220"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
<int key="NSsFlags">1</int> <int key="NSsFlags">1</int>
@ -910,7 +1017,7 @@
<double key="NSPercent">0.94565218687057495</double> <double key="NSPercent">0.94565218687057495</double>
</object> </object>
</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="NSSuperview" ref="311013698"/>
<reference key="NSNextKeyView" ref="708990027"/> <reference key="NSNextKeyView" ref="708990027"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
@ -920,7 +1027,7 @@
<reference key="NSContentView" ref="708990027"/> <reference key="NSContentView" ref="708990027"/>
</object> </object>
</object> </object>
<string key="NSFrame">{{10, 33}, {607, 327}}</string> <string key="NSFrame">{{10, 33}, {607, 427}}</string>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
</object> </object>
<string key="NSLabel">Log Messages</string> <string key="NSLabel">Log Messages</string>
@ -928,17 +1035,17 @@
<reference key="NSTabView" ref="389252804"/> <reference key="NSTabView" ref="389252804"/>
</object> </object>
</object> </object>
<reference key="NSSelectedTabViewItem" ref="740075218"/> <reference key="NSSelectedTabViewItem" ref="762265164"/>
<reference key="NSFont" ref="696441443"/> <reference key="NSFont" ref="696441443"/>
<int key="NSTvFlags">0</int> <int key="NSTvFlags">0</int>
<bool key="NSDrawsBackground">YES</bool> <bool key="NSDrawsBackground">YES</bool>
<object class="NSMutableArray" key="NSSubviews"> <object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="187214803"/> <reference ref="60314308"/>
</object> </object>
</object> </object>
</object> </object>
<string key="NSFrameSize">{611, 369}</string> <string key="NSFrameSize">{611, 469}</string>
<reference key="NSSuperview"/> <reference key="NSSuperview"/>
<object class="NSDictionary" key="NSViewAnimations"> <object class="NSDictionary" key="NSViewAnimations">
<string key="NS.key.0">subviews</string> <string key="NS.key.0">subviews</string>
@ -962,8 +1069,8 @@
</object> </object>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
</object> </object>
<string key="NSScreenRect">{{0, 0}, {800, 578}}</string> <string key="NSScreenRect">{{0, 0}, {1280, 778}}</string>
<string key="NSMinSize">{213, 129}</string> <string key="NSMinSize">{611, 491}</string>
<string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string> <string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string>
</object> </object>
<object class="NSArrayController" id="678105904"> <object class="NSArrayController" id="678105904">
@ -979,10 +1086,6 @@
<string key="NSClassName">SshuttleController</string> <string key="NSClassName">SshuttleController</string>
</object> </object>
<object class="NSUserDefaultsController" id="582889489"> <object class="NSUserDefaultsController" id="582889489">
<object class="NSMutableArray" key="NSDeclaredKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>debug</string>
</object>
<bool key="NSSharedInstance">YES</bool> <bool key="NSSharedInstance">YES</bool>
</object> </object>
<object class="NSCustomObject" id="735871403"> <object class="NSCustomObject" id="735871403">
@ -1000,6 +1103,9 @@
<string>statusMsg</string> <string>statusMsg</string>
<string>status</string> <string>status</string>
<string>isValid</string> <string>isValid</string>
<string>useDns</string>
<string>title</string>
<string>latencyControl</string>
</object> </object>
<string key="NSObjectClassName">SshuttleServer</string> <string key="NSObjectClassName">SshuttleServer</string>
<bool key="NSEditable">YES</bool> <bool key="NSEditable">YES</bool>
@ -1109,35 +1215,6 @@
</object> </object>
<int key="connectionID">480</int> <int key="connectionID">480</int>
</object> </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="IBConnectionRecord">
<object class="IBBindingConnection" key="connection"> <object class="IBBindingConnection" key="connection">
<string key="label">selectedIndex: selection.autoNets</string> <string key="label">selectedIndex: selection.autoNets</string>
@ -1454,6 +1531,83 @@
</object> </object>
<int key="connectionID">557</int> <int key="connectionID">557</int>
</object> </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>
<object class="IBMutableOrderedSet" key="objectRecords"> <object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects"> <object class="NSArray" key="orderedObjects">
@ -1554,15 +1708,18 @@
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="889877302"/> <reference ref="889877302"/>
<reference ref="753545988"/> <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="801412726"/>
<reference ref="840157770"/> <reference ref="840157770"/>
<reference ref="538356055"/> <reference ref="538356055"/>
<reference ref="776974664"/> <reference ref="451647466"/>
<reference ref="610703353"/> <reference ref="459566505"/>
<reference ref="26015719"/>
<reference ref="244571541"/>
<reference ref="962924480"/>
<reference ref="705215911"/>
</object> </object>
<reference key="parent" ref="762265164"/> <reference key="parent" ref="762265164"/>
</object> </object>
@ -1962,6 +2119,78 @@
<reference key="object" ref="132399775"/> <reference key="object" ref="132399775"/>
<reference key="parent" ref="625121428"/> <reference key="parent" ref="625121428"/>
</object> </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> </object>
<object class="NSMutableDictionary" key="flattenedProperties"> <object class="NSMutableDictionary" key="flattenedProperties">
@ -2055,6 +2284,18 @@
<string>552.IBAttributePlaceholdersKey</string> <string>552.IBAttributePlaceholdersKey</string>
<string>552.IBPluginDependency</string> <string>552.IBPluginDependency</string>
<string>553.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>
<object class="NSMutableArray" key="dict.values"> <object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
@ -2062,13 +2303,13 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES"/> <boolean value="YES"/>
<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>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{317, 387}, {611, 369}}</string> <string>{{324, 171}, {611, 469}}</string>
<boolean value="YES"/> <boolean value="YES"/>
<boolean value="NO"/> <boolean value="NO"/>
<boolean value="YES"/> <boolean value="YES"/>
<string>{213, 107}</string> <string>{611, 469}</string>
<object class="NSMutableDictionary"> <object class="NSMutableDictionary">
<string key="NS.key.0">ToolTip</string> <string key="NS.key.0">ToolTip</string>
<object class="IBToolTipAttribute" key="NS.object.0"> <object class="IBToolTipAttribute" key="NS.object.0">
@ -2232,6 +2473,32 @@
</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>
<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> </object>
<object class="NSMutableDictionary" key="unlocalizedProperties"> <object class="NSMutableDictionary" key="unlocalizedProperties">
@ -2250,7 +2517,7 @@
</object> </object>
</object> </object>
<nil key="sourceID"/> <nil key="sourceID"/>
<int key="maxID">557</int> <int key="maxID">584</int>
</object> </object>
<object class="IBClassDescriber" key="IBDocument.Classes"> <object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions"> <object class="NSMutableArray" key="referencedPartialClassDescriptions">
@ -2280,6 +2547,7 @@
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<string>autoReconnectField</string> <string>autoReconnectField</string>
<string>debugField</string> <string>debugField</string>
<string>latencyControlField</string>
<string>logField</string> <string>logField</string>
<string>prefsWindow</string> <string>prefsWindow</string>
<string>routingField</string> <string>routingField</string>
@ -2295,6 +2563,7 @@
<string>id</string> <string>id</string>
<string>id</string> <string>id</string>
<string>id</string> <string>id</string>
<string>id</string>
</object> </object>
</object> </object>
<object class="IBClassDescriptionSource" key="sourceIdentifier"> <object class="IBClassDescriptionSource" key="sourceIdentifier">

View File

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

View File

@ -58,6 +58,9 @@ NET_ALL = 0
NET_AUTO = 1 NET_AUTO = 1
NET_MANUAL = 2 NET_MANUAL = 2
LAT_BANDWIDTH = 0
LAT_INTERACTIVE = 1
class SshuttleServer(NSObject): class SshuttleServer(NSObject):
def init(self): def init(self):
self = super(SshuttleServer, self).init() self = super(SshuttleServer, self).init()
@ -92,11 +95,28 @@ class SshuttleServer(NSObject):
if self.autoNets() == NET_MANUAL and not len(list(self.nets())): if self.autoNets() == NET_MANUAL and not len(list(self.nets())):
return False return False
return True 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): def host(self):
return getattr(self, '_k_host', None) return getattr(self, '_k_host', None)
def setHost_(self, v): def setHost_(self, v):
self._k_host = v self._k_host = v
self.setTitle_(None)
config_changed() config_changed()
@objc.accessor @objc.accessor
def validateHost_error_(self, value, error): def validateHost_error_(self, value, error):
@ -109,6 +129,7 @@ class SshuttleServer(NSObject):
return getattr(self, '_k_nets', []) return getattr(self, '_k_nets', [])
def setNets_(self, v): def setNets_(self, v):
self._k_nets = v self._k_nets = v
self.setTitle_(None)
config_changed() config_changed()
def netsHidden(self): def netsHidden(self):
#print 'checking netsHidden' #print 'checking netsHidden'
@ -122,6 +143,8 @@ class SshuttleServer(NSObject):
def setAutoNets_(self, v): def setAutoNets_(self, v):
self._k_autoNets = v self._k_autoNets = v
self.setNetsHidden_(-1) self.setNetsHidden_(-1)
self.setUseDns_(v == NET_ALL)
self.setTitle_(None)
config_changed() config_changed()
def autoHosts(self): def autoHosts(self):
@ -129,3 +152,15 @@ class SshuttleServer(NSObject):
def setAutoHosts_(self, v): def setAutoHosts_(self, v):
self._k_autoHosts = v self._k_autoHosts = v
config_changed() 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 redo-ifchange debug.app
exec >&2 exec >&2
./debug.app/Contents/MacOS/run ./debug.app/Contents/MacOS/Sshuttle