diff --git a/client.py b/client.py index 3195d37..42da341 100644 --- a/client.py +++ b/client.py @@ -1,5 +1,5 @@ import struct, socket, select, subprocess, errno -import ssnet, ssh, helpers +import helpers, ssnet, ssh from ssnet import SockWrapper, Handler, Proxy, Mux, MuxWrapper from helpers import * @@ -15,7 +15,9 @@ def original_dst(sock): def iptables_setup(port, subnets): subnets_str = ['%s/%d' % (ip,width) for ip,width in subnets] - argv = ['sudo', sys.argv[0], '--iptables', str(port)] + subnets_str + argv = (['sudo', sys.argv[0]] + + ['-v'] * (helpers.verbose or 0) + + ['--iptables', str(port)] + subnets_str) rv = subprocess.call(argv) if rv != 0: raise Exception('%r returned %d' % (argv, rv)) @@ -46,10 +48,10 @@ def _main(listener, listenport, use_server, remotename, subnets): def onaccept(): sock,srcip = listener.accept() dstip = original_dst(sock) - log('Accept: %r:%r -> %r:%r.\n' % (srcip[0],srcip[1], + debug1('Accept: %r:%r -> %r:%r.\n' % (srcip[0],srcip[1], dstip[0],dstip[1])) if dstip == sock.getsockname(): - log("-- ignored: that's my address!\n") + debug1("-- ignored: that's my address!\n") sock.close() return if use_server: @@ -73,7 +75,7 @@ def _main(listener, listenport, use_server, remotename, subnets): handlers = filter(lambda s: s.ok, handlers) for s in handlers: s.pre_select(r,w,x) - log('Waiting: %d[%d,%d,%d]...\n' + debug2('Waiting: %d[%d,%d,%d]...\n' % (len(handlers), len(r), len(w), len(x))) (r,w,x) = select.select(r,w,x) #log('r=%r w=%r x=%r\n' % (r,w,x)) @@ -84,7 +86,7 @@ def _main(listener, listenport, use_server, remotename, subnets): def main(listenip, use_server, remotename, subnets): - log('Starting sshuttle proxy.\n') + debug1('Starting sshuttle proxy.\n') listener = socket.socket() listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) if listenip[1]: @@ -93,22 +95,22 @@ def main(listenip, use_server, remotename, subnets): ports = xrange(12300,65536) last_e = None bound = False - log('Binding:') + debug2('Binding:') for port in ports: - log(' %d' % port) + debug2(' %d' % port) try: listener.bind((listenip[0], port)) bound = True break except socket.error, e: last_e = e - log('\n') + debug2('\n') if not bound: assert(last_e) raise last_e listener.listen(10) listenip = listener.getsockname() - log('Listening on %r.\n' % (listenip,)) + debug1('Listening on %r.\n' % (listenip,)) try: return _main(listener, listenip[1], use_server, remotename, subnets) diff --git a/helpers.py b/helpers.py index d397cd8..5ffada5 100644 --- a/helpers.py +++ b/helpers.py @@ -1,8 +1,17 @@ import sys, os logprefix = '' +verbose = 0 def log(s): sys.stdout.flush() sys.stderr.write(logprefix + s) sys.stderr.flush() + +def debug1(s): + if verbose >= 1: + log(s) + +def debug2(s): + if verbose >= 2: + log(s) diff --git a/iptables.py b/iptables.py index 096844e..8afdb81 100644 --- a/iptables.py +++ b/iptables.py @@ -1,4 +1,5 @@ import subprocess, re +import helpers from helpers import * @@ -15,7 +16,7 @@ def chain_exists(name): def ipt(*args): argv = ['iptables', '-t', 'nat'] + list(args) - log('>> %s\n' % ' '.join(argv)) + debug1('>> %s\n' % ' '.join(argv)) rv = subprocess.call(argv) if rv: raise Exception('%r returned %d' % (argv, rv)) diff --git a/main.py b/main.py index 9115e63..b83502b 100755 --- a/main.py +++ b/main.py @@ -1,6 +1,6 @@ #!/usr/bin/env python import sys, os, re -import options, client, iptables, server +import helpers, options, client, server, iptables # list of: @@ -50,6 +50,7 @@ sshuttle --server -- l,listen= transproxy to this ip address and port number [default=0] r,remote= ssh hostname (and optional username) of remote sshuttle server +v,verbose increase debug message verbosity noserver don't use a separate server process (mostly for debugging) server [internal use only] iptables [internal use only] @@ -57,6 +58,8 @@ iptables [internal use only] o = options.Options('sshuttle', optspec) (opt, flags, extra) = o.parse(sys.argv[1:]) +helpers.verbose = opt.verbose + if opt.server: sys.exit(server.main()) elif opt.iptables: diff --git a/server.py b/server.py index 03753b5..b050c82 100644 --- a/server.py +++ b/server.py @@ -32,8 +32,8 @@ def main(): handlers = filter(lambda s: s.ok, handlers) for s in handlers: s.pre_select(r,w,x) - log('Waiting: %d[%d,%d,%d]...\n' - % (len(handlers), len(r), len(w), len(x))) + debug2('Waiting: %d[%d,%d,%d]...\n' + % (len(handlers), len(r), len(w), len(x))) (r,w,x) = select.select(r,w,x) #log('r=%r w=%r x=%r\n' % (r,w,x)) ready = set(r) | set(w) | set(x) diff --git a/ssh.py b/ssh.py index ef3199e..4c983b9 100644 --- a/ssh.py +++ b/ssh.py @@ -1,4 +1,5 @@ import sys, os, re, subprocess, socket +import helpers def connect(rhost): main_exe = sys.argv[0] @@ -7,7 +8,7 @@ def connect(rhost): if rhost == '-': rhost = None if not rhost: - argv = ['sshuttle', '--server'] + argv = ['sshuttle', '--server'] + ['-v']*(helpers.verbose or 0) else: # WARNING: shell quoting security holes are possible here, so we # have to be super careful. We have to use 'sh -c' because diff --git a/ssnet.py b/ssnet.py index bbc926f..e562390 100644 --- a/ssnet.py +++ b/ssnet.py @@ -55,9 +55,9 @@ class SockWrapper: self.peername = peername or _try_peername(self.rsock) def __del__(self): - log('%r: deleting\n' % self) + debug1('%r: deleting\n' % self) if self.exc: - log('%r: error was: %r\n' % (self, self.exc)) + debug1('%r: error was: %r\n' % (self, self.exc)) def __repr__(self): return 'SW:%s' % (self.peername,) @@ -68,13 +68,13 @@ class SockWrapper: def noread(self): if not self.shut_read: - log('%r: done reading\n' % self) + debug2('%r: done reading\n' % self) self.shut_read = True #self.rsock.shutdown(socket.SHUT_RD) # doesn't do anything anyway def nowrite(self): if not self.shut_write: - log('%r: done writing\n' % self) + debug2('%r: done writing\n' % self) self.shut_write = True try: self.wsock.shutdown(socket.SHUT_WR) @@ -200,18 +200,18 @@ class Mux(Handler): assert(len(data) <= 65535) p = struct.pack('!ccHHH', 'S', 'S', channel, cmd, len(data)) + data self.outbuf.append(p) - log(' > channel=%d cmd=%s len=%d\n' - % (channel, cmd_to_name[cmd], len(data))) + debug2(' > channel=%d cmd=%s len=%d\n' + % (channel, cmd_to_name[cmd], len(data))) #log('Mux: send queue is %d/%d\n' # % (len(self.outbuf), sum(len(b) for b in self.outbuf))) def got_packet(self, channel, cmd, data): - log('< channel=%d cmd=%s len=%d\n' - % (channel, cmd_to_name[cmd], len(data))) + debug2('< channel=%d cmd=%s len=%d\n' + % (channel, cmd_to_name[cmd], len(data))) if cmd == CMD_PING: self.send(0, CMD_PONG, data) elif cmd == CMD_PONG: - log('received PING response\n') + debug2('received PING response\n') elif cmd == CMD_EXIT: self.ok = False elif cmd == CMD_CONNECT: @@ -278,7 +278,7 @@ class MuxWrapper(SockWrapper): self.mux = mux self.channel = channel self.mux.channels[channel] = self.got_packet - log('new channel: %d\n' % channel) + debug2('new channel: %d\n' % channel) def __del__(self): self.nowrite() @@ -322,7 +322,7 @@ class MuxWrapper(SockWrapper): def connect_dst(ip, port): - log('Connecting to %s:%d\n' % (ip, port)) + debug2('Connecting to %s:%d\n' % (ip, port)) outsock = socket.socket() outsock.setsockopt(socket.SOL_IP, socket.IP_TTL, 42) e = None