diff --git a/sshuttle/assembler.py b/sshuttle/assembler.py index 2d09a50..2937335 100644 --- a/sshuttle/assembler.py +++ b/sshuttle/assembler.py @@ -42,4 +42,4 @@ import sshuttle.cmdline_options as options # noqa: E402 from sshuttle.server import main # noqa: E402 main(options.latency_control, options.latency_buffer_size, options.auto_hosts, options.to_nameserver, - options.auto_nets, options.ttl) + options.auto_nets, options.ttl, options.localhost_detector) diff --git a/sshuttle/client.py b/sshuttle/client.py index c1cabdb..354c887 100644 --- a/sshuttle/client.py +++ b/sshuttle/client.py @@ -6,6 +6,7 @@ import subprocess as ssubprocess import os import sys import platform +import tempfile import psutil import sshuttle.helpers as helpers @@ -47,6 +48,10 @@ def got_signal(signum, frame): _pidname = None +# This variable is set to true if the client and the server appear to +# be running on the same host. +_client_server_samehost = False + def check_daemon(pidfile): global _pidname @@ -467,6 +472,16 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename, handlers = [] debug1('Connecting to server...') + # The client creates this file. If the server sees the file, it + # will delete it before writing SSHUTTLE0001 back to the client. + # If the server sees the file, then the server can deduce that it + # is running on the same host as the client. If the client sees + # that the server deleted the file, then the client can deduce + # that it is running on the same host as the server. The + # _client_server_samehost variable is set to true when they are on + # the same machine. + (_, localhost_detector) = tempfile.mkstemp(prefix="sshuttle-localhost-") + try: (serverproc, serversock) = ssh.connect( ssh_cmd, remotename, python, @@ -476,7 +491,8 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename, auto_hosts=auto_hosts, to_nameserver=to_nameserver, auto_nets=auto_nets, - ttl=ttl)) + ttl=ttl, + localhost_detector=localhost_detector)) except socket.error as e: if e.args[0] == errno.EPIPE: raise Fatal("failed to establish ssh session (1)") @@ -586,6 +602,18 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename, % (expected, initstring)) log('Connected to server.') sys.stdout.flush() + + # If the server couldn't delete our localhost_detector file, then + # the server is running on a different machine. + global _client_server_samehost + if os.path.exists(localhost_detector): + debug2("Client and server appear to be running on different machines.") + _client_server_samehost = False + os.remove(localhost_detector) # cleanup + else: + debug1("Client and server are running on the same machine.") + _client_server_samehost = True + if daemon: daemonize() log('daemonizing (%s).' % _pidname) diff --git a/sshuttle/server.py b/sshuttle/server.py index 645252b..1d443e8 100644 --- a/sshuttle/server.py +++ b/sshuttle/server.py @@ -16,6 +16,8 @@ from sshuttle.ssnet import Handler, Proxy, Mux, MuxWrapper from sshuttle.helpers import b, log, debug1, debug2, debug3, Fatal, \ resolvconf_random_nameserver, which, get_env +_client_server_samehost = False + def _ipmatch(ipstr): # FIXME: IPv4 only @@ -273,7 +275,7 @@ class UdpProxy(Handler): def main(latency_control, latency_buffer_size, auto_hosts, to_nameserver, - auto_nets, ttl): + auto_nets, ttl, localhost_detector): try: helpers.logprefix = ' s: ' debug1('Starting server with Python version %s' @@ -284,6 +286,16 @@ def main(latency_control, latency_buffer_size, auto_hosts, to_nameserver, import sshuttle.ssnet as ssnet ssnet.LATENCY_BUFFER_SIZE = latency_buffer_size + # The client writes this file to the local machine. If we can see + # it, we delete it prior to send the synchronization header. The + # client can then determine if the server and client are running + # on the same machine by checking for the presence of the file. + global _client_server_samehost + if os.path.exists(localhost_detector): + debug3("Deleted the localhost_detector created by the client.\n") + os.remove(localhost_detector) + _client_server_samehost = True + # synchronization header sys.stdout.write('\0\0SSHUTTLE0001') sys.stdout.flush()