From 9ee03e5adb549f58d58c57b5fcb9a9d7740f5ac3 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 13 Dec 2020 12:30:19 +0000 Subject: [PATCH] psusan: write a man page. I've been collecting actual examples of things I've used psusan for, and now I think I have enough of them to make some kind of case for why it's a useful tool. So I've written a man page, and dumped all my collected examples in there. --- doc/Makefile | 3 +- doc/man-psusan.but | 342 +++++++++++++++++++++++++++++++++++++++++++++ unix/uxpsusan.c | 21 ++- 3 files changed, 363 insertions(+), 3 deletions(-) create mode 100644 doc/man-psusan.but diff --git a/doc/Makefile b/doc/Makefile index fd5ca531..9359a6f0 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -59,7 +59,7 @@ putty.info: $(INPUTS) MKMAN = $(HALIBUT) --man=$@ mancfg.but $< MANPAGES = putty.1 puttygen.1 plink.1 pscp.1 psftp.1 puttytel.1 pterm.1 \ - pageant.1 + pageant.1 psusan.1 man: $(MANPAGES) putty.1: man-putt.but mancfg.but; $(MKMAN) @@ -70,6 +70,7 @@ psftp.1: man-psft.but mancfg.but; $(MKMAN) puttytel.1: man-ptel.but mancfg.but; $(MKMAN) pterm.1: man-pter.but mancfg.but; $(MKMAN) pageant.1: man-pag.but mancfg.but; $(MKMAN) +psusan.1: man-psusan.but mancfg.but; $(MKMAN) mostlyclean: rm -f *.html *.txt *.hlp *.cnt *.1 *.info vstr.but *.hh[pck] diff --git a/doc/man-psusan.but b/doc/man-psusan.but new file mode 100644 index 00000000..a2565a8e --- /dev/null +++ b/doc/man-psusan.but @@ -0,0 +1,342 @@ +\cfg{man-identity}{psusan}{1}{2020-12-13}{PuTTY tool suite}{PuTTY tool suite} + +\H{psusan-manpage} Man page for \cw{psusan} + +\S{psusan-manpage-name} NAME + +\cw{psusan} \- pseudo-SSH for untappable, separately authenticated networks + +\S{psusan-manpage-synopsis} SYNOPSIS + +\c psusan [ options ] +\e bbbbbb iiiiiii + +\S{psusan-manpage-description} DESCRIPTION + +\cw{psusan} is a server program that behaves like the innermost +\q{connection} layer of an SSH session, without the two outer security +layers of encryption and authentication. It provides all the +post-authentication features of an SSH connection: + +\b choosing whether to run an interactive terminal session or a single +specified command + +\b multiple terminal sessions at once (or a mixture of those and +specified commands) + +\b SFTP file transfer + +\b all the standard SSH port-forwarding options + +\b X11 forwarding + +\b SSH agent forwarding + +The catch is that, because it lacks the outer layers of SSH, you have +to run it over some kind of data channel that is already authenticated +as the right user, and that is already protected to your satisfaction +against eavesdropping and session hijacking. A good rule of thumb is +that any channel that you were prepared to run a \e{bare} shell +session over, you can run \cw{psusan} over instead, which adds all the +above conveniences without changing the security properties. + +The protocol that \cw{psusan} speaks is also spoken by PuTTY and +Plink, if you select the protocol type \q{Bare ssh-connection}. + +\S{psusan-manpage-examples} EXAMPLES + +The idea of a secure, pre-authenticated data channel seems strange to +people thinking about \e{network} connections. But there are lots of +examples within the context of a single Unix system, and that's where +\cw{psusan} is typically useful. + +\S2{psusan-manpage-examples-docker} Docker + +A good example is the console or standard I/O channel leading into a +container or virtualisation system. Docker is a familiar example. If +you want to start a Docker container and run a shell directly within +it, you might say something like + +\c docker run -i -t some:image +\e iiiiiiiiii + +which will allow you to run a single shell session inside the +container, in the same terminal you started Docker from. + +Suppose that you'd prefer to run \e{multiple} shell sessions in the +same container at once (perhaps so that one of them can use debugging +tools to poke at what another is doing). And perhaps inside that +container you're going to run a program that you don't trust with full +access to your network, but are prepared to let it make one or two +specific network connections of the kind you could set up with an SSH +port forwarding. + +In that case, you could remove the \cw{-t} option from that Docker +command line (which means \q{allocate a terminal device}), and tell it +to run \cw{psusan} inside the container: + +\c docker run -i some:image /some/path/to/psusan +\e iiiiiiiiii iiiiiiiiiiii + +(Of course, you'll need to ensure that \cw{psusan} is installed +somewhere inside the container image.) + +If you do that from a shell command line, you'll see a banner line +looking something like this: + +\c SSHCONNECTION@putty.projects.tartarus.org-2.0-PSUSAN_Release_0.75 + +which isn't particularly helpful except that it tells you that +\cw{psusan} has started up successfully. + +To talk to this server \e{usefully}, you can set up a PuTTY saved +session as follows: + +\b Set the protocol to \q{Bare ssh-connection} (the \cw{psusan} +protocol). + +\b Write \e{something} in the hostname box. It will appear in PuTTY's +window title (if you run GUI PuTTY), so you might want to write +something that will remind you what kind of window it is. If you have +no opinion, something generic like \cq{dummy} will do. + +\b In the \q{Proxy} configuration panel, set the proxy type to +\q{Local}, and enter the above \cq{docker run} command in the +\q{Telnet command, or local proxy command} edit box. + +\b In the \q{SSH} configuration panel, you will very likely want to +turn on connection sharing. (See below.) + +This arranges that when PuTTY starts up, it will run the Docker +command as shown above in place of making a network connection, and +talk to that command using the \cw{psusan} SSH-like protocol. + +The effect is that you will still get a shell session in the context +of a Docker container. But this time, it's got all the SSH amenities. +If you also turn on connection sharing in the \q{SSH} configuration +panel, then the \q{Duplicate Session} option will get you a second +shell in the \e{same} Docker container (instead of a primary shell in +a separate instance). You can transfer files in and out of the +container while it's running using PSCP or PSFTP; you can forward +network ports, X11 programs, and/or an SSH agent to the container. + +Of course, another way to do all of this would be to run the \e{full} +SSH protocol over the same channel. This involves more setup: you have +to invent an SSH host key for the container, accept it in the client, +and deal with it being left behind in your client's host key cache +when the container is discarded. And you have to set up some login +details in the container: either configure a password, and type it in +the client, or copy in the public half of some SSH key you already +had. And all this inconvenience is \e{unnecessary}, because these are +all precautions you need to take when the connection between two +systems is going over a hostile network. In this case, it's only going +over a kernel IPC channel that's guaranteed to go to the right place, +so those safety precautions are redundant, and they only add +awkwardness. + +\S2{psusan-manpage-examples-uml} User-mode Linux + +User-mode Linux is another container type you can talk to in the same +way. Here's a small worked example. + +The \e{easiest} way to run UML is to use its \cq{hostfs} file system +type to give the guest kernel access to the same virtual filesystem as +you have on the host. For example, a command line like this gets you a +shell prompt inside a UML instance sharing your existing filesystem: + +\c linux mem=512M rootfstype=hostfs rootflags=/ rw init=/bin/bash + +If you run this at a command line (assuming you have a UML kernel +available on your path under the name \cq{linux}), then you should see +a lot of kernel startup messages, followed by a shell prompt along the +lines of + +\c root@(none):/# + +To convert this into a \cw{psusan}-based UML session, we need to +adjust the command line so that instead of running \cw{bash} it runs +\cw{psusan}. But running \cw{psusan} directly isn't quite enough, +because \cw{psusan} will depend on a small amount of setup, such as +having \cw{/proc} mounted. So instead, we set the init process to a +shell script which will do the necessary setup and \e{then} invoke +\cw{psusan}. + +Also, running \cw{psusan} directly over the UML console device is a +bad idea, because then the \cw{psusan} binary protocol will be mixed +with textual console messages. So a better plan is to redirect UML's +console to the standard error of the \cw{linux} process, and map its +standard input and output to a serial port. So the replacement UML +command line might look something like this: + +\c linux mem=512M rootfstype=hostfs rootflags=/ rw \ +\c con=fd:2,fd:2 ssl0=fd:0,fd:1 init=/some/path/to/uml-psusan.sh +\e iiiiiiiiiiiiiiiiiiiiiiiiiii + +And the setup script \cw{uml-psusan.sh} might look like this: + +\c #!/bin/bash +\c # Set up vital pseudo-filesystems +\e iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii +\c mount -t proc none /proc +\c mount -t devpts none /dev/pts +\c # Redirect I/O to the serial port, but stderr to the console +\e iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii +\c exec 0<>/dev/ttyS0 1>&0 2>/dev/console +\c # Set the serial port into raw mode, to run a binary protocol +\e iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii +\c stty raw -echo +\c # Choose what shell you want to run inside psusan +\e iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii +\c export SHELL=/bin/bash +\c # And now run psusan over the serial port +\e iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii +\c exec /home/simon/src/putty/misc/psusan + +Now set up a PuTTY saved session as in the Docker example above, using +that \cw{linux} command as the local proxy command, and you'll have a +PuTTY session that starts up a clean UML instance when you run it, and +(if you enabled connection sharing) further instances of the same +session will connect to the same instance again. + +\S2{psusan-manpage-examples-schroot} \cw{schroot} + +Another example of a container-like environment is the alternative +filesystem layout set up by \cw{schroot}(\e{1}). + +\cw{schroot} is another program that defaults to running an +interactive shell session in the terminal you launched it from. But +again, you can get a \cw{psusan} connection into the \cw{schroot} +environment by setting up a PuTTY saved session whose local proxy +command is along the lines of + +\c schroot -c chroot-name /some/path/to/psusan +\e iiiiiiiiiii iiiiiiiiiiii + +Depending on how much of the chroot environment is copied from your +main one, you might find this makes it easier to (for example) run X11 +programs inside the chroot that open windows on your main X display, +or transfer files in and out of the chroot. + +\S2{psusan-manpage-examples-namespace} Between network namespaces + +If you've set up multiple network namespaces on a Linux system, with +different TCP/IP configurations, then \cw{psusan} can be a convenient +unprivileged-user gateway between them, if you run it as a non-root +user in the non-default one of your namespaces, listening for +connections on a Unix-domain socket. + +If you do that, then it gives you convenient control over which of +your outgoing network connections use which TCP/IP configuration: you +can use PuTTY to run a shell session in the context of the other +namespace if you want to run commands like \cw{ping}, or you can set +up individual port forwardings or even a SOCKS server so that +processes running in one namespace can send their network connections +via the other one. + +For this application, it's probably most convenient to use the +\cw{--listen} option in \cw{psusan}, which makes it run as a server +and listen for connections on a Unix-domain socket. Then you can enter +that socket name in PuTTY's host name configuration field (and also +still select the \q{Bare ssh-connection} protocol option), to connect +to that socket as if it were an SSH client. + +Provided the Unix-domain socket is inside a directory that only the +right user has access to, this will ensure that authentication is done +implicitly by the Linux kernel. + +\S2{psusan-manpage-examples-userv} Between user ids, via GNU userv + +If you use multiple user ids on the same machine, say for purposes of +privilege separation (running some less-trusted program with limited +abilities to access all your stuff), then you probably have a +\q{default} or most privileged account where you run your main login +session, and sometimes need to run a shell in another account. + +\cw{psusan} can be used as an access channel between the accounts, +using GNU \cw{userv}(\e{1}) as the transport. In the account you want +to access, write a \cw{userv} configuration stanza along the lines of + +\c if (glob service psusan & glob calling-user my-main-account-name) +\e iiiiiiiiiiiiiiiiiiii +\c reset +\c execute /some/path/to/psusan +\e iiiiiiiiiiii +\c fi + +This gives your main account the right to run the command + +\c userv my-sub-account-name psusan +\e iiiiiiiiiiiiiiiiiii + +and you can configure that command name as a PuTTY local proxy +command, in the same way as most of the previous examples. + +Of course, there are plenty of ways already to access one local +account from another, such as \cw{sudo}. One advantage of doing it +this way is that you don't need the system administrator to intervene +when you want to change the access controls (e.g. change which of your +accounts have access to another): as long as you have \e{some} means +of getting into each account in the first place, and \cw{userv} is +installed, you can make further configuration changes without having +to bother root about it. + +Another advantage is that it might make file transfer between the +accounts easier. If you're the kind of person who keeps your home +directories private, then it's awkward to copy a file from one of your +accounts to another just by using the \cw{cp} command, because there's +nowhere convenient that you can leave it in one account where the +other one can read it. But with \cw{psusan} over \cw{userv}, you don't +need any shared piece of filesystem: you can \cw{scp} files back and +forth without any difficulty. + +\S{psusan-manpage-options} OPTIONS + +The command-line options supported by \cw{psusan} are: + +\dt \cw{--listen} \e{unix-socket-name} + +\dd Run \cw{psusan} in listening mode. \e{unix-socket-name} is the +pathname of a Unix-domain socket to listen on. You should ensure that +this pathname is inside a directory whose read and exec permissions +are restricted to only the user(s) you want to be able to access the +environment that \cw{psusan} is running in. + +\lcont{ + +The listening socket has to be a Unix-domain socket. \cw{psusan} does +not provide an option to run over TCP/IP, because the unauthenticated +nature of the protocol would make it inherently insecure. + +} + +\dt \cw{--listen-once} + +\dd In listening mode, this option causes \cw{psusan} to listen for +only one connection, and exit immediately after that connection +terminates. + +\dt \cw{--sessiondir} \e{pathname} + +\dd This option sets the directory that shell sessions and +subprocesses will start in. By default it is \cw{psusan}'s own working +directory, but in some situations it's easier to change it with a +command-line option than by wrapping \cw{psusan} in a script that +changes directory before starting it. + +\dt \cw{-v}, \cw{--verbose} + +\dd This option causes \cw{psusan} to print verbose log messages on +its standard error. This is probably most useful in listening mode. + +\dt \cw{\-sshlog} \e{logfile} + +\dt \cw{\-sshrawlog} \e{logfile} + +\dd These options cause \cw{psusan} to log protocol details to a file, +similarly to the logging options in PuTTY and Plink. + +\lcont{ +\cw{\-sshlog} logs decoded SSH packets and other events (those that +\cw{\-v} would print). \cw{\-sshrawlog} additionally logs the raw wire +data, including the outer packet format and the initial greetings. +} diff --git a/unix/uxpsusan.c b/unix/uxpsusan.c index b23ba426..c60728ce 100644 --- a/unix/uxpsusan.c +++ b/unix/uxpsusan.c @@ -2,8 +2,25 @@ * 'psusan': Pseudo Ssh for Untappable, Separately Authenticated Networks * * This is a standalone application that speaks on its standard I/O - * the server end of the bare ssh-connection protocol used by PuTTY's - * connection sharing. + * (or a listening Unix-domain socket) the server end of the bare + * ssh-connection protocol used by PuTTY's connection sharing. + * + * The idea of this tool is that you can use it to communicate across + * any 8-bit-clean data channel between two inconveniently separated + * domains, provided the channel is already (as the name suggests) + * adequately secured against eavesdropping and modification and + * already authenticated as the right user. + * + * If you're sitting at one end of such a channel and want to type + * commands into the other end, the most obvious thing to do is to run + * a terminal session directly over it. But if you run psusan at one + * end, and a PuTTY (or compatible) client at the other end, then you + * not only get a single terminal session: you get all the other SSH + * amenities, like the ability to spawn extra terminal sessions, + * forward ports or X11 connections, even forward an SSH agent. + * + * There are a surprising number of channels of that kind; see the man + * page for some examples. */ #include