mirror of
https://github.com/sshuttle/sshuttle.git
synced 2025-06-20 01:48:18 +02:00
MacOS precompiled app package for sshuttle-0.60
This commit is contained in:
parent
5b57de2404
commit
d5c3aa61b8
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -78,6 +78,11 @@ class Runner:
|
|||||||
if pid == self.pid:
|
if pid == self.pid:
|
||||||
if os.WIFEXITED(code):
|
if os.WIFEXITED(code):
|
||||||
self.rv = os.WEXITSTATUS(code)
|
self.rv = os.WEXITSTATUS(code)
|
||||||
|
if self.rv == 111:
|
||||||
|
NSRunAlertPanel('Sshuttle',
|
||||||
|
'Please restart your computer to finish '
|
||||||
|
'installing Sshuttle.',
|
||||||
|
'Restart Later', None, None)
|
||||||
else:
|
else:
|
||||||
self.rv = -os.WSTOPSIG(code)
|
self.rv = -os.WSTOPSIG(code)
|
||||||
self.serverobj.setConnected_(False)
|
self.serverobj.setConnected_(False)
|
||||||
@ -87,7 +92,10 @@ class Runner:
|
|||||||
return self.rv
|
return self.rv
|
||||||
|
|
||||||
def wait(self):
|
def wait(self):
|
||||||
return self._try_wait(0)
|
rv = None
|
||||||
|
while rv is None:
|
||||||
|
self.gotdata(None)
|
||||||
|
rv = self._try_wait(os.WNOHANG)
|
||||||
|
|
||||||
def poll(self):
|
def poll(self):
|
||||||
return self._try_wait(os.WNOHANG)
|
return self._try_wait(os.WNOHANG)
|
||||||
|
@ -3,6 +3,7 @@ import my
|
|||||||
|
|
||||||
|
|
||||||
configchange_callback = setconnect_callback = None
|
configchange_callback = setconnect_callback = None
|
||||||
|
objc_validator = objc.signature('@@:N^@o^@')
|
||||||
|
|
||||||
|
|
||||||
def config_changed():
|
def config_changed():
|
||||||
@ -39,7 +40,7 @@ class SshuttleNet(NSObject):
|
|||||||
def setSubnet_(self, v):
|
def setSubnet_(self, v):
|
||||||
self._k_subnet = v
|
self._k_subnet = v
|
||||||
config_changed()
|
config_changed()
|
||||||
@objc.accessor
|
@objc_validator
|
||||||
def validateSubnet_error_(self, value, error):
|
def validateSubnet_error_(self, value, error):
|
||||||
#print 'validateSubnet!'
|
#print 'validateSubnet!'
|
||||||
return True, _validate_ip(value), error
|
return True, _validate_ip(value), error
|
||||||
@ -49,7 +50,7 @@ class SshuttleNet(NSObject):
|
|||||||
def setWidth_(self, v):
|
def setWidth_(self, v):
|
||||||
self._k_width = v
|
self._k_width = v
|
||||||
config_changed()
|
config_changed()
|
||||||
@objc.accessor
|
@objc_validator
|
||||||
def validateWidth_error_(self, value, error):
|
def validateWidth_error_(self, value, error):
|
||||||
#print 'validateWidth!'
|
#print 'validateWidth!'
|
||||||
return True, _validate_width(value), error
|
return True, _validate_width(value), error
|
||||||
@ -118,7 +119,7 @@ class SshuttleServer(NSObject):
|
|||||||
self._k_host = v
|
self._k_host = v
|
||||||
self.setTitle_(None)
|
self.setTitle_(None)
|
||||||
config_changed()
|
config_changed()
|
||||||
@objc.accessor
|
@objc_validator
|
||||||
def validateHost_error_(self, value, error):
|
def validateHost_error_(self, value, error):
|
||||||
#print 'validatehost! %r %r %r' % (self, value, error)
|
#print 'validatehost! %r %r %r' % (self, value, error)
|
||||||
while value.startswith('-'):
|
while value.startswith('-'):
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -171,10 +171,71 @@ class FirewallClient:
|
|||||||
def done(self):
|
def done(self):
|
||||||
self.pfile.close()
|
self.pfile.close()
|
||||||
rv = self.p.wait()
|
rv = self.p.wait()
|
||||||
if rv:
|
if rv == EXITCODE_NEEDS_REBOOT:
|
||||||
|
raise FatalNeedsReboot()
|
||||||
|
elif rv:
|
||||||
raise Fatal('cleanup: %r returned %d' % (self.argv, rv))
|
raise Fatal('cleanup: %r returned %d' % (self.argv, rv))
|
||||||
|
|
||||||
|
|
||||||
|
def onaccept(listener, mux, handlers):
|
||||||
|
global _extra_fd
|
||||||
|
try:
|
||||||
|
sock,srcip = listener.accept()
|
||||||
|
except socket.error, e:
|
||||||
|
if e.args[0] in [errno.EMFILE, errno.ENFILE]:
|
||||||
|
debug1('Rejected incoming connection: too many open files!\n')
|
||||||
|
# free up an fd so we can eat the connection
|
||||||
|
os.close(_extra_fd)
|
||||||
|
try:
|
||||||
|
sock,srcip = listener.accept()
|
||||||
|
sock.close()
|
||||||
|
finally:
|
||||||
|
_extra_fd = os.open('/dev/null', os.O_RDONLY)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
dstip = original_dst(sock)
|
||||||
|
debug1('Accept: %s:%r -> %s:%r.\n' % (srcip[0],srcip[1],
|
||||||
|
dstip[0],dstip[1]))
|
||||||
|
if dstip[1] == listener.getsockname()[1] and islocal(dstip[0]):
|
||||||
|
debug1("-- ignored: that's my address!\n")
|
||||||
|
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))
|
||||||
|
|
||||||
|
|
||||||
|
dnsreqs = {}
|
||||||
|
def dns_done(chan, data):
|
||||||
|
peer,sock,timeout = dnsreqs.get(chan) or (None,None,None)
|
||||||
|
debug3('dns_done: channel=%r peer=%r\n' % (chan, peer))
|
||||||
|
if peer:
|
||||||
|
del dnsreqs[chan]
|
||||||
|
debug3('doing sendto %r\n' % (peer,))
|
||||||
|
sock.sendto(data, peer)
|
||||||
|
|
||||||
|
|
||||||
|
def ondns(listener, mux, handlers):
|
||||||
|
pkt,peer = listener.recvfrom(4096)
|
||||||
|
now = time.time()
|
||||||
|
if pkt:
|
||||||
|
debug1('DNS request from %r: %d bytes\n' % (peer, len(pkt)))
|
||||||
|
chan = mux.next_channel()
|
||||||
|
dnsreqs[chan] = peer,listener,now+30
|
||||||
|
mux.send(chan, ssnet.CMD_DNS_REQ, pkt)
|
||||||
|
mux.channels[chan] = lambda cmd,data: dns_done(chan,data)
|
||||||
|
for chan,(peer,sock,timeout) in dnsreqs.items():
|
||||||
|
if timeout < now:
|
||||||
|
del dnsreqs[chan]
|
||||||
|
debug3('Remaining DNS requests: %d\n' % len(dnsreqs))
|
||||||
|
|
||||||
|
|
||||||
def _main(listener, fw, ssh_cmd, remotename, python, latency_control,
|
def _main(listener, fw, ssh_cmd, remotename, python, latency_control,
|
||||||
dnslistener, seed_hosts, auto_nets,
|
dnslistener, seed_hosts, auto_nets,
|
||||||
syslog, daemon):
|
syslog, daemon):
|
||||||
@ -255,63 +316,10 @@ def _main(listener, fw, ssh_cmd, remotename, python, latency_control,
|
|||||||
fw.sethostip(name, ip)
|
fw.sethostip(name, ip)
|
||||||
mux.got_host_list = onhostlist
|
mux.got_host_list = onhostlist
|
||||||
|
|
||||||
def onaccept():
|
handlers.append(Handler([listener], lambda: onaccept(listener, mux, handlers)))
|
||||||
global _extra_fd
|
|
||||||
try:
|
|
||||||
sock,srcip = listener.accept()
|
|
||||||
except socket.error, e:
|
|
||||||
if e.args[0] in [errno.EMFILE, errno.ENFILE]:
|
|
||||||
debug1('Rejected incoming connection: too many open files!\n')
|
|
||||||
# free up an fd so we can eat the connection
|
|
||||||
os.close(_extra_fd)
|
|
||||||
try:
|
|
||||||
sock,srcip = listener.accept()
|
|
||||||
sock.close()
|
|
||||||
finally:
|
|
||||||
_extra_fd = os.open('/dev/null', os.O_RDONLY)
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
dstip = original_dst(sock)
|
|
||||||
debug1('Accept: %s:%r -> %s:%r.\n' % (srcip[0],srcip[1],
|
|
||||||
dstip[0],dstip[1]))
|
|
||||||
if dstip[1] == listener.getsockname()[1] and islocal(dstip[0]):
|
|
||||||
debug1("-- ignored: that's my address!\n")
|
|
||||||
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))
|
|
||||||
handlers.append(Handler([listener], onaccept))
|
|
||||||
|
|
||||||
dnsreqs = {}
|
|
||||||
def dns_done(chan, data):
|
|
||||||
peer,timeout = dnsreqs.get(chan) or (None,None)
|
|
||||||
debug3('dns_done: channel=%r peer=%r\n' % (chan, peer))
|
|
||||||
if peer:
|
|
||||||
del dnsreqs[chan]
|
|
||||||
debug3('doing sendto %r\n' % (peer,))
|
|
||||||
dnslistener.sendto(data, peer)
|
|
||||||
def ondns():
|
|
||||||
pkt,peer = dnslistener.recvfrom(4096)
|
|
||||||
now = time.time()
|
|
||||||
if pkt:
|
|
||||||
debug1('DNS request from %r: %d bytes\n' % (peer, len(pkt)))
|
|
||||||
chan = mux.next_channel()
|
|
||||||
dnsreqs[chan] = peer,now+30
|
|
||||||
mux.send(chan, ssnet.CMD_DNS_REQ, pkt)
|
|
||||||
mux.channels[chan] = lambda cmd,data: dns_done(chan,data)
|
|
||||||
for chan,(peer,timeout) in dnsreqs.items():
|
|
||||||
if timeout < now:
|
|
||||||
del dnsreqs[chan]
|
|
||||||
debug3('Remaining DNS requests: %d\n' % len(dnsreqs))
|
|
||||||
if dnslistener:
|
if dnslistener:
|
||||||
handlers.append(Handler([dnslistener], ondns))
|
handlers.append(Handler([dnslistener], lambda: ondns(dnslistener, mux, handlers)))
|
||||||
|
|
||||||
if seed_hosts != None:
|
if seed_hosts != None:
|
||||||
debug1('seed_hosts: %r\n' % seed_hosts)
|
debug1('seed_hosts: %r\n' % seed_hosts)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import re, errno, socket, select, struct
|
import re, errno, socket, select, signal, struct
|
||||||
import compat.ssubprocess as ssubprocess
|
import compat.ssubprocess as ssubprocess
|
||||||
import helpers, ssyslog
|
import helpers, ssyslog
|
||||||
from helpers import *
|
from helpers import *
|
||||||
@ -6,6 +6,12 @@ from helpers import *
|
|||||||
# python doesn't have a definition for this
|
# python doesn't have a definition for this
|
||||||
IPPROTO_DIVERT = 254
|
IPPROTO_DIVERT = 254
|
||||||
|
|
||||||
|
# return values from sysctl_set
|
||||||
|
SUCCESS = 0
|
||||||
|
SAME = 1
|
||||||
|
FAILED = -1
|
||||||
|
NONEXIST = -2
|
||||||
|
|
||||||
|
|
||||||
def nonfatal(func, *args):
|
def nonfatal(func, *args):
|
||||||
try:
|
try:
|
||||||
@ -14,6 +20,14 @@ def nonfatal(func, *args):
|
|||||||
log('error: %s\n' % e)
|
log('error: %s\n' % e)
|
||||||
|
|
||||||
|
|
||||||
|
def _call(argv):
|
||||||
|
debug1('>> %s\n' % ' '.join(argv))
|
||||||
|
rv = ssubprocess.call(argv)
|
||||||
|
if rv:
|
||||||
|
raise Fatal('%r returned %d' % (argv, rv))
|
||||||
|
return rv
|
||||||
|
|
||||||
|
|
||||||
def ipt_chain_exists(name):
|
def ipt_chain_exists(name):
|
||||||
argv = ['iptables', '-t', 'nat', '-nL']
|
argv = ['iptables', '-t', 'nat', '-nL']
|
||||||
p = ssubprocess.Popen(argv, stdout = ssubprocess.PIPE)
|
p = ssubprocess.Popen(argv, stdout = ssubprocess.PIPE)
|
||||||
@ -27,10 +41,7 @@ def ipt_chain_exists(name):
|
|||||||
|
|
||||||
def ipt(*args):
|
def ipt(*args):
|
||||||
argv = ['iptables', '-t', 'nat'] + list(args)
|
argv = ['iptables', '-t', 'nat'] + list(args)
|
||||||
debug1('>> %s\n' % ' '.join(argv))
|
_call(argv)
|
||||||
rv = ssubprocess.call(argv)
|
|
||||||
if rv:
|
|
||||||
raise Fatal('%r returned %d' % (argv, rv))
|
|
||||||
|
|
||||||
|
|
||||||
_no_ttl_module = False
|
_no_ttl_module = False
|
||||||
@ -135,6 +146,42 @@ def _fill_oldctls(prefix):
|
|||||||
raise Fatal('%r returned no data' % (argv,))
|
raise Fatal('%r returned no data' % (argv,))
|
||||||
|
|
||||||
|
|
||||||
|
KERNEL_FLAGS_PATH = '/Library/Preferences/SystemConfiguration/com.apple.Boot'
|
||||||
|
KERNEL_FLAGS_NAME = 'Kernel Flags'
|
||||||
|
def _defaults_read_kernel_flags():
|
||||||
|
argv = ['defaults', 'read', KERNEL_FLAGS_PATH, KERNEL_FLAGS_NAME]
|
||||||
|
debug1('>> %s\n' % ' '.join(argv))
|
||||||
|
p = ssubprocess.Popen(argv, stdout = ssubprocess.PIPE)
|
||||||
|
flagstr = p.stdout.read().strip()
|
||||||
|
rv = p.wait()
|
||||||
|
if rv:
|
||||||
|
raise Fatal('%r returned %d' % (argv, rv))
|
||||||
|
flags = flagstr and flagstr.split(' ') or []
|
||||||
|
return flags
|
||||||
|
|
||||||
|
|
||||||
|
def _defaults_write_kernel_flags(flags):
|
||||||
|
flagstr = ' '.join(flags)
|
||||||
|
argv = ['defaults', 'write', KERNEL_FLAGS_PATH, KERNEL_FLAGS_NAME,
|
||||||
|
flagstr]
|
||||||
|
_call(argv)
|
||||||
|
argv = ['plutil', '-convert', 'xml1', KERNEL_FLAGS_PATH + '.plist']
|
||||||
|
_call(argv)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def defaults_write_kernel_flag(name, val):
|
||||||
|
flags = _defaults_read_kernel_flags()
|
||||||
|
found = 0
|
||||||
|
for i in range(len(flags)):
|
||||||
|
if flags[i].startswith('%s=' % name):
|
||||||
|
found += 1
|
||||||
|
flags[i] = '%s=%s' % (name, val)
|
||||||
|
if not found:
|
||||||
|
flags.insert(0, '%s=%s' % (name, val))
|
||||||
|
_defaults_write_kernel_flags(flags)
|
||||||
|
|
||||||
|
|
||||||
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))
|
||||||
@ -150,20 +197,24 @@ def sysctl_set(name, val, permanent=False):
|
|||||||
_fill_oldctls(PREFIX)
|
_fill_oldctls(PREFIX)
|
||||||
if not (name in _oldctls):
|
if not (name in _oldctls):
|
||||||
debug1('>> No such sysctl: %r\n' % name)
|
debug1('>> No such sysctl: %r\n' % name)
|
||||||
return False
|
return NONEXIST
|
||||||
oldval = _oldctls[name]
|
oldval = _oldctls[name]
|
||||||
if val != oldval:
|
if val == oldval:
|
||||||
rv = _sysctl_set(name, val)
|
return SAME
|
||||||
if rv==0 and permanent:
|
|
||||||
debug1('>> ...saving permanently in /etc/sysctl.conf\n')
|
rv = _sysctl_set(name, val)
|
||||||
f = open('/etc/sysctl.conf', 'a')
|
if rv != 0:
|
||||||
f.write('\n'
|
return FAILED
|
||||||
'# Added by sshuttle\n'
|
if permanent:
|
||||||
'%s=%s\n' % (name, val))
|
debug1('>> ...saving permanently in /etc/sysctl.conf\n')
|
||||||
f.close()
|
f = open('/etc/sysctl.conf', 'a')
|
||||||
else:
|
f.write('\n'
|
||||||
_changedctls.append(name)
|
'# Added by sshuttle\n'
|
||||||
return True
|
'%s=%s\n' % (name, val))
|
||||||
|
f.close()
|
||||||
|
else:
|
||||||
|
_changedctls.append(name)
|
||||||
|
return SUCCESS
|
||||||
|
|
||||||
|
|
||||||
def _udp_unpack(p):
|
def _udp_unpack(p):
|
||||||
@ -201,10 +252,7 @@ def _handle_diversion(divertsock, dnsport):
|
|||||||
|
|
||||||
def ipfw(*args):
|
def ipfw(*args):
|
||||||
argv = ['ipfw', '-q'] + list(args)
|
argv = ['ipfw', '-q'] + list(args)
|
||||||
debug1('>> %s\n' % ' '.join(argv))
|
_call(argv)
|
||||||
rv = ssubprocess.call(argv)
|
|
||||||
if rv:
|
|
||||||
raise Fatal('%r returned %d' % (argv, rv))
|
|
||||||
|
|
||||||
|
|
||||||
def do_ipfw(port, dnsport, subnets):
|
def do_ipfw(port, dnsport, subnets):
|
||||||
@ -222,8 +270,14 @@ 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)
|
||||||
changed = sysctl_set('net.inet.ip.scopedroute', 0, permanent=True)
|
|
||||||
if changed:
|
# This seems to be needed on MacOS 10.6 and 10.7. For more
|
||||||
|
# information, see:
|
||||||
|
# http://groups.google.com/group/sshuttle/browse_thread/thread/bc32562e17987b25/6d3aa2bb30a1edab
|
||||||
|
# and
|
||||||
|
# http://serverfault.com/questions/138622/transparent-proxying-leaves-sockets-with-syn-rcvd-in-macos-x-10-6-snow-leopard
|
||||||
|
changeflag = sysctl_set('net.inet.ip.scopedroute', 0, permanent=True)
|
||||||
|
if changeflag == SUCCESS:
|
||||||
log("\n"
|
log("\n"
|
||||||
" WARNING: ONE-TIME NETWORK DISRUPTION:\n"
|
" WARNING: ONE-TIME NETWORK DISRUPTION:\n"
|
||||||
" =====================================\n"
|
" =====================================\n"
|
||||||
@ -234,6 +288,21 @@ def do_ipfw(port, dnsport, subnets):
|
|||||||
"ethernet port) NOW, then restart sshuttle. The fix is\n"
|
"ethernet port) NOW, then restart sshuttle. The fix is\n"
|
||||||
"permanent; you only have to do this once.\n\n")
|
"permanent; you only have to do this once.\n\n")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
elif changeflag == FAILED:
|
||||||
|
# On MacOS 10.7, the scopedroute sysctl became read-only, so
|
||||||
|
# we have to fix it using a kernel boot parameter instead,
|
||||||
|
# which requires rebooting. For more, see:
|
||||||
|
# http://groups.google.com/group/sshuttle/browse_thread/thread/a42505ca33e1de80/e5e8f3e5a92d25f7
|
||||||
|
log('Updating kernel boot flags.\n')
|
||||||
|
defaults_write_kernel_flag('net.inet.ip.scopedroute', 0)
|
||||||
|
log("\n"
|
||||||
|
" YOU MUST REBOOT TO USE SSHUTTLE\n"
|
||||||
|
" ===============================\n"
|
||||||
|
"sshuttle has changed a MacOS kernel boot-time setting\n"
|
||||||
|
"to work around a bug in MacOS 10.7 Lion. You will need\n"
|
||||||
|
"to reboot before it takes effect. You only have to\n"
|
||||||
|
"do this once.\n\n")
|
||||||
|
sys.exit(EXITCODE_NEEDS_REBOOT)
|
||||||
|
|
||||||
ipfw('add', sport, 'check-state', 'ip',
|
ipfw('add', sport, 'check-state', 'ip',
|
||||||
'from', 'any', 'to', 'any')
|
'from', 'any', 'to', 'any')
|
||||||
@ -243,11 +312,11 @@ def do_ipfw(port, dnsport, subnets):
|
|||||||
for swidth,sexclude,snet in sorted(subnets, reverse=True):
|
for swidth,sexclude,snet in sorted(subnets, reverse=True):
|
||||||
if sexclude:
|
if sexclude:
|
||||||
ipfw('add', sport, 'skipto', xsport,
|
ipfw('add', sport, 'skipto', xsport,
|
||||||
'log', 'tcp',
|
'tcp',
|
||||||
'from', 'any', 'to', '%s/%s' % (snet,swidth))
|
'from', 'any', 'to', '%s/%s' % (snet,swidth))
|
||||||
else:
|
else:
|
||||||
ipfw('add', sport, 'fwd', '127.0.0.1,%d' % port,
|
ipfw('add', sport, 'fwd', '127.0.0.1,%d' % port,
|
||||||
'log', 'tcp',
|
'tcp',
|
||||||
'from', 'any', 'to', '%s/%s' % (snet,swidth),
|
'from', 'any', 'to', '%s/%s' % (snet,swidth),
|
||||||
'not', 'ipttl', '42', 'keep-state', 'setup')
|
'not', 'ipttl', '42', 'keep-state', 'setup')
|
||||||
|
|
||||||
@ -289,12 +358,12 @@ def do_ipfw(port, dnsport, subnets):
|
|||||||
for ip in nslist:
|
for ip in nslist:
|
||||||
# relabel and then catch outgoing DNS requests
|
# relabel and then catch outgoing DNS requests
|
||||||
ipfw('add', sport, 'divert', sport,
|
ipfw('add', sport, 'divert', sport,
|
||||||
'log', 'udp',
|
'udp',
|
||||||
'from', 'any', 'to', '%s/32' % ip, '53',
|
'from', 'any', 'to', '%s/32' % ip, '53',
|
||||||
'not', 'ipttl', '42')
|
'not', 'ipttl', '42')
|
||||||
# relabel DNS responses
|
# relabel DNS responses
|
||||||
ipfw('add', sport, 'divert', sport,
|
ipfw('add', sport, 'divert', sport,
|
||||||
'log', 'udp',
|
'udp',
|
||||||
'from', 'any', str(dnsport), 'to', 'any',
|
'from', 'any', str(dnsport), 'to', 'any',
|
||||||
'not', 'ipttl', '42')
|
'not', 'ipttl', '42')
|
||||||
|
|
||||||
@ -398,6 +467,11 @@ def main(port, dnsport, syslog):
|
|||||||
sys.stdout.write('READY\n')
|
sys.stdout.write('READY\n')
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
# don't disappear if our controlling terminal or stdout/stderr
|
||||||
|
# disappears; we still have to clean up.
|
||||||
|
signal.signal(signal.SIGHUP, signal.SIG_IGN)
|
||||||
|
signal.signal(signal.SIGPIPE, signal.SIG_IGN)
|
||||||
|
|
||||||
# ctrl-c shouldn't be passed along to me. When the main sshuttle dies,
|
# ctrl-c shouldn't be passed along to me. When the main sshuttle dies,
|
||||||
# I'll die automatically.
|
# I'll die automatically.
|
||||||
os.setsid()
|
os.setsid()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import sys, os, socket
|
import sys, os, socket, errno
|
||||||
|
|
||||||
logprefix = ''
|
logprefix = ''
|
||||||
verbose = 0
|
verbose = 0
|
||||||
@ -30,6 +30,11 @@ class Fatal(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
EXITCODE_NEEDS_REBOOT = 111
|
||||||
|
class FatalNeedsReboot(Fatal):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def list_contains_any(l, sub):
|
def list_contains_any(l, sub):
|
||||||
for i in sub:
|
for i in sub:
|
||||||
if i in l:
|
if i in l:
|
||||||
|
8
Sshuttle VPN.app/Contents/Resources/sshuttle/main.py
Normal file → Executable file
8
Sshuttle VPN.app/Contents/Resources/sshuttle/main.py
Normal file → Executable file
@ -63,6 +63,7 @@ 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)
|
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
|
||||||
|
V,version print sshuttle's version number
|
||||||
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]
|
||||||
server (internal use only)
|
server (internal use only)
|
||||||
@ -72,6 +73,10 @@ hostwatch (internal use only)
|
|||||||
o = options.Options(optspec)
|
o = options.Options(optspec)
|
||||||
(opt, flags, extra) = o.parse(sys.argv[2:])
|
(opt, flags, extra) = o.parse(sys.argv[2:])
|
||||||
|
|
||||||
|
if opt.version:
|
||||||
|
import version
|
||||||
|
print version.TAG
|
||||||
|
sys.exit(0)
|
||||||
if opt.daemon:
|
if opt.daemon:
|
||||||
opt.syslog = 1
|
opt.syslog = 1
|
||||||
if opt.wrap:
|
if opt.wrap:
|
||||||
@ -121,6 +126,9 @@ try:
|
|||||||
parse_subnets(includes),
|
parse_subnets(includes),
|
||||||
parse_subnets(excludes),
|
parse_subnets(excludes),
|
||||||
opt.syslog, opt.daemon, opt.pidfile))
|
opt.syslog, opt.daemon, opt.pidfile))
|
||||||
|
except FatalNeedsReboot, e:
|
||||||
|
log('You must reboot before using sshuttle.\n')
|
||||||
|
sys.exit(EXITCODE_NEEDS_REBOOT)
|
||||||
except Fatal, e:
|
except Fatal, e:
|
||||||
log('fatal: %s\n' % e)
|
log('fatal: %s\n' % e)
|
||||||
sys.exit(99)
|
sys.exit(99)
|
||||||
|
@ -152,6 +152,17 @@ class SockWrapper:
|
|||||||
debug3('%r: fixed connect result: %s\n' % (self, e))
|
debug3('%r: fixed connect result: %s\n' % (self, e))
|
||||||
if e.args[0] in [errno.EINPROGRESS, errno.EALREADY]:
|
if e.args[0] in [errno.EINPROGRESS, errno.EALREADY]:
|
||||||
pass # not connected yet
|
pass # not connected yet
|
||||||
|
elif e.args[0] == 0:
|
||||||
|
# connected successfully (weird Linux bug?)
|
||||||
|
# Sometimes Linux seems to return EINVAL when it isn't
|
||||||
|
# invalid. This *may* be caused by a race condition
|
||||||
|
# between connect() and getsockopt(SO_ERROR) (ie. it
|
||||||
|
# finishes connecting in between the two, so there is no
|
||||||
|
# longer an error). However, I'm not sure of that.
|
||||||
|
#
|
||||||
|
# I did get at least one report that the problem went away
|
||||||
|
# when we added this, however.
|
||||||
|
self.connect_to = None
|
||||||
elif e.args[0] == errno.EISCONN:
|
elif e.args[0] == errno.EISCONN:
|
||||||
# connected successfully (BSD)
|
# connected successfully (BSD)
|
||||||
self.connect_to = None
|
self.connect_to = None
|
||||||
|
Loading…
x
Reference in New Issue
Block a user