\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, Plink,
PSCP, and PSFTP, if you select the protocol type \q{Bare ssh-connection}
or the command-line option \cw{-ssh-connection} and specify the
absolute path to the appropriate Unix-domain socket in place of
a hostname.

\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 # Set up a default path
\e iiiiiiiiiiiiiiiiiiiiiii
\c export PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin
\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.
Basically you'll want to use the above \cw{linux} command as the local
proxy command. However, it's worth wrapping it in \cw{setsid}(\e{1}),
because when UML terminates, it kills its entire process group. So
it's better that PuTTY should not be part of that group, and should
have the opportunity to shut down cleanly by itself. So probably you
end up setting the proxy command to be something more like:

\c setsid 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

You may also find that you have to enable the bug workaround that
indicates that the server \q{Discards data sent before its greeting},
because otherwise PuTTY's outgoing protocol greeting can be
accidentally lost during UML startup. (See
\W{https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=991958}{Debian
bug #991958}.)

Once you've done that, 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-wsl} Windows Subsystem for Linux

On Windows, the default way to use WSL is to run the \cw{wsl} program,
or one of its aliases, in a Windows console, either by launching it
from an existing command prompt, or by using a shortcut that opens it
in a fresh console. This gives you a Linux terminal environment, but
in a Windows console window.

If you'd prefer to interact with the same environment using PuTTY as
the terminal (for example, if you prefer PuTTY's mouse shortcuts for
copy and paste), you can set it up by installing \cw{psusan} in the
Linux environment, and then setting up a PuTTY saved session that
talks to it. A nice way to do this is to use the name of the WSL
distribution as the \q{host name}:

\b set the local proxy command to \cq{wsl -d %host
/usr/local/bin/psusan} (or wherever you installed \cw{psusan} in the
Linux system)

\b enter the name of a particular WSL distribution in the host name
box. (For example, if you installed WSL Debian in the standard way
from the Windows store, this will just be \q{Debian}.)

\b set the protocol to \q{Bare ssh-connection}, as usual.

Like all the other examples here, this also permits you to forward
ports in and out of the WSL environment (e.g. expose a WSL2 network
service through the hypervisor's internal NAT), forward Pageant into
it, and so on.

\S2{psusan-manpage-examples-cygwin} Cygwin

Another Unix-like environment on Windows is Cygwin. That comes with
its own GUI terminal application, \cw{mintty} (as it happens, a
derivative of PuTTY); but if you'd prefer to use PuTTY itself to talk
to your Cygwin terminal sessions, \cw{psusan} can help.

To do this, you'll first need to build the Unix PuTTY tools inside
Cygwin (via the usual \cw{cmake} method). Then, copy the resulting
\cw{psusan.exe} into Cygwin's \cw{/bin} directory. (It has to be
in that directory for non-Cygwin programs to run it; otherwise it
won't be able to find the Cygwin DLL at startup.)

Then set up your PuTTY saved session like this:

\b set the local proxy command to run \cw{psusan.exe} via its real
Windows path. You might also want to add the \cw{--sessiondir} option
so that shell sessions start up in your Cygwin home directory. For
example, you might use the command \cq{c:\\cygwin64\\bin\\psusan.exe
--sessiondir /home/simon} (changing the pathname and username to match
your setup).

\b enter anything you like in the host name box; \cq{Cygwin} is
probably a good choice

\b set the protocol to \q{Bare ssh-connection}, as usual.

Port forwarding is probably not particularly useful in this case,
since Cygwin shares the same network port space as the host machine.
But turning on agent forwarding is useful, because then the Cygwin
command-line SSH client can talk to Pageant without any further
configuration.

\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.
}
