Uniquely Identifying the Local TTY of an SSH Connection
Ethan Pailes
ethan at pailes.org
Thu Mar 2 00:09:34 AEDT 2023
Hi,
I'm working on a tool for persistent terminal sessions that works much
like tmux, and I would like to be able to make it so that people can
set things up so that when they ssh onto a remote host, they
automatically connect to a persistent session based on the local
terminal they are connecting from. The idea would be that users can
just type `ssh my-host` if their connection drops and they will
immediately be dropped back into their old session with all the
context like they left it.
Right now, I have two different approaches to this, both of which have
some problems. The first thing I tried is setting up some config on
the local machine in `~/.ssh/config` to make use of the RemoteCommand
and LocalCommand options. I basically want to do the equivalent of
sshing in and immediately running `tmux attach-session -t tty-1`
(though for my tool the attach command obviously looks a bit
different). The tricky bit is that I can't write down the name of the
local tty in my RemoteCommand because it is dynamic, and I can't have
my RemoteCommand derive it by itself because the RemoteCommand runs on
the remote host. To work around this, what I do is have a
RemoteCommand that connects to the session multiplexer and parks,
occupying a single global slot, then I have a LocalCommand which is
itself a nested invocation of `ssh` to connect to the remote host and
inform this parked RemoteCommand about the name of the local tty. To
make this a bit more concrete, the config block to make this work with
my tool looks like
```
Host = your-ssh-target-name
Hostname your.ssh.host.example.com
RemoteCommand shpool plumbing ssh-remote-command
PermitLocalCommand yes
LocalCommand ssh -oPermitLocalCommand=no -oRemoteCommand="shpool
plumbing ssh-local-command-set-metadata '%u@%h:%p$(tty)'" %n
```
This kinda works, but has several fairly big problems. A really
obvious one is that single global parking slot which opens this
protocol up to race conditions and limits the ability to quickly shell
in from multiple terminals at once. The second big problem is that it
requires sshing in twice to establish a connection, which means
authenticating twice. This can be pretty slow depending on how exactly
authentication has been set up.
The second approach I have is much simpler and, except for one big
issue, smoother. Instead of editing your local machine
`~/.ssh/config`, you just edit the `.bashrc` on your remote machine to
include the following block
```
if [[ $- =~ i ]] && [[ -n "$SSH_TTY" ]]; then
shpool attach "ssh-$(basename $SSH_TTY)"
fi
```
I think the equivilant for tmux is
```
if [[ $- =~ i ]] && [[ -n "$SSH_TTY" ]]; then
tmux attach-session -t "ssh-$(basename $SSH_TTY)"
fi
```
this works quite well, except that $SSH_TTY holds the path of the
remote pty rather than the local pty, so there is nothing that ensures
that you will reconnect to the same session if you ssh back into your
remote machine from the same local terminal emulator.
First of all, can anyone think of some obvious thing I'm missing that
will make this easier? Perhaps there is some config feature of
environment variable ssh sets or can be persuaded to set that I've
missed. If so, apologies for the noise.
If there really isn't such a feature, what do you think would be the
easiest way to add support for uniquely identifying the local tty and
would you be open to adding support for such a feature? I would be
willing to try to contribute support if the ssh maintainers are open
to it.
I can think of two possible ways to uniquely identify the local tty.
One way would be to add a new % format code that is available in the
context of a RemoteCommand which contains the result of evaluating
$(tty) on the local machine (or something semantically equivalent, it
wouldn't have to actually fork a subprocess). Another way would be to
just start injecting the information into the environment when sshd
forks a new subprocess in a new env var called something like
$SSH_LOCAL_TTY.
Finally, some administrative notes: I wasn't able to sign up for this
mailing list at
https://lists.mindrot.org/mailman/subscribe/openssh-unix-dev because
attempts to do so were met by a "Bug in Mailman version 2.1.39" page.
I'd also like to pre-emptively apologize if I've accidentally sent an
HTML email since I'm sending from a webmail client and this is my
first attempt to send plaintext email.
Thanks!
- Ethan Pailes
More information about the openssh-unix-dev
mailing list