psusan [ options ]
psusan is a server program that behaves like the innermost `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:
- choosing whether to run an interactive terminal session or a single specified command
- multiple terminal sessions at once (or a mixture of those and specified commands)
- SFTP file transfer
- all the standard SSH port-forwarding options
- X11 forwarding
- 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 bare shell session over, you can run psusan over instead, which adds all the above conveniences without changing the security properties.
The protocol that psusan speaks is also spoken by PuTTY, Plink, PSCP, and PSFTP, if you select the protocol type `Bare ssh-connection' or the command-line option -ssh-connection and specify the absolute path to the appropriate Unix-domain socket in place of a hostname.
The idea of a secure, pre-authenticated data channel seems strange to people thinking about network connections. But there are lots of examples within the context of a single Unix system, and that's where psusan is typically useful.
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
docker run -i -t some:image
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 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 -t option from that Docker command line (which means `allocate a terminal device'), and tell it to run psusan inside the container:
docker run -i some:image /some/path/to/psusan
(Of course, you'll need to ensure that 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:
which isn't particularly helpful except that it tells you that psusan has started up successfully.
To talk to this server usefully, you can set up a PuTTY saved session as follows:
- Set the protocol to `Bare ssh-connection' (the psusan protocol).
- Write 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 `dummy' will do.
- In the `Proxy' configuration panel, set the proxy type to `Local', and enter the above `docker run' command in the `Telnet command, or local proxy command' edit box.
- In the `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 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 `SSH' configuration panel, then the `Duplicate Session' option will get you a second shell in the 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 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 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.
User-mode Linux is another container type you can talk to in the same way. Here's a small worked example.
The easiest way to run UML is to use its `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:
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 `linux'), then you should see a lot of kernel startup messages, followed by a shell prompt along the lines of
To convert this into a psusan-based UML session, we need to adjust the command line so that instead of running bash it runs psusan. But running psusan directly isn't quite enough, because psusan will depend on a small amount of setup, such as having /proc mounted. So instead, we set the init process to a shell script which will do the necessary setup and then invoke psusan.
Also, running psusan directly over the UML console device is a bad idea, because then the 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 linux process, and map its standard input and output to a serial port. So the replacement UML command line might look something like this:
linux mem=512M rootfstype=hostfs rootflags=/ rw \ con=fd:2,fd:2 ssl0=fd:0,fd:1 init=/some/path/to/uml-psusan.sh
And the setup script uml-psusan.sh might look like this:
#!/bin/bash # Set up vital pseudo-filesystems mount -t proc none /proc mount -t devpts none /dev/pts # Redirect I/O to the serial port, but stderr to the console exec 0<>/dev/ttyS0 1>&0 2>/dev/console # Set the serial port into raw mode, to run a binary protocol stty raw -echo # Choose what shell you want to run inside psusan export SHELL=/bin/bash # And now run psusan over the serial port exec /home/simon/src/putty/misc/psusan
Now set up a PuTTY saved session as in the Docker example above, using that 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.
Windows Subsystem for Linux
On Windows, the default way to use WSL is to run the 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 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 `host name':
- set the local proxy command to `wsl -d %host /usr/local/bin/psusan' (or wherever you installed psusan in the Linux system)
- 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 `Debian'.)
- set the protocol to `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.
Another example of a container-like environment is the alternative filesystem layout set up by schroot(1).
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 psusan connection into the schroot environment by setting up a PuTTY saved session whose local proxy command is along the lines of
schroot -c chroot-name /some/path/to/psusan
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.
Between network namespaces
If you've set up multiple network namespaces on a Linux system, with different TCP/IP configurations, then 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 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 --listen option in 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 `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.
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 `default' or most privileged account where you run your main login session, and sometimes need to run a shell in another account.
psusan can be used as an access channel between the accounts, using GNU userv(1) as the transport. In the account you want to access, write a userv configuration stanza along the lines of
if (glob service psusan & glob calling-user my-main-account-name) reset execute /some/path/to/psusan fi
This gives your main account the right to run the command
userv my-sub-account-name psusan
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 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 some means of getting into each account in the first place, and 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 cp command, because there's nowhere convenient that you can leave it in one account where the other one can read it. But with psusan over userv, you don't need any shared piece of filesystem: you can scp files back and forth without any difficulty.
The command-line options supported by psusan are:
- --listen unix-socket-name
Run psusan in listening mode. 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 psusan is running in.
The listening socket has to be a Unix-domain socket. psusan does not provide an option to run over TCP/IP, because the unauthenticated nature of the protocol would make it inherently insecure.
In listening mode, this option causes psusan to listen for only one connection, and exit immediately after that connection terminates.
- --sessiondir pathname
This option sets the directory that shell sessions and subprocesses will start in. By default it is psusan's own working directory, but in some situations it's easier to change it with a command-line option than by wrapping psusan in a script that changes directory before starting it.
- -v, --verbose
This option causes psusan to print verbose log messages on its standard error. This is probably most useful in listening mode.
- -sshlog logfile
- -sshrawlog logfile
These options cause psusan to log protocol details to a file, similarly to the logging options in PuTTY and Plink.
-sshlog logs decoded SSH packets and other events (those that -v would print). -sshrawlog additionally logs the raw wire data, including the outer packet format and the initial greetings.
plink(1), pscp(1), psftp(1).