summaryrefslogtreecommitdiff
path: root/sshvia
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2021-03-12 08:10:42 +0200
committerLars Wirzenius <liw@liw.fi>2021-03-12 08:24:06 +0200
commit466fcd268e53743ca7414f1fe969a74cd0ac1ee1 (patch)
tree18056390e7f507c1f40b38edfaa4c218b840f0e7 /sshvia
parent2a562fd5a7d935d3743f6746927236b40f891a5c (diff)
downloadextrautils-466fcd268e53743ca7414f1fe969a74cd0ac1ee1.tar.gz
drop old crap
Diffstat (limited to 'sshvia')
-rwxr-xr-xsshvia219
1 files changed, 0 insertions, 219 deletions
diff --git a/sshvia b/sshvia
deleted file mode 100755
index ea94018..0000000
--- a/sshvia
+++ /dev/null
@@ -1,219 +0,0 @@
-#!/usr/bin/python
-#
-# Summary
-# =======
-#
-# ssh user1%foo:2222+user2%bar
-#
-# This logs in a user2@bar via user1@foo (port 2222). All
-# authentication happens locally, not on remote hosts. Private keys
-# are only locally, not on foo.
-#
-# Note that port for the last host must be given using ssh -p, not a
-# :22 suffix to the host. This is because this script doesn't get
-# called in that case and can't handle it, and ssh itself doesn't
-# handle it.
-#
-# Description
-# ===========
-#
-# This is a helper to allow ssh to be used in a "via this host"
-# manner. The user runs "ssh foo+bar" and this effectively logs them
-# into bar by first logging into foo and running ssh there.
-#
-# This is useful when bar is not directly accessible from the local
-# machine, but foo is. Authentication (ssh private keys, password
-# entry) is done on the local machine, even for the login to bar:
-# there is no need to, for example, store ssh private keys on foo.
-#
-# Example use case: one has a set of virtual machines behind a
-# firewall or NAT, and only one of them is accessible from anywhere on
-# the Internet. This is called a jump host. You're expected to access
-# the other hosts via the jumphost.
-#
-# Setup
-# =====
-#
-# User needs to setup their ssh on the local host (via ~/.ssh/config)
-# to run this when there is a plus sign in the target hostname:
-#
-# Host *+*
-# ProxyCommand $(sshvia %h %p)
-#
-# Also, this script should be executable and accessible via $PATH, or
-# else the config file should use the full path to this script.
-#
-# There is no need to configure anything on remote hosts, assuming
-# they have a working ssh already.
-#
-# Implementation
-# ==============
-#
-# This program outputs the magic ssh command line to connect to the
-# first target on the command line and to forward its stdin, stdout to
-# to that host. In other words, given the following command line:
-#
-# ssh foo+bar
-#
-# Each target separated by + has the following form:
-#
-# [user%]host[:port]
-#
-# Note the use of % instead of @ to get around the parsing that ssh
-# itself does.
-#
-# Using the above configuration, when the user runs "ssh foo+bar",
-# the following happens:
-#
-# * ssh matches "foo+bar" to the "Host *+*" section, and runs
-# the proxy command.
-#
-# * The proxy command invokes "ssh foo -W bar:22", which means
-# it connects to foo and forwards the local stdin/stdout to
-# bar's ssh port. The forwarding happens over the secure link
-# to foo.
-#
-# * The ssh started by the user uses the proxy command's
-# stdin/stdout to talk to what it thinks is the "foo+bar"
-# server. In other words, instead of making a TCP connection
-# to the host named "foo+bar" and sets up an encrypted channel
-# over that TCP connection, it uses the stdin/stdout of the
-# proxy command instead.
-#
-# In other words, the ssh client started by the user talks to
-# the ssh server on bar, but the communication goes via the
-# secure channel to foo.
-#
-# Additionally, this script gives ssh options to set the remote user
-# and port for the first host in a chain.
-
-import re
-import sys
-
-import cliapp
-
-
-def debug(msg):
- # Set condition below to true to get debug output to stderr.
- if False:
- sys.stderr.write('SSHVIA DEBUG: {}\n'.format(msg))
-
-
-def panic(msg):
- sys.stderr.write('SSHVIA ERROR: {}\n'.format(msg))
- sys.exit(1)
-
-
-def extract_last_target(full_target):
- # Input is foo+bar. Return foo, bar.
- i = full_target.rfind('+')
- if i == -1:
- return None, full_target
- return full_target[:i], full_target[i+1:]
-
-
-def extract_targets(full_target):
- targets = []
- remaining = full_target
- while remaining:
- remaining, target = extract_last_target(remaining)
- targets.append(target)
- return list(reversed(targets))
-
-
-def parse_target(target):
- # Input is of the form: [user%]host[:port]
- # Return user, host, port (None for user, port if missing).
-
- percent = target.find('%')
- colon = target.find(':')
-
- user = None
- port = None
-
- if percent == -1 and colon == -1:
- # It's just the host.
- host = target
- elif percent >= 0 and colon >= 0 and percent < colon:
- # It's user%host:port
- user = target[:percent]
- host = target[percent+1:colon]
- port = target[colon+1:]
- elif percent >= 0 and colon >= 0 and percent >= colon:
- # it's an error
- panic('Do not understand %r' % target)
- elif percent >= 0:
- # It's user%host
- user = target[:percent]
- host = target[percent+1:]
- elif colon >= 0:
- # It's host:port
- host = target[:colon]
- port = target[colon+1:]
- else:
- # it's a programming error
- panic('Confused by %r' % target)
-
- return user, host, port
-
-
-# ssh parses its own command line, and extracts target host, target
-# port, and target (or remote) username. However, since ssh doesn't
-# actually understand the + syntax itself, it gets things muddled: it
-# parses user1@host1:8888+user2@host2:2222 in ways that will confuse
-# users. Thus, we want the user to use % instead of @ so that ssh
-# doesn't get in the way.
-#
-# ssh also allows the user to provide the remote user with the -l
-# option, but we do not need to care about that, since it'll only be
-# used to log into the last host in the chain.
-#
-# We do need to care about ports. ssh's -p option may be used for the
-# last host in the chain, but every host in the chain may use : to
-# separate a port number.
-
-
-# Parse command line. We expect the full host (%h) and the port for
-# thst last host in the chain (%p). That port may be the default 22,
-# and will be overriden by the post in the full host if given.
-
-debug('argv: %r' % sys.argv)
-full_target, last_target_default_port = sys.argv[1:]
-
-targets = extract_targets(full_target)
-debug('targets: %r' % targets)
-if len(targets) < 2:
- panic('ERROR: Must be called with foo+bar syntax!')
-
-first_target = targets[0]
-middle_targets = targets[1:-1]
-last_target = targets[-1]
-
-
-# Extract user from first target.
-first_user, first_host, first_port = parse_target(first_target)
-
-# Extract port from last target. Replace with default if missing.
-last_user, last_host, last_port = parse_target(last_target)
-if last_port is None:
- last_port = last_target_default_port
-
-# Set up the argv array.
-argv = ['ssh', '-W', '{}:{}'.format(last_host, last_port)]
-
-if first_user is not None:
- argv.extend(['-l', first_user])
-if first_port is not None:
- argv.extend(['-p', first_port])
-all_but_last = [first_host] + middle_targets
-argv.append('+'.join(all_but_last))
-
-
-# Shell-quote everything in argv, to avoid shell metacharacters from
-# causing trouble.
-argv = [cliapp.shell_quote(x) for x in argv]
-
-
-# Output the command.
-debug('result: %r' % argv)
-sys.stdout.write(' '.join(argv) + '\n')