mirror of
https://github.com/sshuttle/sshuttle.git
synced 2025-05-10 11:05:03 +02:00
MacOS precompiled app package for sshuttle-0.52
This commit is contained in:
parent
cd15e2eda6
commit
cde9521825
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -102,7 +102,7 @@ class FirewallClient:
|
|||||||
self.subnets_include = subnets_include
|
self.subnets_include = subnets_include
|
||||||
self.subnets_exclude = subnets_exclude
|
self.subnets_exclude = subnets_exclude
|
||||||
self.dnsport = dnsport
|
self.dnsport = dnsport
|
||||||
argvbase = ([sys.argv[0]] +
|
argvbase = ([sys.argv[1], sys.argv[0], sys.argv[1]] +
|
||||||
['-v'] * (helpers.verbose or 0) +
|
['-v'] * (helpers.verbose or 0) +
|
||||||
['--firewall', str(port), str(dnsport)])
|
['--firewall', str(port), str(dnsport)])
|
||||||
if ssyslog._p:
|
if ssyslog._p:
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -7,6 +7,13 @@ from helpers import *
|
|||||||
IPPROTO_DIVERT = 254
|
IPPROTO_DIVERT = 254
|
||||||
|
|
||||||
|
|
||||||
|
def nonfatal(func, *args):
|
||||||
|
try:
|
||||||
|
func(*args)
|
||||||
|
except Fatal, e:
|
||||||
|
log('error: %s\n' % e)
|
||||||
|
|
||||||
|
|
||||||
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)
|
||||||
@ -57,9 +64,9 @@ def do_iptables(port, dnsport, subnets):
|
|||||||
|
|
||||||
# basic cleanup/setup of chains
|
# basic cleanup/setup of chains
|
||||||
if ipt_chain_exists(chain):
|
if ipt_chain_exists(chain):
|
||||||
ipt('-D', 'OUTPUT', '-j', chain)
|
nonfatal(ipt, '-D', 'OUTPUT', '-j', chain)
|
||||||
ipt('-D', 'PREROUTING', '-j', chain)
|
nonfatal(ipt, '-D', 'PREROUTING', '-j', chain)
|
||||||
ipt('-F', chain)
|
nonfatal(ipt, '-F', chain)
|
||||||
ipt('-X', chain)
|
ipt('-X', chain)
|
||||||
|
|
||||||
if subnets or dnsport:
|
if subnets or dnsport:
|
||||||
@ -143,7 +150,7 @@ 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
|
return False
|
||||||
oldval = _oldctls[name]
|
oldval = _oldctls[name]
|
||||||
if val != oldval:
|
if val != oldval:
|
||||||
rv = _sysctl_set(name, val)
|
rv = _sysctl_set(name, val)
|
||||||
@ -156,6 +163,7 @@ def sysctl_set(name, val, permanent=False):
|
|||||||
f.close()
|
f.close()
|
||||||
else:
|
else:
|
||||||
_changedctls.append(name)
|
_changedctls.append(name)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def _udp_unpack(p):
|
def _udp_unpack(p):
|
||||||
@ -214,7 +222,18 @@ 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, permanent=True)
|
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',
|
ipfw('add', sport, 'check-state', 'ip',
|
||||||
'from', 'any', 'to', 'any')
|
'from', 'any', 'to', 'any')
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -13,7 +13,11 @@ _nmb_ok = True
|
|||||||
_smb_ok = True
|
_smb_ok = True
|
||||||
hostnames = {}
|
hostnames = {}
|
||||||
queue = {}
|
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):
|
def _is_ip(s):
|
||||||
|
Binary file not shown.
5
Sshuttle VPN.app/Contents/Resources/sshuttle/main.py
Executable file → Normal file
5
Sshuttle VPN.app/Contents/Resources/sshuttle/main.py
Executable file → Normal file
@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import sys, os, re
|
import sys, os, re
|
||||||
import helpers, options, client, server, firewall, hostwatch
|
import helpers, options, client, server, firewall, hostwatch
|
||||||
import compat.ssubprocess as ssubprocess
|
import compat.ssubprocess as ssubprocess
|
||||||
@ -55,7 +54,7 @@ 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
|
H,auto-hosts scan for remote hostnames and update local /etc/hosts
|
||||||
N,auto-nets automatically determine subnets to route
|
N,auto-nets automatically determine subnets to route
|
||||||
dns capture local DNS requests and forward to the remote DNS server
|
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
|
r,remote= ssh hostname (and optional username) of remote sshuttle server
|
||||||
x,exclude= exclude this subnet (can be used more than once)
|
x,exclude= exclude this subnet (can be used more than once)
|
||||||
v,verbose increase debug message verbosity
|
v,verbose increase debug message verbosity
|
||||||
@ -71,7 +70,7 @@ firewall (internal use only)
|
|||||||
hostwatch (internal use only)
|
hostwatch (internal use only)
|
||||||
"""
|
"""
|
||||||
o = options.Options(optspec)
|
o = options.Options(optspec)
|
||||||
(opt, flags, extra) = o.parse(sys.argv[1:])
|
(opt, flags, extra) = o.parse(sys.argv[2:])
|
||||||
|
|
||||||
if opt.daemon:
|
if opt.daemon:
|
||||||
opt.syslog = 1
|
opt.syslog = 1
|
||||||
|
Binary file not shown.
@ -119,7 +119,14 @@ class DnsProxy(Handler):
|
|||||||
self.sock.send(request)
|
self.sock.send(request)
|
||||||
|
|
||||||
def callback(self):
|
def callback(self):
|
||||||
data = self.sock.recv(4096)
|
try:
|
||||||
|
data = self.sock.recv(4096)
|
||||||
|
except socket.error, e:
|
||||||
|
if e.args[0] == errno.ECONNREFUSED:
|
||||||
|
debug2('DNS response: ignoring ECONNREFUSED.\n')
|
||||||
|
return # might have been spurious; wait for a real answer
|
||||||
|
else:
|
||||||
|
raise
|
||||||
debug2('DNS response: %d bytes\n' % len(data))
|
debug2('DNS response: %d bytes\n' % len(data))
|
||||||
self.mux.send(self.chan, ssnet.CMD_DNS_RESPONSE, data)
|
self.mux.send(self.chan, ssnet.CMD_DNS_RESPONSE, data)
|
||||||
self.ok = False
|
self.ok = False
|
||||||
|
Binary file not shown.
@ -73,16 +73,23 @@ def connect(ssh_cmd, rhostport, python, stderr, options):
|
|||||||
|
|
||||||
|
|
||||||
if not rhost:
|
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:
|
else:
|
||||||
if ssh_cmd:
|
if ssh_cmd:
|
||||||
sshl = ssh_cmd.split(' ')
|
sshl = ssh_cmd.split(' ')
|
||||||
else:
|
else:
|
||||||
sshl = ['ssh']
|
sshl = ['ssh']
|
||||||
|
if python:
|
||||||
|
pycmd = "'%s' -c '%s'" % (python, pyscript)
|
||||||
|
else:
|
||||||
|
pycmd = ("P=python2; $P -V 2>/dev/null || P=python; "
|
||||||
|
"\"$P\" -c '%s'") % pyscript
|
||||||
argv = (sshl +
|
argv = (sshl +
|
||||||
portl +
|
portl +
|
||||||
ipv6flag +
|
ipv6flag +
|
||||||
[rhost, '--', "'%s' -c '%s'" % (python, pyscript)])
|
[rhost, '--', pycmd])
|
||||||
(s1,s2) = socket.socketpair()
|
(s1,s2) = socket.socketpair()
|
||||||
def setup():
|
def setup():
|
||||||
# runs in the child process
|
# runs in the child process
|
||||||
|
Binary file not shown.
@ -1,131 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/bin/sh
|
||||||
import sys, os, re
|
DIR=$(dirname "$0")
|
||||||
import helpers, options, client, server, firewall, hostwatch
|
if python2 -V 2>/dev/null; then
|
||||||
import compat.ssubprocess as ssubprocess
|
exec python2 "$DIR/main.py" python2 "$@"
|
||||||
from helpers import *
|
else
|
||||||
|
exec python "$DIR/main.py" python "$@"
|
||||||
|
fi
|
||||||
# list of:
|
|
||||||
# 1.2.3.4/5 or just 1.2.3.4
|
|
||||||
def parse_subnets(subnets_str):
|
|
||||||
subnets = []
|
|
||||||
for s in subnets_str:
|
|
||||||
m = re.match(r'(\d+)(?:\.(\d+)\.(\d+)\.(\d+))?(?:/(\d+))?$', s)
|
|
||||||
if not m:
|
|
||||||
raise Fatal('%r is not a valid IP subnet format' % s)
|
|
||||||
(a,b,c,d,width) = m.groups()
|
|
||||||
(a,b,c,d) = (int(a or 0), int(b or 0), int(c or 0), int(d or 0))
|
|
||||||
if width == None:
|
|
||||||
width = 32
|
|
||||||
else:
|
|
||||||
width = int(width)
|
|
||||||
if a > 255 or b > 255 or c > 255 or d > 255:
|
|
||||||
raise Fatal('%d.%d.%d.%d has numbers > 255' % (a,b,c,d))
|
|
||||||
if width > 32:
|
|
||||||
raise Fatal('*/%d is greater than the maximum of 32' % width)
|
|
||||||
subnets.append(('%d.%d.%d.%d' % (a,b,c,d), width))
|
|
||||||
return subnets
|
|
||||||
|
|
||||||
|
|
||||||
# 1.2.3.4:567 or just 1.2.3.4 or just 567
|
|
||||||
def parse_ipport(s):
|
|
||||||
s = str(s)
|
|
||||||
m = re.match(r'(?:(\d+)\.(\d+)\.(\d+)\.(\d+))?(?::)?(?:(\d+))?$', s)
|
|
||||||
if not m:
|
|
||||||
raise Fatal('%r is not a valid IP:port format' % s)
|
|
||||||
(a,b,c,d,port) = m.groups()
|
|
||||||
(a,b,c,d,port) = (int(a or 0), int(b or 0), int(c or 0), int(d or 0),
|
|
||||||
int(port or 0))
|
|
||||||
if a > 255 or b > 255 or c > 255 or d > 255:
|
|
||||||
raise Fatal('%d.%d.%d.%d has numbers > 255' % (a,b,c,d))
|
|
||||||
if port > 65535:
|
|
||||||
raise Fatal('*:%d is greater than the maximum of 65535' % port)
|
|
||||||
if a == None:
|
|
||||||
a = b = c = d = 0
|
|
||||||
return ('%d.%d.%d.%d' % (a,b,c,d), port)
|
|
||||||
|
|
||||||
|
|
||||||
optspec = """
|
|
||||||
sshuttle [-l [ip:]port] [-r [username@]sshserver[:port]] <subnets...>
|
|
||||||
sshuttle --server
|
|
||||||
sshuttle --firewall <port> <subnets...>
|
|
||||||
sshuttle --hostwatch
|
|
||||||
--
|
|
||||||
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]
|
|
||||||
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]
|
|
||||||
server (internal use only)
|
|
||||||
firewall (internal use only)
|
|
||||||
hostwatch (internal use only)
|
|
||||||
"""
|
|
||||||
o = options.Options(optspec)
|
|
||||||
(opt, flags, extra) = o.parse(sys.argv[1:])
|
|
||||||
|
|
||||||
if opt.daemon:
|
|
||||||
opt.syslog = 1
|
|
||||||
if opt.wrap:
|
|
||||||
import ssnet
|
|
||||||
ssnet.MAX_CHANNEL = int(opt.wrap)
|
|
||||||
helpers.verbose = opt.verbose
|
|
||||||
|
|
||||||
try:
|
|
||||||
if opt.server:
|
|
||||||
if len(extra) != 0:
|
|
||||||
o.fatal('no arguments expected')
|
|
||||||
server.latency_control = opt.latency_control
|
|
||||||
sys.exit(server.main())
|
|
||||||
elif opt.firewall:
|
|
||||||
if len(extra) != 2:
|
|
||||||
o.fatal('exactly two arguments expected')
|
|
||||||
sys.exit(firewall.main(int(extra[0]), int(extra[1]), opt.syslog))
|
|
||||||
elif opt.hostwatch:
|
|
||||||
sys.exit(hostwatch.hw_main(extra))
|
|
||||||
else:
|
|
||||||
if len(extra) < 1 and not opt.auto_nets:
|
|
||||||
o.fatal('at least one subnet (or -N) expected')
|
|
||||||
includes = extra
|
|
||||||
excludes = ['127.0.0.0/8']
|
|
||||||
for k,v in flags:
|
|
||||||
if k in ('-x','--exclude'):
|
|
||||||
excludes.append(v)
|
|
||||||
remotename = opt.remote
|
|
||||||
if remotename == '' or remotename == '-':
|
|
||||||
remotename = None
|
|
||||||
if opt.seed_hosts and not opt.auto_hosts:
|
|
||||||
o.fatal('--seed-hosts only works if you also use -H')
|
|
||||||
if opt.seed_hosts:
|
|
||||||
sh = re.split(r'[\s,]+', (opt.seed_hosts or "").strip())
|
|
||||||
elif opt.auto_hosts:
|
|
||||||
sh = []
|
|
||||||
else:
|
|
||||||
sh = None
|
|
||||||
sys.exit(client.main(parse_ipport(opt.listen or '0.0.0.0:0'),
|
|
||||||
opt.ssh_cmd,
|
|
||||||
remotename,
|
|
||||||
opt.python,
|
|
||||||
opt.latency_control,
|
|
||||||
opt.dns,
|
|
||||||
sh,
|
|
||||||
opt.auto_nets,
|
|
||||||
parse_subnets(includes),
|
|
||||||
parse_subnets(excludes),
|
|
||||||
opt.syslog, opt.daemon, opt.pidfile))
|
|
||||||
except Fatal, e:
|
|
||||||
log('fatal: %s\n' % e)
|
|
||||||
sys.exit(99)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
log('\n')
|
|
||||||
log('Keyboard interrupt: exiting.\n')
|
|
||||||
sys.exit(1)
|
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/env python
|
||||||
import sys, os, socket, select, struct, time
|
import sys, os, socket, select, struct, time
|
||||||
|
|
||||||
listener = socket.socket()
|
listener = socket.socket()
|
||||||
|
Loading…
Reference in New Issue
Block a user