Skip to content

Instantly share code, notes, and snippets.

@ryuheechul
Last active March 29, 2024 16:23
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ryuheechul/9515381570a0cea994e62647d92a864f to your computer and use it in GitHub Desktop.
Save ryuheechul/9515381570a0cea994e62647d92a864f to your computer and use it in GitHub Desktop.
Networking (ssh, mosh, etc)

SSH

RemoteCommand

RemoteCommand tmux a # as something other than default shell
RequestTTY force # as our (remote) command require TTY

# equivalent to `ssh [host] -t 'tmux a'

Compression

also see Eleven SSH Tricks

Compression yes

Tunneling

Agent Forwarding

Agent forwarding is kind of a must so that the end client's pubkey is used

ForwardAgent yes

Also make sure to run ssh-add -k # or ssh-add [keyname] to add keys to agent or check with ssh-add -l to see if it's listed. Otherwise it will not be picked up. And you might see an error meesage below.

**sign_and_send_pubkey: signing failed: agent refused operation** # (it might print your key name here too)

An additional config stanza like below could add automatically.

AddKeysToAgent yes

But I experienced that some system don't (like Blink Shell at the moment) so make sure to verify keys added by seeing the key at the result of ssh-add -l.

SSH Agent Priorities

Sometimes a server has its own local agent running and connect it via a config like below

host *
  IdentityAgent some/socket/file

But this will ignore $SSH_AUTH_SOCK and (this is so not obvious as ssh-add -l will still show the one from $SSH_AUTH_SOCK but that's what it is...). There is a workaround to this though by only setting IdentityAgent when it's a direct connect (achieved by looking at the presence of $SSH_TTY).

Match host * exec "test -z $SSH_TTY"
  IdentityAgent some/socket/file

Now $SSH_AUTH_SOCK will be honored with the config above.

There is a thread on this information - https://1password.community/discussion/comment/662319/#Comment_662319.

My Implementation of A Jump Host

Examples of using public keys as IdentityFile

Connections issuses

https://gist.github.com/ryuheechul/494f4e6f08eaca34ef00ab8b238eca2a#troubleshoot-send-disconnect-broken-pipe

Long lasting ssh-agent

Enter Keychain, https://www.funtoo.org/OpenSSH_Key_Management,_Part_2

https://esc.sh/blog/ssh-agent-windows10-wsl2/ or
# maybe in your .bashrc or .zshrc
eval $(keychain [--quiet] --eval --agents ssh [id_rsa])

Accessing Clipboard

assuming pbcopy & pbpaste is what is used for clipboard on both systems

From Remote Host

ssh remote-host pbpaste | pbcopy

To Remote Host

pbpaste | ssh remote-host pbcopy

not strictly related to above, but I enjoyed reading this article, https://andrewbrookins.com/technology/synchronizing-the-ios-clipboard-with-a-remote-server-using-command-line-tools/ and hopefully iPad gets to have macOS one day, lol.

Sharing Clipboard

Even beyond simply accessing it, sharing clipboard is also possible via something called X11 forwaring.

A nice explanation is at https://askubuntu.com/a/305681.

# client side at ./ssh/config

Host [host]
  ForwardX11 yes # make sure this is on
# server side at /etc/ssh/sshd_config

X11Forwarding yes # make sure this is on - this might be blocked by default on macOS host

# When an error occur like this
# ```
# Remote: No xauth program; cannot forward
# X11 forwarding request failed on channel 0
# ```
# and the host is macOS and xquartz is installed, this should help with error above
XAuthLocation /opt/X11/bin/xauth # or the path what `which xauth` returns

Restart the sshd on macOS after editing

# applying edited /etc/ssh/sshd_config requires restarting sshd
sudo launchctl stop com.openssh.sshd && sudo launchctl start com.openssh.sshd

serving SSH via tailscale seems to have an issue with X11Forwarding, tailscale/tailscale#5160

[an update on above] I discovered an workaround! - tailscale/tailscale#5160 (comment)

On macOS, there is no X11 server by default but it can be installed

I would install it by one of these ways:

  • nix-env -iA nixpkgs.xquartz
  • brew install --cask xquartz

Another important thing is that we need to know how to use clipboard on linux and that information can be found at https://ostechnix.com/access-clipboard-contents-using-xclip-and-xsel-in-linux/.

I prefer to use xsel over xclip.

And having xsel is enough to make these two plugins work:

I also would make an alias to help my muscle memory used to macOS.

# bring `pbcopy` and `pbpaste` to linux
alias  pbcopy='xsel -i -b'
alias pbpaste='xsel -o -b'

Now things copied inside ssh and vice versa!

When ForwardX11 yes Doesn't Work

If you are in a "abnormal" situation that simple ForwardX11 yes doesn't work (i. e. WSL with WSLg), the solution below might work.

# below is equivalent to `ssh -R 6020:/tmp/.X11-unix/X0 [host]` if it was used as CLI
Host [host]
    RemoteForward 6020 /tmp/.X11-unix/X0 # basically can be used in place of `ForwardX11 yes`
#                 ^              ^
#                 |              |
#                 |              |
#  as a TCP port on remote host  |
#          (6020)                |
#                  as a Unix Domain Socket on the SSH client host
#                       (/tmp/.X11-unix/X0)
#                    which your xorg server (possibly WSLg) is lisetning to

# and the remote host side would need to `export DISPLAY=':20'`
# so that X11 client will use `localhost:6020` for X11 channel

# where is +6000 coming from?
# > `man 1 xorg | grep 6000`

# what exactly the values like these `:0` or `:20` mean?
# > `man 7 X` and search `DISPLAY NAMES`
# > to see how these resolves to which protocols (i.e. TCP or Unix Domain Socket)

# also read links below to understand more about why it works and why it might not work for some situations

But this can fail with the message below (depends on your SSH client side setup):

# from remote side

$ printenv DISPLAY
:20
$ xsel -o -b
Authorization required, but no authorization protocol specified
xsel: Can't open display: (null)
: Socket is not connected
# from ssh client (NixOS + Gnome + XWayland)

$ printenv XAUTHORITY # does this have anything to do with it?
/run/user/1000/.mutter-Xwaylandauth.ABCXYZ
# yes it's probably due to a mismatch between $DISPLAY and $XAUTHORITY
# run `xauth list` to debug

But... nested X would make it work althrough how useful would that be is up to you

Clipboard synced via something like UTM

Let's say a host is macOS and guest is a Linux VM running via UTM (and there is an agent syncing clipboard). And with whatever reason, on the host side, there is no X server (XQuartz) are running or just ForwardX11 doesn't work.

In this case, the SSH client connection (from the host) can "pretend" that it is running directly from the guest GUI by setting $XAUTHORITY. Get the value by running printenv DISPLAY XAUTHORITY from the terminal within the guest directly. And export DISPLAY and XAUTHORITY within the client connection.

# an example (that values from the above step)
export DISPLAY=:0
export XAUTHORITY=/run/user/1000/.mutter-Xwaylandauth.XYZABC

Actually there is a better way to get these value less manually via systemctl systemctl --user show-environment. e.g. https://github.com/ryuheechul/dotfiles/commit/1f4329b603646e24048a232aeedf43e026a614bc

With this particular "workaround", unlike the usual usage, we are using the X server is at the remote host (VM guest in this case) not at the SSH client (Host macOS machine)

Potential downsides of this qurky configuration

  • application (e.g. poetry, pip) that excpect the keyring auth will prompt in the original virtual console which is hard to know unless you are looking the original virtual console via for example UTM window.
    • possibly you can get hint on this by running a command with verbose log option like -v, -vv, -vvv if command supports it

Few readings regarding above:

Trouble Shooting

XQuartz Installation

Using after initial installation may require reboot (let me know if not)

xeyes command to see if it's working (and it should run the app if it wasn't)

A timing could be little tricky that when it actually start working.

xsel on Host

Check to see if xsel (or xclip if you prefer) is installed on the host system.

$DISPLAY

But bascially, when you run printenv DISPLAY, you should see something like below.

# on the client side - in this case, macOS
$ printenv DISPLAY
/private/tmp/com.apple.launchd.xYzAbCde/org.xquartz:0

# on the ssh host side - in this case, linux
$ printenv DISPLAY
localhost:10.0

Wrong Selection

The selection should be CLIPBOARD not PRIMARY nor SECONDARY.

These should work

  • xclip [-i] [-o] -s clipboard
  • xclip [-i] [-o] -s c
  • xsel [-i] [-o] --clipboard
  • xsel [-i] [-o] -b

but not these:

  • xclip [-i] [-o]
  • xsel [-i] [-o]

xeyes is working but not xsel -ib

via X11 forwarding, xeyes works but not xsel -ib from the remote machine? (xse -ob works when it's copied from the client)

# `xsel -ib` could fail silently, which happens with `xsel -ob`, too.

# let's see the verbose messages

$ xsel -obvvv
xsel: Window id: 0xc00001 (unmapped)
xsel: Timestamp: 30457450
xsel: Maximum request size: 4000 bytes
xsel: Conversion refused
xsel: Conversion refused

# conversion refused... why?

$ echo 'please copy me' | xsel -ibvvv
xsel: Window id: 0x1c00001 (unmapped)
xsel: Timestamp: 30561631
xsel: Maximum request size: 4000 bytes
xsel: opened logfile /home/[user]/.cache/xsel.log

# ok let's follow the log file and then try `xsel -ib`

$ tail -f ~/.cache/xsel.log
xsel: BadAccess (attempt to access private resource denied): Resource temporarily unavailable

Turns out adding one more option like below worked

# ~/.ssh/config
  
Host [host]
  ForwardX11 yes # not just this one but the line below
  ForwardX11Trusted yes # but it doesn't seem to be always necessary (depends on your client machine, I guess)
  # for example, I didn't need `ForwardX11Trusted yes` on macOS + XQuartz but with NixOS + XWayland
  # I don't know why exactly yet, but I assume the X server configuration on (my) NixOS configuration has a tighter control.

pbcopy, pbpaste on macOS host

pbcopy and pbpaste seems not work out of the box to forwarded X11 on the host side. (when it is on the client side it works)

xsel [-i] [-o] -b still works though

Even after running XQaurtz on the host side and make sure it syncs clipboards. My speculation is that it's because even if it syncs, it syncs with the host X11 not the client's which makes sense to me.

I'm looking for an way to mitigate this as this could be annoying that plugins that I use automatically select pbcopy|paste when they exist.

I invented a workaround that uses these wrapper scripts:

They worked as I hoped for my use cases!

And now these plugins works on macOS host.

Just make sure those scripts are exported to $PATH.

But this might break the sync between macOS clipboard and xsel -b. I'm looking into it. I'm fine with the workaround for now.

Disable Password Authentication

Mosh

Remote terminal application that allows roaming, supports intermittent connectivity, and ... The project can be found here, https://mosh.org/. In addition to SSH, Mosh can be a great fit with mobile applications like Blink Shell since the condition of connection will be constanly changing (assuming you are on the move with your mobile devices).

It use SSH to initialize (including authenticating) connection so not much additional overhead should be necessary. It doesn't even need you to run addtional daemon process (sonn you will know about what it means after your first connection).

Install

nix-env -i mosh

Usage

instead of ssh ..., mosh [--server=/your/path/for/mosh-server] ...

True Color Issue

blinksh/blink#609 (comment) can be dealt with brew install --head mosh

no longer the case thanks to https://github.com/mobile-shell/mosh/releases/tag/mosh-1.4.0

Connection Issue

Impressively Mosh maintains connection even after a client machine's rebooting. However if you rely on VPN to connect a server and if your machine like iPad can't connect (or seems to not respond for a while), it's probably not Mosh's issue. Double check the network connectivity and configure it properly and it should be good to go.

Locale issue

mobile-shell/mosh#793 (comment)

Maybe just run with LC_ALL=en_US.UTF-8 mosh ...? I'm not sure what's the best way to do it for now.

with Tmux

I would like to have a dedicated session for Mosh and setting Mosh Command for [bash|zsh -c ']tmux a -t mosh-session || tmux new -s mosh-session['] should work butit somehow does not work with Blink.

So I just place a helper script like this in the host and set command in Blink like below.

/path/to/tmux-attach-or-new.sh mosh-session