Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested tmux session over ssh #1

Open
sourya7 opened this issue Jan 27, 2020 · 21 comments
Open

Nested tmux session over ssh #1

sourya7 opened this issue Jan 27, 2020 · 21 comments

Comments

@sourya7
Copy link

sourya7 commented Jan 27, 2020

Hi, first of all, this is pretty sweet. One question I have is about nesting over ssh. In my client, I have tmux and I want to be able to ssh over to a server, run tmux and switch between the two. Is this something that is possible? I'm not very competent with tmux to know if we can even achieve this but it would be pretty cool if we can. If not, I can live with two terminals.

@aleclearmind
Copy link
Owner

I've thought about that, it should possible to notify an inner tmux session over SSH by sending a key (we send Alt + F12). However notifying the outer tmux session is more of an issue since we do this by writing on the tmux socket specified through an environment variable (TMUX_PARENT). However, that socket is on another machine.
We should redesign this approach and try to switch to a key-based approach to communicate to outer tmux too. However, this is not obvious.

@strazto
Copy link

strazto commented Feb 8, 2021

Hi there.
I'll preface this suggestion with the following acknowledgement- What I'm proposing adds a really decent amount of complexity, and turns this from being a tmux conf into being something more complex.

One way to potentially support this is to use remote port fort forwarding in the ssh session, as in:

# Tunnel client's localhost:8008 => remote-host's localhost:8008
ssh -R 8008:localhost:8008 remote-host

OR more robustly in the ssh config

Host remote-host
   RemoteForward 8008 localhost:8008

On the remote host, we can redirect the TMUX_PARENT socket to localhost:8008, probably using socat or something.

On the client (local) machine, we can use socat to redirect localhost:8008 to our actual TMUX socket.

There's a few caveats - A lot of enterprise/corporate servers are going to restrict what you can & can't do with ssh port forwarding (legitimate security reasons)- there's a decent chance you just can't for some servers.

To enable portforwarding, the remote's sshd_config needs to have:

AllowTcpForwarding yes

To allow remote forwarding, it needs

GatewayPorts yes

@strazto
Copy link

strazto commented Feb 8, 2021

Actually, according to
https://serverfault.com/a/753733/615908 since OpenSSH 6.7 , you can forward local unix sockets directly (this blew my mind).

Of course, a lot of enterprise servers run old versions of OpenSSH (My workplace's HPC runs OpenSSH 5.3), so we'll have to settle with using socat to redirect in those instances.

Since ssh_configs don't allow for env substitution (for example, substituting TMUX as the socket to forward), chances are, you're going to need either an alias, or a script/function to service this connection, so that you can forward the correct socket dynamically.

EDIT

actually looks like you can only localforward unix domain sockets, so without some more redirection via socat, chances are you can't directly do this - checking now

nevermind, apparently it's valid to remote forward unix sockets. SO cool my gosh.

@strazto

This comment has been minimized.

@aleclearmind
Copy link
Owner

I didn't know about forwarding UNIX sockets! Nice!
Before thinking about embedding this in ssh_config or supporting old SSH versions, I'd like to see this work with an ssh wrapper we can provide (e.g., ssh-nested-tmux).

Have you tried it? Does it work?

@strazto

This comment has been minimized.

@aleclearmind
Copy link
Owner

Mmmh, why do you rename the remote socket? This does not support multiple nested sessions over the same machine.
Also, can't you use SendEnv instead of ~/.ssh/rc?

@strazto
Copy link

strazto commented Feb 8, 2021

Mmmh, why do you rename the remote socket? This does not support multiple nested sessions over the same machine.

Good point, renamed because I'm not sure what we can write to, but I guess we can just forward the socket 1:1, meaning we can directly forward TMUX as well

Also, can't you use SendEnv instead of ~/.ssh/rc?

I think so, I'm not sure about portability (requires sshd_config to AcceptEnv yes), but assuming you have root on both machines, that's simpler, and would work better for dynamically forwarding TMUX if we don't rename the socket.

I'll rewrite the script & hide the previous attempt

@strazto
Copy link

strazto commented Feb 8, 2021

Local ~/.ssh/config

Redundant
Host remote-host
   SendEnv TMUX
   # Maybe wildcard? TMUX_* 
#!/usr/bin/env bash

# -R remote_socket:local_socket
ssh -R "${TMUX}:${TMUX}" -o SendEnv=TMUX  remote-host

@aleclearmind
Copy link
Owner

-o SendEnv=TMUX?

@strazto
Copy link

strazto commented Feb 8, 2021

-o SendEnv=TMUX?

Updated

@strazto
Copy link

strazto commented Feb 8, 2021

I actually haven't applied nested-tmux to my own tmux conf, btw, so I can't test this until I do so, if you're able to test it out I'd love to hear about it- Thank you for your feedback!

If it works, I'd love to be the one to open the PR if that's okay

@strazto
Copy link

strazto commented Feb 8, 2021

Regarding directly forwarding the tmux socket, I just checked and it looks like my UID is encoded into the directory of the tmux socket, we may need to hack around that a bit for systems where the client uid != remote uid, idk

@aleclearmind
Copy link
Owner

Please, reduce the amount of messages, test things and then make a PR.
Otherwise I'll look into that when I get the chance.

@deliciouslytyped
Copy link

Are there possibly any other ways to do this? I don't know about tmux's security model, but forwarding sockets leaves me a bit uncomfortable. - or is that unwarranted?

@aleclearmind
Copy link
Owner

Yeah, it'd be nice to limit what can be communicated back to the client only a signal to reactivate the outer layer.

@deliciouslytyped
Copy link

Ok so there are (at least?) two ways to do this

  1. wait for a "signal" (side-channel) from the inner session to change the tmux state
  2. directly modify the parent state
  3. use terminal escape sequences?

nested-tmux curently does the latter, which is what introduces the socket requirement.
The problem with the former is you need to find a signal, that you can observe, which is obscure enough as to generally not impair functionality if it is co-opted. This also limity flexibility and youhave to define a protocol to use over the sidechannel.

Looking through the tmux man page,

All the notifications listed in the CONTROL MODE section are hooks (without any arguments), except %exit.  The following additional hooks are available:

Items that caught my eye for tunneling information: pane-set-clipboard,
Things that are 1-bit signals seem tedious, but one-hot encoding two 1-bit signals should be feasible at least for triggering "up/down" navigation.

If the clipboard hook combined with OSC 52 (apparently some sort of clipboard copy escape sequence; needs more research; example: https://gist.github.com/yudai/95b20e3da66df1b066531997f982b57b ) allows us to be notified on data transfer via the clipboard, we could parse arbitrary information. The main downside i see is having to deal with clobbering the clipboard, but apparently the xterm escape sequence (section P c ; P d section in https://www.xfree86.org/current/ctlseqs.html) can specify a target buffer? I'm not sure if that's the same thing though. tmux/tmux#1477 also looks very relevant to this approach.

Anyway lot of this seems rather hacky and maybe it's worth asking the tmux developer for suggestions once there's a clear question.

I don't immediately see any other hooks we could use.

Another question is how to handle something with the ssh connection breaking, timing out, or accidentally outputting bad data on the terminal. This is generally a risk with in-band signaling.

@deliciouslytyped
Copy link

Making this work also would/could allow assimilating existing (nested) tmux sessions?
I've done some experiments trying to do that but I had some issues I don't understand yet.

@deliciouslytyped
Copy link

Should we just try to get upstream to support nested tmux better by design? :P

@strazto
Copy link

strazto commented Apr 12, 2021

Should we just try to get upstream to support nested tmux better by design? :P

By upstream, do you mean nicm & the tmux maintainers?

They're great maintainers, but they're pretty hard to influence, I guess you can try your luck lmao, but I'm sure this has already been raised with them

@niqodea
Copy link

niqodea commented Jun 20, 2024

FYI, my alternative plugin tmux-matryoshka supports nested tmux over ssh for free, without the need for the nested tmux session to be aware of the external one (though it might lack some of nested-tmux's functionalities in other departments)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants