Restructure code

* Make compatible with setuptools.
* Load modules via ssh into separate modules, not the one name space.
This commit is contained in:
Brian May 2015-11-15 16:45:26 +11:00
parent 41b8ad4c97
commit d4f10b232a
55 changed files with 214 additions and 316 deletions

5
MANIFEST.in Normal file
View File

@ -0,0 +1,5 @@
include *.txt
include *.rst
include *.py
include MANIFEST.in
recursive-include sshuttle *.py

View File

@ -1,28 +1,3 @@
WARNING:
On MacOS 10.6 (at least up to 10.6.6), your network will
stop responding about 10 minutes after the first time you
start sshuttle, because of a MacOS kernel bug relating to
arp and the net.inet.ip.scopedroute sysctl. To fix it,
just switch your wireless off and on. Sshuttle makes the
kernel setting it changes permanent, so this won't happen
again, even after a reboot.
Required Software
=================
- You need PyXAPI, available here:
http://www.pps.univ-paris-diderot.fr/~ylg/PyXAPI/
- Python 2.x, both locally and the remote system
Additional Suggested Software
-----------------------------
- You may want to need autossh, available in various package management
systems
sshuttle: where transparent proxy meets VPN meets ssh sshuttle: where transparent proxy meets VPN meets ssh
===================================================== =====================================================
@ -70,38 +45,57 @@ Prerequisites
available. (The server doesn't need to be MacOS or BSD.) available. (The server doesn't need to be MacOS or BSD.)
- Python 2.x, both locally and the remote system. Python 3.x is not yet supported.
*WARNING*:
On MacOS 10.6 (at least up to 10.6.6), your network will
stop responding about 10 minutes after the first time you
start sshuttle, because of a MacOS kernel bug relating to
arp and the net.inet.ip.scopedroute sysctl. To fix it,
just switch your wireless off and on. Sshuttle makes the
kernel setting it changes permanent, so this won't happen
again, even after a reboot.
Additional Suggested Software
-----------------------------
- You may want to need autossh, available in various package management
systems
- For Linux only tproxy support, you need PyXAPI, available here:
http://www.pps.univ-paris-diderot.fr/~ylg/PyXAPI/
Obtaining sshuttle Obtaining sshuttle
------------------ ------------------
- First, go get PyXAPI from the link above - Clone::
- Clone: `git clone https://github.com/sshuttle/sshuttle.git` git clone https://github.com/sshuttle/sshuttle.git
./setup.py install
- From PyPI::
pip install sshuttle
Usage on (Ubuntu) Linux Usage
----------------------- -----
- `cd packaging; ./make_deb` - Forward all traffic::
- `sudo dpkg -i ./sshuttle-VERSION.deb` sshuttle -r username@sshserver 0.0.0.0/0 -vv
- Check out the files in `/etc/sshuttle`; configure them so your tunnel works
- `sudo service sshuttle start`
Usage on other Linuxes and OSes
-------------------------------
<tt>src/sshuttle -r username@sshserver 0.0.0.0/0 -vv</tt>
- There is a shortcut for 0.0.0.0/0 for those that value - There is a shortcut for 0.0.0.0/0 for those that value
their wrists their wrists::
<tt>src/sshuttle -r username@sshserver 0/0 -vv</tt>
sshuttle -r username@sshserver 0/0 -vv
- If you would also like your DNS queries to be proxied - If you would also like your DNS queries to be proxied
through the DNS server of the server you are connect to: through the DNS server of the server you are connect to::
<tt>src/sshuttle --dns -vvr username@sshserver 0/0</tt>
sshuttle --dns -vvr username@sshserver 0/0
The above is probably what you want to use to prevent The above is probably what you want to use to prevent
local network attacks such as Firesheep and friends. local network attacks such as Firesheep and friends.
@ -112,6 +106,7 @@ then the remote ssh password. Or you might have sudo and ssh set
up to not require passwords, in which case you won't be up to not require passwords, in which case you won't be
prompted at all.) prompted at all.)
Usage Notes Usage Notes
----------- -----------
@ -127,7 +122,7 @@ to the remote python interpreter.
This creates a transparent proxy server on your local machine for all IP This creates a transparent proxy server on your local machine for all IP
addresses that match 0.0.0.0/0. (You can use more specific IP addresses if addresses that match 0.0.0.0/0. (You can use more specific IP addresses if
you want; use any number of IP addresses or subnets to change which you want; use any number of IP addresses or subnets to change which
addresses get proxied. Using 0.0.0.0/0 proxies <i>everything</i>, which is addresses get proxied. Using 0.0.0.0/0 proxies *everything*, which is
interesting if you don't trust the people on your local network.) interesting if you don't trust the people on your local network.)
Any TCP session you initiate to one of the proxied IP addresses will be Any TCP session you initiate to one of the proxied IP addresses will be
@ -139,6 +134,19 @@ Fun, right? A poor man's instant VPN, and you don't even have to have
admin access on the server. admin access on the server.
Support
-------
Mailing list:
* Subscribe by sending a message to <sshuttle+subscribe@googlegroups.com>
* List archives are at: http://groups.google.com/group/sshuttle
Issue tracker and pull requests at github:
* https://github.com/sshuttle/sshuttle
Theory of Operation Theory of Operation
------------------- -------------------
@ -155,8 +163,7 @@ doesn't care about individual connections; ie. it's "stateless" with respect
to the traffic. sshuttle is the opposite of stateless; it tracks every to the traffic. sshuttle is the opposite of stateless; it tracks every
single connection. single connection.
You could compare sshuttle to something like the old <a You could compare sshuttle to something like the old `Slirp <http://en.wikipedia.org/wiki/Slirp>`_ program, which was a
href="http://en.wikipedia.org/wiki/Slirp">Slirp</a> program, which was a
userspace TCP/IP implementation that did something similar. But it userspace TCP/IP implementation that did something similar. But it
operated on a packet-by-packet basis on the client side, reassembling the operated on a packet-by-packet basis on the client side, reassembling the
packets on the server side. That worked okay back in the "real live serial packets on the server side. That worked okay back in the "real live serial
@ -164,9 +171,9 @@ port" days, because serial ports had predictable latency and buffering.
But you can't safely just forward TCP packets over a TCP session (like ssh), But you can't safely just forward TCP packets over a TCP session (like ssh),
because TCP's performance depends fundamentally on packet loss; it because TCP's performance depends fundamentally on packet loss; it
<i>must</i> experience packet loss in order to know when to slow down! At *must* experience packet loss in order to know when to slow down! At
the same time, the outer TCP session (ssh, in this case) is a reliable the same time, the outer TCP session (ssh, in this case) is a reliable
transport, which means that what you forward through the tunnel <i>never</i> transport, which means that what you forward through the tunnel *never*
experiences packet loss. The ssh session itself experiences packet loss, of experiences packet loss. The ssh session itself experiences packet loss, of
course, but TCP fixes it up and ssh (and thus you) never know the course, but TCP fixes it up and ssh (and thus you) never know the
difference. But neither does your inner TCP session, and extremely screwy difference. But neither does your inner TCP session, and extremely screwy
@ -181,8 +188,7 @@ safe.
Useless Trivia Useless Trivia
-------------- --------------
Back in 1998 (12 years ago! Yikes!), I released the first version of <a Back in 1998 (12 years ago! Yikes!), I released the first version of `Tunnel Vision <http://alumnit.ca/wiki/?TunnelVisionReadMe>`_, a
href="http://alumnit.ca/wiki/?TunnelVisionReadMe">Tunnel Vision</a>, a
semi-intelligent VPN client for Linux. Unfortunately, I made two big mistakes: semi-intelligent VPN client for Linux. Unfortunately, I made two big mistakes:
I implemented the key exchange myself (oops), and I ended up doing I implemented the key exchange myself (oops), and I ended up doing
TCP-over-TCP (double oops). The resulting program worked okay - and people TCP-over-TCP (double oops). The resulting program worked okay - and people
@ -197,8 +203,7 @@ tool we called "Double Vision").
I was still in university at the time. A couple years after that, one of my I was still in university at the time. A couple years after that, one of my
professors was working with some graduate students on the technology that professors was working with some graduate students on the technology that
would eventually become <a href="http://www.slipstream.com/">Slipstream would eventually become `Slipstream Internet Acceleration <http://www.slipstream.com/>`_. He asked me to do a contract for him to build an
Internet Acceleration</a>. He asked me to do a contract for him to build an
initial prototype of a transparent proxy server for mobile networks. The initial prototype of a transparent proxy server for mobile networks. The
idea was similar to sshuttle: if you reassemble and then disassemble the TCP idea was similar to sshuttle: if you reassemble and then disassemble the TCP
packets, you can reduce latency and improve performance vs. just forwarding packets, you can reduce latency and improve performance vs. just forwarding
@ -215,7 +220,3 @@ later. You're welcome.
-- --
Avery Pennarun <apenwarr@gmail.com> Avery Pennarun <apenwarr@gmail.com>
Mailing list:
Subscribe by sending a message to <sshuttle+subscribe@googlegroups.com>
List archives are at: http://groups.google.com/group/sshuttle

1
VERSION.txt Normal file
View File

@ -0,0 +1 @@
0.72

6
run Executable file
View File

@ -0,0 +1,6 @@
#!/bin/sh
if python2 -V 2>/dev/null; then
exec python2 -m "sshuttle" "$@"
else
exec python -m "sshuttle" "$@"
fi

51
setup.py Executable file
View File

@ -0,0 +1,51 @@
#!/usr/bin/env python
# Copyright 2012-2014 Brian May
#
# This file is part of python-tldap.
#
# python-tldap is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# python-tldap is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with python-tldap If not, see <http://www.gnu.org/licenses/>.
from setuptools import setup, find_packages
with open('VERSION.txt', 'r') as f:
version = f.readline().strip()
setup(
name="sshuttle",
version=version,
url='https://github.com/sshuttle/sshuttle',
author='Brian May',
author_email='brian@linuxpenguins.xyz',
description='Transparent proxy server that works as a poor man\'s VPN.',
packages=find_packages(),
license="GPL2+",
long_description=open('README.rst').read(),
classifiers=[
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Intended Audience :: End Users/Desktop",
"License :: OSI Approved :: "
"GNU General Public License v2 or later (GPLv2+)",
"Operating System :: OS Independent",
"Programming Language :: Python :: 2.7",
"Topic :: System :: Networking",
],
entry_points={
'console_scripts': [
'sshuttle = sshuttle.__main__',
],
},
keywords="ssh vpn",
)

View File

@ -1,10 +0,0 @@
all:
Makefile:
@
%: FORCE
+./do $@
.PHONY: FORCE

175
src/do
View File

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

View File

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

View File

@ -3,11 +3,11 @@ import re
import socket import socket
import helpers import helpers
import options import options
import client import sshuttle.client as client
import server import sshuttle.server as server
import firewall import sshuttle.firewall as firewall
import hostwatch import sshuttle.hostwatch as hostwatch
from helpers import family_ip_tuple, log, Fatal from sshuttle.helpers import family_ip_tuple, log, Fatal
# 1.2.3.4/5 or just 1.2.3.4 # 1.2.3.4/5 or just 1.2.3.4
@ -139,7 +139,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[2:]) (opt, flags, extra) = o.parse(sys.argv[1:])
if opt.daemon: if opt.daemon:
opt.syslog = 1 opt.syslog = 1

View File

@ -1,8 +1,8 @@
import sys import sys
import zlib import zlib
import imp
z = zlib.decompressobj() z = zlib.decompressobj()
mainmod = sys.modules[__name__]
while 1: while 1:
name = sys.stdin.readline().strip() name = sys.stdin.readline().strip()
if name: if name:
@ -11,17 +11,23 @@ while 1:
sys.stderr.write('server: assembling %r (%d bytes)\n' sys.stderr.write('server: assembling %r (%d bytes)\n'
% (name, nbytes)) % (name, nbytes))
content = z.decompress(sys.stdin.read(nbytes)) content = z.decompress(sys.stdin.read(nbytes))
exec compile(content, name, "exec")
# FIXME: this crushes everything into a single module namespace, module = imp.new_module(name)
# then makes each of the module names point at this one. Gross. parent, _, parent_name = name.rpartition(".")
assert(name.endswith('.py')) if parent != "":
modname = name[:-3] setattr(sys.modules[parent], parent_name, module)
mainmod.__dict__[modname] = mainmod
code = compile(content, name, "exec")
exec code in module.__dict__
sys.modules[name] = module
else: else:
break break
verbose = verbosity
sys.stderr.flush() sys.stderr.flush()
sys.stdout.flush() sys.stdout.flush()
import sshuttle.helpers
sshuttle.helpers.verbose = verbosity
from sshuttle.server import main
main() main()

View File

@ -3,15 +3,15 @@ import errno
import re import re
import signal import signal
import time import time
import compat.ssubprocess as ssubprocess import sshuttle.compat.ssubprocess as ssubprocess
import helpers import helpers
import os import os
import ssnet import sshuttle.ssnet as ssnet
import ssh import sshuttle.ssh as ssh
import ssyslog import ssyslog
import sys import sys
from ssnet import SockWrapper, Handler, Proxy, Mux, MuxWrapper from sshuttle.ssnet import SockWrapper, Handler, Proxy, Mux, MuxWrapper
from helpers import log, debug1, debug2, debug3, Fatal, islocal, \ from sshuttle.helpers import log, debug1, debug2, debug3, Fatal, islocal, \
resolvconf_nameservers resolvconf_nameservers
recvmsg = None recvmsg = None
@ -282,7 +282,9 @@ class FirewallClient:
self.auto_nets = [] self.auto_nets = []
self.subnets_include = subnets_include self.subnets_include = subnets_include
self.subnets_exclude = subnets_exclude self.subnets_exclude = subnets_exclude
argvbase = ([sys.argv[1], sys.argv[0], sys.argv[1]] + python_path = os.path.dirname(os.path.dirname(__file__))
argvbase = (["PYTHONPATH=%s" % python_path] +
[sys.executable, sys.argv[0]] +
['-v'] * (helpers.verbose or 0) + ['-v'] * (helpers.verbose or 0) +
['--firewall', str(port_v6), str(port_v4), ['--firewall', str(port_v6), str(port_v4),
str(dnsport_v6), str(dnsport_v4), str(dnsport_v6), str(dnsport_v4),

View File

View File

@ -8,7 +8,7 @@ import ssyslog
import sys import sys
import os import os
import re import re
from helpers import log, debug1, debug3, islocal, Fatal, family_to_string, \ from sshuttle.helpers import log, debug1, debug3, islocal, Fatal, family_to_string, \
resolvconf_nameservers resolvconf_nameservers
from fcntl import ioctl from fcntl import ioctl
from ctypes import c_char, c_uint8, c_uint16, c_uint32, Union, Structure, \ from ctypes import c_char, c_uint8, c_uint16, c_uint32, Union, Structure, \

View File

@ -5,10 +5,10 @@ import select
import errno import errno
import os import os
import sys import sys
if not globals().get('skip_imports'):
import compat.ssubprocess as ssubprocess import sshuttle.compat.ssubprocess as ssubprocess
import helpers import sshuttle.helpers as helpers
from helpers import log, debug1, debug2, debug3 from sshuttle.helpers import log, debug1, debug2, debug3
POLL_TIME = 60 * 15 POLL_TIME = 60 * 15
NETSTAT_POLL_TIME = 30 NETSTAT_POLL_TIME = 30

View File

@ -5,14 +5,14 @@ import traceback
import time import time
import sys import sys
import os import os
if not globals().get('skip_imports'):
import ssnet import sshuttle.ssnet as ssnet
import helpers import sshuttle.helpers as helpers
import hostwatch import sshuttle.hostwatch as hostwatch
import compat.ssubprocess as ssubprocess import sshuttle.compat.ssubprocess as ssubprocess
from ssnet import Handler, Proxy, Mux, MuxWrapper from sshuttle.ssnet import Handler, Proxy, Mux, MuxWrapper
from helpers import log, debug1, debug2, debug3, Fatal, \ from sshuttle.helpers import log, debug1, debug2, debug3, Fatal, \
resolvconf_random_nameserver resolvconf_random_nameserver
if not globals().get('latency_control'): if not globals().get('latency_control'):

View File

@ -3,28 +3,51 @@ import os
import re import re
import socket import socket
import zlib import zlib
import compat.ssubprocess as ssubprocess import imp
import helpers import sshuttle.compat.ssubprocess as ssubprocess
from helpers import debug2 import sshuttle.helpers as helpers
from sshuttle.helpers import debug2
def readfile(name): def readfile(name):
basedir = os.path.dirname(os.path.abspath(sys.argv[0])) tokens = name.split(".")
path = [basedir] + sys.path f = None
for d in path:
fullname = os.path.join(d, name)
if os.path.exists(fullname):
return open(fullname, 'rb').read()
raise Exception("can't find file %r in any of %r" % (name, path))
token = tokens[0]
token_name = [token]
token_str = ".".join(token_name)
def empackage(z, filename, data=None): try:
(path, basename) = os.path.split(filename) f, pathname, description = imp.find_module(token_str)
for token in tokens[1:]:
module = imp.load_module(token_str, f, pathname, description)
if f is not None:
f.close()
token_name.append(token)
token_str = ".".join(token_name)
f, pathname, description = imp.find_module(
token, module.__path__)
if f is not None:
contents = f.read()
else:
contents = ""
finally:
if f is not None:
f.close()
return contents
def empackage(z, name, data=None):
if not data: if not data:
data = readfile(filename) data = readfile(name)
content = z.compress(data) content = z.compress(data)
content += z.flush(zlib.Z_SYNC_FLUSH) content += z.flush(zlib.Z_SYNC_FLUSH)
return '%s\n%d\n%s' % (basename, len(content), content) return '%s\n%d\n%s' % (name, len(content), content)
def connect(ssh_cmd, rhostport, python, stderr, options): def connect(ssh_cmd, rhostport, python, stderr, options):
@ -52,19 +75,20 @@ def connect(ssh_cmd, rhostport, python, stderr, options):
rhost = None rhost = None
z = zlib.compressobj(1) z = zlib.compressobj(1)
content = readfile('assembler.py') content = readfile('sshuttle.assembler')
optdata = ''.join("%s=%r\n" % (k, v) for (k, v) in options.items()) optdata = ''.join("%s=%r\n" % (k, v) for (k, v) in options.items())
content2 = (empackage(z, 'cmdline_options.py', optdata) + content2 = (empackage(z, 'sshuttle') +
empackage(z, 'helpers.py') + empackage(z, 'sshuttle.cmdline_options', optdata) +
empackage(z, 'compat/ssubprocess.py') + empackage(z, 'sshuttle.helpers') +
empackage(z, 'ssnet.py') + empackage(z, 'sshuttle.compat') +
empackage(z, 'hostwatch.py') + empackage(z, 'sshuttle.compat.ssubprocess') +
empackage(z, 'server.py') + empackage(z, 'sshuttle.ssnet') +
empackage(z, 'sshuttle.hostwatch') +
empackage(z, 'sshuttle.server') +
"\n") "\n")
pyscript = r""" pyscript = r"""
import sys; import sys;
skip_imports=1;
verbosity=%d; verbosity=%d;
exec compile(sys.stdin.read(%d), "assembler.py", "exec") exec compile(sys.stdin.read(%d), "assembler.py", "exec")
""" % (helpers.verbose or 0, len(content)) """ % (helpers.verbose or 0, len(content))

View File

@ -3,8 +3,7 @@ import socket
import errno import errno
import select import select
import os import os
if not globals().get('skip_imports'): from sshuttle.helpers import log, debug1, debug2, debug3, Fatal
from helpers import log, debug1, debug2, debug3, Fatal
MAX_CHANNEL = 65535 MAX_CHANNEL = 65535