From 348f0eb65375f5a5ccfe051ff13f9a36cc3dcb20 Mon Sep 17 00:00:00 2001 From: Samir Aguiar Date: Mon, 1 Jul 2024 23:42:51 -0300 Subject: [PATCH] Add support for non-compliant ssh wrappers ssh wrappers like teleport's tsh do not correctly interpret the double dash as an argument delimiter and will not work properly with sshuttle. This PR adds a new command line switch to handle these cases by not adding the delimiter. Fixes #599 --- docs/manpage.rst | 7 +++++++ sshuttle/client.py | 7 ++++--- sshuttle/cmdline.py | 1 + sshuttle/options.py | 8 ++++++++ sshuttle/ssh.py | 14 ++++++++------ 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/docs/manpage.rst b/docs/manpage.rst index 2053eee..b860dde 100644 --- a/docs/manpage.rst +++ b/docs/manpage.rst @@ -181,6 +181,13 @@ Options in a non-standard location or you want to provide extra options to the ssh command, for example, ``-e 'ssh -v'``. +.. option:: --no-cmd-delimiter + + Do not add a double dash (--) delimiter before invoking Python on + the remote host. This option is useful when the ssh command used + to connect is a custom command that does not interpret this + delimiter correctly. + .. option:: --seed-hosts A comma-separated list of hostnames to use to diff --git a/sshuttle/client.py b/sshuttle/client.py index 29c3dfa..730046b 100644 --- a/sshuttle/client.py +++ b/sshuttle/client.py @@ -539,7 +539,7 @@ def ondns(listener, method, mux, handlers): def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename, python, latency_control, latency_buffer_size, dns_listener, seed_hosts, auto_hosts, auto_nets, daemon, - to_nameserver): + to_nameserver, add_cmd_delimiter): helpers.logprefix = 'c : ' debug1('Starting client with Python version %s' @@ -554,6 +554,7 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename, (serverproc, serversock) = ssh.connect( ssh_cmd, remotename, python, stderr=ssyslog._p and ssyslog._p.stdin, + add_cmd_delimiter=add_cmd_delimiter, options=dict(latency_control=latency_control, latency_buffer_size=latency_buffer_size, auto_hosts=auto_hosts, @@ -755,7 +756,7 @@ def main(listenip_v6, listenip_v4, latency_buffer_size, dns, nslist, method_name, seed_hosts, auto_hosts, auto_nets, subnets_include, subnets_exclude, daemon, to_nameserver, pidfile, - user, group, sudo_pythonpath, tmark): + user, group, sudo_pythonpath, add_cmd_delimiter, tmark): if not remotename: raise Fatal("You must use -r/--remote to specify a remote " @@ -1103,7 +1104,7 @@ def main(listenip_v6, listenip_v4, return _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename, python, latency_control, latency_buffer_size, dns_listener, seed_hosts, auto_hosts, auto_nets, - daemon, to_nameserver) + daemon, to_nameserver, add_cmd_delimiter) finally: try: if daemon: diff --git a/sshuttle/cmdline.py b/sshuttle/cmdline.py index 5480815..3e98eee 100644 --- a/sshuttle/cmdline.py +++ b/sshuttle/cmdline.py @@ -115,6 +115,7 @@ def main(): opt.user, opt.group, opt.sudo_pythonpath, + opt.add_cmd_delimiter, opt.tmark) if return_code == 0: diff --git a/sshuttle/options.py b/sshuttle/options.py index acd46da..84ff26f 100644 --- a/sshuttle/options.py +++ b/sshuttle/options.py @@ -301,6 +301,14 @@ parser.add_argument( the command to use to connect to the remote [%(default)s] """ ) +parser.add_argument( + "--no-cmd-delimiter", + action="store_false", + dest="add_cmd_delimiter", + help=""" + do not add a double dash before the python command + """ +) parser.add_argument( "--seed-hosts", metavar="HOSTNAME[,HOSTNAME]", diff --git a/sshuttle/ssh.py b/sshuttle/ssh.py index d7293fa..4ce2f56 100644 --- a/sshuttle/ssh.py +++ b/sshuttle/ssh.py @@ -84,7 +84,7 @@ def parse_hostport(rhostport): return username, password, port, host -def connect(ssh_cmd, rhostport, python, stderr, options): +def connect(ssh_cmd, rhostport, python, stderr, add_cmd_delimiter, options): username, password, port, host = parse_hostport(rhostport) if username: rhost = "{}@{}".format(username, host) @@ -183,13 +183,15 @@ def connect(ssh_cmd, rhostport, python, stderr, options): if password is not None: os.environ['SSHPASS'] = str(password) argv = (["sshpass", "-e"] + sshl + - portl + - [rhost, '--', pycmd]) + portl + [rhost]) else: - argv = (sshl + - portl + - [rhost, '--', pycmd]) + argv = (sshl + portl + [rhost]) + + if add_cmd_delimiter: + argv += ['--', pycmd] + else: + argv += [pycmd] # Our which() function searches for programs in get_path() # directories (which include PATH). This step isn't strictly