Hacker News new | past | comments | ask | show | jobs | submit login
SSH tips and tricks (carlosbecker.dev)
589 points by feross on Aug 16, 2022 | hide | past | favorite | 157 comments



"Enter" then ~ then . will kill a hung SSH connection, instead of having to close the terminal tab. I use it all the time but most people haven't heard of it.


Related: "Enter" then ~ then "C" will open a command prompt that allows to add/close port forwardings. There others. Try "Enter" then ~ then "?".


Also related: if you use ControlMaster, then the master session takes over any port forwardings defined in new shared sessions. So you can “ssh host” once to establish the master, then “ssh host -L… -R…” to make port forwardings in new shared connections; the shared sessions can be closed and the forwardings will stay active so long as the master doesn’t close.


Is that documented as intentional? Seems weird to me that the process shutdown wouldn't tear down the forwarding


This is a great tip that I use all the time.

To be more precise ~ is the default ssh escape character. It is only treated as the ssh escape character if it is at the beginning of a new line. From the ssh(1):

> The escape character followed by a dot (`.') closes the connection; followed by control-Z suspends the connection; and followed by itself sends the escape character once.


And if you're deeper in nested SSH sessions you can use a number of ~s to indicate which one to kill.

There's more commands than the dot too but I admit I forgot the others


Ahhh that would explain why it didn't feel consistent for me, since I use ProxyCommand to hop through another box most of the time. I usually need to do that key sequence twice. But I guess now I know I just need the tilde twice.


I think the ProxyJump config option will help you.


ProxyJump (or the -J option as a shortcut) plus TCP port forwarding (-L/-R) is ridiculously powerful. You can chain jump hosts with commas, threading a port forward deep into (or out of) multiple server hops with a single command.


Also,

~?

will print a list of the available escape sequences.


That needs an enter first? That might explain why I've always found ~. to be so unreliable


It is so that you don't quit every time you paste "foobar~.baz" through the terminal.


it's because the escape character is only recognized at the beginning of a line


For those of us in the dead key land (using AltGr to type ~), remember to hit space after typing out the ~, otherwise it won't register properly.


I did not need to type the space. Just AltGr ~ (nothing is output) and then .


It can also be used for nested connections. E.g. if you SSH to server A, and then from server A to server B, ~. will kill the session on B. Alternatively, ~~. will kill the session on A.

EDIT: I started distrusting my memory here and went hunting, it appears my memory has the escape nesting backwards https://lgfang.github.io/computer/2009/05/08/quit-nested-ssh...


Documented in ssh(1), section "ESCAPE CHARACTERS".


somebody should find a way to map +++ATH0 to that same sequence for fun


And then some random garbage and NO CARRIER to confirm the disconnection :)

It was [wait]+++[wait] and then ATH or ATH0 by the way, on a modem that implemented the Hayes command set correctly. To avoid at least some inadvertent triggering of this in-band signalling.



Thank you! I will be doing a lot less "<return><return><return>...wait for connection to timeout"!


Whoa... I was today days old when I learnt this.


Thank you. I remember hearing about this but couldn’t remember the sequence! I tried spamming ~ but gave up when it didn’t work


You could have looked it up. It's under ESCAPE CHARACTERS in the man-page :)


Woah. I recently saw this shortcut when I discovered tmate. Didn't realise it was a general ssh thing. Good to know!


is this the same as hitting CTRL-D?


>> "Enter" then ~ then . will kill a hung SSH connection

> is this the same as hitting CTRL-D?

No. ^d is a character that is sent to the remote shell (bash, zsh, etc) to tell it to exit. ~. is something for the SSH client to tell it to cut the connect if (e.g.) the shell has hung.

Thing of it like working at different OSI layers: ^d is HTTP, while ~. is like TCP or IP.


amazing tip, needed this today!


I sincerly hope that works.


The SSH straight into tmux solution uses RemoteCommand and will break things like scp and rsync [1]

I have this in fish config:

  function tsh
    ssh -o RequestTTY=yes $argv tmux -u -CC new -A -s tmux-main
  end
and use `tsh host`

[1] https://unix.stackexchange.com/questions/628607/how-to-bypas...


Well, it used to break scp, but then I fixed scp: https://github.com/openssh/openssh-portable/commit/77e05394a...


Two lines of code.

That was clearly one of those paper cut type of fixes that makes the world a tiny bit nicer.


I have a similar setup but the tmux invokation is handled on the remote shell. Needless to say it does not break scp. (I will admit that a single config file for all hosts is more convenient though)

I am actually switching to having wezterm handling the mux functionality. It's nice to have this stuff running on the local client which allows all familiar keyboard shortcuts to work without conflict. Automatic Pane/Tab support is really nice. Mosh like functionality comes for free as well.


Thanks, I personally grew accustomed to just writing "ssh $host 'tmux a || tmux'


For anyone dealing with very shoddy connection, I'd highly recommend mosh: https://mosh.org

I used it when trying to use my iPad for minimalist development (mosh + ec2 + vim + Go) and it worked great compared to SSH.


Thank you! We are about to have a new release (with a new team of maintainers) and would appreciate all the testing of the rc that Hacker News is willing to provide. Details here: https://mailman.mit.edu/pipermail/mosh-devel/2022-August/001...


Thanks for all the hard work


On a somewhat related note, Wireguard acts somewhat similar to Mosh in that it can handle poor connections and moving across networks without reconnecting anything. I use SSH over Wireguard on the home DSL which sometimes has significant packet loss and it works well. I also use ZNC over Wireguard on my phone so I can move between networks without having to reconnect (home wifi => cell network => public wifi => etc).

Mosh has more features than just handling unreliable connections though, so SSH over Wireguard is not a proper replacement. Mosh reduces input latency by just echoing text right away and fixing it if needed and only syncs the visible part of the screen instead of making output block while catching up. It does other interesting things too that I don't understand very well!

You can always run Mosh over Wireguard too! This is what I'm going to start doing I think.


you can use telnet over wireguard


I wanted to try mosh, but noticed that its last release was in 2017, which doesn't inspire confidence in its security.


I did some digging, and apparently there's a new release candidate available which is accumulating those 5 years of code changes that for some reason haven't been turned into a release:

https://github.com/mobile-shell/mosh/releases/tag/mosh-1.3.2...

If anyone here is more knowledgeable, it'd be good to know why it's been this long since an official release. It looks like most of the authors of mosh are academics, so my best guess is that mosh is a volunteer effort and it's just something that slipped through the cracks


Hi -- original Mosh author here. We're excited to be doing a new release, with a new team of maintainers (not academics!), fuzzing from oss-fuzz, 24color support, etc., and would appreciate all the testing of the release candidate that Hacker News is able to provide. Hopefully we'll have a 1.4 soon. Details here: https://mailman.mit.edu/pipermail/mosh-devel/2022-August/001...

Re: why has it been five years, I feel like I've written this message many times on HN (https://news.ycombinator.com/item?id=28151637 , https://news.ycombinator.com/item?id=31010005), but here's another go. :-) We take Mosh's security seriously. In the ten years that Mosh has been out (https://news.ycombinator.com/item?id=3819382), we've never had a real security hole -- that we know about. That's a fantastic (apparent) track record. I don't want us to boast about it because it's just tempting fate, and of course you never really know if you have a security hole (just the ones you find or people tell you about), but, in terms of "security holes discovered," Mosh's track record compares really well with OpenSSH, OpenSSL, etc. Of course those codebases (a) have a lot more features than Mosh, and do more than Mosh, and (b) release more often than Mosh, but I'm happy (and I think the rest of the team is too) that Mosh does the thing it does well and without having made our users vulnerable. Back in 2012 when Mosh first came out, with a novel C++ codebase, and a novel secure datagram protocol, a lot of people were skeptical that it was worth trusting, and I'm pretty happy with how things turned out. This was all before HeartBleed and before QUIC, when self-assured people told me to "use something vetted, like OpenSSL" instead of our own new protocol and codebase. It took a long time to earn the community's trust, and now there's a few million people using Mosh, and I don't want us to fuck that up.

I had handed off the project to another maintainer, and my understanding is that he had some health challenges or maybe just got burnt out. Given the choice between "release the code with lots of new features, but without the normal procedure and without an active maintainer to take responsibility for it" vs. "don't release," we chose the conservative option. I think that was the right choice. Of course many people equate "how recently was there a release" to "how secure is this software," and... I guess we are a counterexample? Not sure what else to say.

Thank you to HN and Patrick Collison for publicizing Mosh back when it first came out ten years ago (https://news.ycombinator.com/item?id=3819382) and hope the next 10 years goes similarly... uneventfully and full of secure, reliable, mobile terminal sessions. :-) And thank you to all of you who get a chance to test the release candidate!


Where does the expectation comes from that software needs to be permanently updated? Would you consider your car unsafe if it didn't need repairs for years?


Flaws are found regularly in security-centric software. Perhaps low level libs provided the improvements however.


Eternal Terminal is way better. It’s like Mosh that doesn’t break scrollback.

https://eternalterminal.dev/


the big missing piece for my development env is port forwarding https://github.com/mobile-shell/mosh/issues/337


I recently set up autossh + tmux for this. I don't use mosh, because I use X forwarding to share the clipboard with my remote session, and mosh does not support X forwarding.


Mosh is fantastic, my only gripe is the the default escape character interfering with my vi usage (Control-^). So I use: MOSH_ESCAPE_KEY='~' mosh host


mosh breaks scrolling for me. that's a deal breaker


it doesn't support that in the first place (not that it breaks it) . use tmux or screen.


Ehhh... tomato tomato. I can scroll perfectly fine in my Ubuntu terminal. I can scroll perfectly fine when I connect with ssh. Mosh doesn't allow me to scroll. Don't really care whose fault it is.

I did try tmux today. Also doesn't support mouse scrolling out of the box, but I did find the setting for it. Still screws with copy-paste and right clicking.


I only use Mosh, but it's annoying to have to hit C-b [ and end up with clunky scrolling in tmux.


Honestly, I agree. Scrolling experience is subpar on tmux (or a ssh session fwiw)


Eternal Terminal is a great alternative that doesn’t break scrollback

https://eternalterminal.dev/


Will have to check that out. Thanks!


the article already mentions tmux, and tmux already handles ssh reconnection and more.

You might still use mosh if your connection is high latency and you are ok with occasional display artifacts, but its utility is much less if you already have tmux


mosh is great for lots of lag, but tailscale seems to improve unreliable connections for more than ssh


SSH straight into tmux

  Host example.org
 RemoteCommand tmux new -A -s default
Instead of this, i go one step further, and in .zshrc on username@example.org:

  if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
    [ -z "${TMUX}" ] && tmux new-session -A -s default
  fi


How about SSH straight into screen?

Here's how to define a shell function for quickly attaching to an existing screen session after connecting via ssh (or creating a new one if none exists):

  sshcreen () {
      ssh -t "$@" screen -xRR
  }
Works with bash and zsh. Usage is pretty simple:

  $ sshcreen user@example.com
You can use normal ssh arguments, such as the port:

  $ sshcreen root@localhost -p 2222
Detach the session with CTRL-A + D, reattach by re-running the sshcreen command you previously used.

PS: repurposed my comment from a recent discussion: https://news.ycombinator.com/item?id=32486892


I’m using the .zshrc trick too, what are the pros and cons of both? I would like to try out the RemoteCommand one though because it looks cleaner to me


Apparently the RemoteCommand way (which had never occurred to me!) can break other tools like scp or the like.

The advantage I had in mind of using the rcfile is that it's something i configure once and then applies no matter where i ssh from.


From elsewhere in this thread, it doesn’t break scp any more!

https://news.ycombinator.com/item?id=32488843


    ssh root@remotehost “apt update && apt install -y byobu && byobu-enable”
Much simpler IMO.


maybe, but it scratches a totally different itch. your proposed solution certainly doesn’t result in automatic use of tmux over ssh.


It does: that's what the byobu-enable part does. It modifies the .profile or .bashrc or whatever. All subsequent remote logins to that user account will automatically start/reattach to byobu (which uses tmux backend by default iirc).


so the same thing i did but more convoluted and requires a distro package and a service?

nah.


It doesn’t run a service, it just modifies the user’s login scripts to start byobu/tmux on login, just like yours.


Another trick I use is to put all of my stuff into .ssh/config.d/ and then run `ssh-compile` and it generates .ssh/config for me.

This lets me pull in new config files and hosts without having to redo everything every time.


Or you can add this to the top of your ssh config file:

`Include ~/.ssh/config.d/*`


Bonus points if you put the config.d dir in a Syncthing folder and synchronize it to all your workstations.


Does this honor the rc.d prefixes? Eg 0- files go first and then alphabetical?

Edit to say that my compile function does a syntax check too… but this is easier than setting up the dir listener.


I dunno, I think it does “glob-order” which should be alphabetical adjacent.


Oh that’s nice.


Redo everything? Redo what?

I just add a new entry to the bottom, `nvim ~/.ssh/config` -- what is better about your approach / what am I missing out on?

(Have never heard of ssh-compile, will also look it up when not on mobile.)


ssh-compile is my script... It's basically this:

#!/bin/sh SSH_DIR="/Users/nvahalik/.ssh/config.d/" echo "" > ~/.ssh/config for i in `ls "${SSH_DIR}"`; do echo "# ${SSH_DIR}${i}" >> ~/.ssh/config cat "${SSH_DIR}${i}" >> ~/.ssh/config echo "\n" >> ~/.ssh/config done; chmod 644 ~/.ssh/config


What I do for my homelab vms and such:

  # If ~/.ssh/config does not exist, copy file
  if [ ! -f ~/.ssh/config ]; then
    cp ./.ssh/config ~/.ssh/config
  else
    # For each block in ./.ssh/config, if it is not in ~/.ssh/config, add it
    while read -r line; do
      if [[ "$line" == "" ]]; then
        if grep -q "$block" ~/.ssh/config; then
          # If block is not found, add it to ~/.ssh/config
          echo "$block" >> ~/.ssh/config
        fi
      else
        if [[ -z "$block" ]]; then
          block="$line"
        else
          block="$block$line\n"
        fi
      fi
    done < ./.ssh/config
  fi


OpenSSH now has an Include directive.


Another good set of ssh tips for those interested in further reading: https://www.sans.org/blog/using-the-ssh-konami-code-ssh-cont...



Would you like to try cleartext SFTP, to compare performance? This can be done with inetd/socket activation.

  server# cat /etc/systemd/system/ctsftp.socket
  [Unit]
  Description=cleartext sftp

  [Socket]
  ListenStream=7777
  Accept=yes

  [Install]
  WantedBy=sockets.target

  server# cat /etc/systemd/system/ctsftp@.service 
  [Unit]
  Description=cleartext sftp

  [Service]
  ExecStart=-/usr/libexec/openssh/sftp-server
  StandardInput=socket
  User=nobody
  Group=nobody

  server# systemctl start ctsftp.socket
Then, on the client, set up a netcat.

  client$ cat ncssh 
  #!/bin/sh

  exec nc fileserver.myco.com 7777

  client$ chmod 755 ncssh
Feel free to move around the cabin.

  client$ sftp -S ./ncssh bogus
  Connected to bogus.
  sftp> put ncssh
  Uploading ncssh to /ncssh
  remote open("/ncssh"): Permission denied
  sftp> cd tmp
  sftp> put ncssh
  Uploading ncssh to /tmp/ncssh
  ncssh                                         100%   56   128.6KB/s   00:00    
  sftp> quit
I've also jacked this into stunnel. I haven't really benchmarked it, though.

You could probably chroot() this, if there was a desire to use it for something important.

For those who truly miss anonymous FTP, it was hiding inside of SSH the whole time. Shoehorning it back into the browsers is left as an exercise for the reader.


You can have anonymous sftp without it having to be cleartext https://news.ycombinator.com/item?id=26835989


> By the way, do not enable this to all hosts, as it might be considered insecure, especially if you are using a shared user. I only do this on a local server in my home network.

Kind of buried the lede there. Two pages of text followed by "Don't do this, it's unsafe!" is poor form. At least the author shows it in a host-specific configuration.


A very powerful feature of ssh is port forwarding and running SOCKS5 proxy out of the box (which possible in both directions).

Check -D, -R (both support SOCKS5 now) and -L options in man ssh.


After covid hit and I had already gone back to my home country, ssh proxy was the only way I could bypass my university's buggy 2FA to put my working hours in time management software every month. To get there, I had to bypass the university's bastion server and log into a cluster which was able to gain access to the internet. Wild times :D


-R is a reverse tunnel similar to -L, something very different from -D which is indeed a SOCKS proxy.


-R now supports SOCKS5 too. Except you initiate it from the other side (compared to -D), which is pretty cool and gives the same practical effect.


How does that work? Does it try to autodetect whether you're speaking SOCKS to it? What if you want to reverse tunnel a socks proxy from another process like Tor?


If I understand correctly, something like this:

Let's say you have hosts A and B.

Doing this from A:

    ssh -R 1080 B
will start a SOCKS5 proxy on A, to which you can connect on B through port 1080 that's being forwarded there. So your web client running on B will use traffic proxied through A while connecting to 1080 on localhost.

> Does it try to autodetect whether you're speaking SOCKS to it

I think it just uses SOCKS5 out of the box if you don't specify the host for -R. According to the man page for -R:

    if no explicit destination was specified, ssh will act
    as a SOCKS 4/5 proxy and forward connections to the
    destinations requested by the remote SOCKS client.


If you don't specify a destination for -R it will work in SOCKS mode.

> ssh -R 8080:localhost:8080 #Port forward

vs

> ssh -R 8080 #SOCKS


TO make using SSH more ergonomic, use it with a terminal that integrates with it, such as kitty: https://sw.kovidgoyal.net/kitty/kittens/ssh/

That makes using SSH ControlMaster automatic, scoped to the lifetime of the terminal session, and allows for easy automatic syncing of local shell and editor rc files to the remote host, as well as easy opening of remote files in the local editor and can even clone shell sessions into new terminal windows.


I use kitty, but I can't use this functionality because I tend to ssh into root-only (or where a single user is shared) boxes. Copying config files there wouldn't be good because it would affect everyone, not just me. That said, it is pretty sweet that this functionality exists.


You dont need to overwrite anyone elses config files, see https://sw.kovidgoyal.net/kitty/kittens/ssh/#a-real-world-ex...


That's not really a solution TBH, it's basically just copying the files _somewhere else_ than the default. I think it's generally not okay to copy over files to prod servers. If it's a shared box, you probably shouldn't be leaving behind a trace.


... except for a Caddyfile :)

For those who do not know Francis, he is co-developing Caddy, THE. BEST. web engine there is.

I take this opportunity to thank you as well as Matt Holt for the incredible product.


That's nice of you! Thank you! :)


Did I mention that the community support is incredibly good as well?

One of these rare non-toxic environments where you can get and answer to some simple problems (usually because you missed something in the excellent docs), or something more advanced for which there is a solution as well :)


:) thanks for the kind words!


I haven't tested it yet, but the tip from https://news.ycombinator.com/item?id=32468605 seem neat: (automatically copy config files on connect)

   Match Host 192.168.123.*,another-example.org,*.example.com User myusername,myotherusername
      ForwardAgent yes
      PermitLocalCommand yes
      LocalCommand rsync -L --exclude .netrwhist --exclude .git --exclude .config/iterm2/AppSupport/ --exclude .vim/bundle/youcompleteme/ -vRrlptze "ssh -o PermitLocalCommand=no" %d/./.screenrc %d/./.gitignore %d/./.bash_profile %d/./.ssh/git_ed25519.pub %d/./.ssh/authorized_keys %d/./.vimrc %d/./.zshrc %d/./.config/iterm2/ %d/./.vim/ %d/./bin/ %d/./.bash/ %r@%n:/home/%r


The SSH agent symlink tip will not fully work. If you connect with a second SSH session and then disconnect it will point to a stale SSH_AUTH_SOCK that doesn't work. The only way I found to solve this is by having a prompt command that refreshes it every time your prompt is rendered. So worst case is you have a broken ssh-agent for a single command.

Add this function to your zshrc/bashrc:

  # This function refreshes some env vars that go stale in old tmux sessions
  # It must be run as a preexec function in zsh or a PROMPT_COMMAND in bash
  function refresh_env {
      local ssh_auth_sock=""
      if [[ -v "TMUX" ]]; then
          ssh_auth_sock=$(tmux show-environment | grep "^SSH_AUTH_SOCK")
      fi
      if [[ -n "$ssh_auth_sock" ]]; then
          #shellcheck disable=SC2163
          export "$ssh_auth_sock"
      fi 
  }
Then for bash, add this:

  if ! [[ "$PROMPT_COMMAND" =~ refresh_env ]]; then
    PROMPT_COMMAND="refresh_env; $PROMPT_COMMAND";
  fi
Or for zsh, add this:

  autoload -U add-zsh-hook
  add-zsh-hook preexec refresh_env


nice I have something similar for fish, just

    if string match -q -r 'tmux\-\d+' "$TMUX"
        tmux show-env \
            | sed -nE 's/^(SSH_[^=]+)=(.\*)/set -gx \1 "\2"/p' \
            | source
    end
in my config.fish. sometimes it goes stale but a quick `exec fish` fixes it, I didn't want more stuff to run on every prompt

also both of our solutions are nice I think, no need to edit a tmux or ssh config


I often SSH into ephemeral servers like autoscaling EC2 instances. The host key checking is unnecessary and annoying, so I use a different SSH command for that:

    function ec2_ssh
      ssh -F ~/.ssh/ec2_config $argv
    end
And then in the ec2_config file…

    StrictHostKeyChecking=no
    UserKnownHostsFile=/dev/null


I feel compelled to be "that guy" for a second and just mention that while this is convenient, it makes you blatantly vulnerable to man-in-the-middle attacks. I mean, host keys exist for a reason. Sure, for many people security may not "matter" but I still think it's good to be aware when you're doing something that's way out of bounds.

I don't know how EC2 instances work in detail, but I imagine there must be a way to get a hold of the host key via an API or something when it's deployed (or maybe at any point) so that integrity could be kept without creating annoyance. I'd be much more comfortable with a solution that, for example, queries AWS over HTTPS before every connection and updates the host key (if necessary).


Yes! I’m not aware of any aws cli command that gives you the host key of a new instance. I’d definitely use that.

The script is designed for ephemeral instances, where I don’t intend to ever connect to the instance again, so saving the host key doesn’t help anything. So, really, anyone not using this hypothetical API is just as vulnerable to such a MITM attack in my threat model.


Back in the day `aws ec2 get-console-output --instance-id $ID` used to contain the public key that can be extracted using regex. Not sure if this still works.


In addition to the security aspect, it helped me understand a few times why I could not ssh into a server by IP.

I was in a secure environment, the question for the key appeared, I accepted the new key I sometimes erase known_hosts, change keys etc. so it was not suspicious). And could not log in.

It took me some time to realize that the IP I was trying to connect is not mine (as in "at home") but on the company network. I realized that when I recalled that I had the key prompt.


> I feel compelled to be "that guy" for a second and just mention that while this is convenient, it makes you blatantly vulnerable to man-in-the-middle attacks.

I don't believe that it makes you vulnerable to MitM attacks if you are authenticating with a key.


Why?


The server requests the client prove it holds the private key in a way that is bound to the session id, which is derived from the shared secret established with ephemeral key exchange.

https://security.stackexchange.com/questions/67242/does-publ...


I'd skip the config file:

    function ec2_ssh
      ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $argv
    end


For those who use (or want to use) SSH to connect to GitHub for Git, I wrote 11 years ago a tool to maintain my SSH settings for GitHub. I still actively maintain it.

https://github.com/dolmen/github-keygen/

github-keygen features:

  * automated maintenance of the GitHub specific configuration (just run the latest release of github-keygen and your setup is safely upgraded)

  * strong security settings

  * eases the management of your SSH keys allowed to access your GitHub account

  * performance settings (ControlMaster)


This seems like a great thing to turn into a GitHub CLI extension[0].

[0] https://cli.github.com/manual/gh_extension


Suggests using a yubikey, OK, then suggests shutting off host key checking, sigh.


Even the yubikey suggestion is suspect. A hardware token can protect access to your private keys by firewalling them on the "first system", which the agent is doing already. And enabling agent support on a remote device is, if anything, only opening new attack vectors; it's improving convenience and not security (the remote system has no way to validate that the hardware is in use, it just knows from ssh key pairs). It's not a bad suggestion, but it's not meaningfully different than just using ssh-agent as intended.

Then it goes on and explains how to use ControlMaster to evade the physical access validation granted by the key! I mean... why even bother with the key in the first place?

ControlMaster itself is a bad idea generically unless you really know what you're doing, because the original connection process needs to stay alive until the last child connection exits. Hands up, all of us who ever inexplicably hung cron jobs and other automated systems by doing interactive stuff at the wrong moment. I know I have. (To be clear: it's still useful as a performance enhancement for remote work, but you absolutely have to know what you're doing and script it carefully. It shouldn't appear like this in a default config line.)

Similarly CanonicalizeHostnames is a recipe for collision with your DNS. If a name doesn't work the way you want it to you need to fix the naming and not just decide to speak a new language.


> but it's not meaningfully different than just using ssh-agent as intended.

Expect for where the key is stored. How much difference that makes depends on the use-case. For a developer laptop with a passphrase protected key? Not much of a difference.

ControlMaster is great for development too. That should have been prefixed with that caveat.

In fact, it seems that all recommendations are from the point of view of a developer, not automation. That would be a bad idea for automated systems, as you point out.


Yes, its from the standpoint of me, as a developer, using these things to improve my own workflow... not to use to automate stuff.

Even the control master thing, I mentioned it goes against the purpose of the yubikey, but then I explain how I use it only for github and only for a few seconds to prevent having to touch the key nonstop when updating nvim plugins and such... IMHO its a good tradeoff...


I would dearly like to have a way to unlock keys on the remote host with my local yubikey. I generate one key for every (user, host, remoteHost) tuple, so when I'm SSH-ed into a remote host, I can't use keys from that remote host to make further connections unless I use a passphrase.


Author here: I suggested disabling host key checking ONLY on localhost...


Just for 'testing stuff'.

What's the problem you see with the recommendation? Specially when it's talking to localhost?


you did see it was localhost only, right?


I will for sure be using the SSH straight into Tmux trick. To get it to work I had to add a RequestTTY option in ~/.ssh/config.


Kind of related, but what I'd love is a way to share part of my local file system with the remote host without using FUSE or requiring root access on the remote system. Something like:

    local $ echo world > ~/src/hello
    local $ sharewith-ssh --dir ~/src:/src code.example.com
    Last login: Wed Aug 16 09:33:55 2022 from 1.2.3.4
    code ~ $ cd /src
    code /src $ cat hello
    world
    code /src $
I think it could be built with a local agent, a binary that you download on the remote host to intercept file system calls for a path (run it and it execs your shell with LD_PRELOAD to the library), and then forwards file system and I/O requests back to the the agent over SSH to get at those files. You could even have a permission prompt UI on the local agent to permit/deny individual reads/writes.

Does anything like this exist?


What's the problem with FUSE?

Anyway, it needs a daemon on the remote system, but perhaps https://github.com/u-root/cpu is suitable. (I can't vouch for it, not having used it.)

The HTCondor batch system also provides something like that, but I don't know details, and it's probably not a separable component.


vscode connected with ssh is close: It's not sharing because it only allows you to edit the server file system as if you had opened a project locally, but it does give you the feeling that you have the project there, and every time you save it goes directly to the server via ssh.


Emacs TRAMP mode can do that too; it supports SSH, sudo (to edit as a different user), and I think a bunch of other protocols. It also supports multi-hop, e.g. edit as sudo, on a remote server, connected via an intermediate bastion/proxy machine.

TRAMP works fine with shell-mode, version control (e.g. magit), dired (file browser), etc. too :)

https://www.emacswiki.org/emacs/TrampMode


> intercept file system calls for a path

How is that any different than FUSE?


It’s been a while, but i’ve created a tool that makes it easier to save an alias to your “.ssh/config” file called ssh-save-id.

https://github.com/vjanssens/ssh-save-alias


- How is vim + tmux compatibility these days? Particularly with regard to powerline, etc. types of plugins? Is there a good resource that helps one set this up from scratch?

- I find that SSH times out / disconnects if unused but only on my mac, not on my linux machine. I don't have any of the configs described here on either machine, so I'm not sure why one disconnects and one doesn't - is there some out-of-the box macOS default that needs to be changed, or is it some arcane battery optimization macOS feature that's killing the SSH sessions?


> How is vim + tmux compatibility these days?

I find I like having "set-option -g mouse on" in ~/.tmux.conf so that mousewheel scrolling feels more natural (like it does in a local terminal).

> I find that SSH times out / disconnects if unused...

This one is a little tricky - it partly depends on the default settings of the remote sshd_config for sending KeepAlive pings (changed Debian 10 to 11, e.g) and what your local vendor-compiled ssh_config defaults look like. In general, to just solve the problem add this to your macOS ~/.ssh/config at the bottom/end:

    Host *
      TCPKeepAlive yes
      ServerAliveInterval 300
TCPKeepAlive is what it sounds like, it's the L3 level tweak. ServerAliveInterval is a higher level ping-pong on the SSH session itself; kind of overkill to have both configured, but it Just Works(tm) for most people to have them set on their client. You can look these up in the man pages (ssh_config, sshd_config) and discover even more tweakable options than just these two I presented - some you can set server side, some client side, some both.

Side note: bash has an envvar `TMOUT` -- if that's set, bash will auto-logout if you idle in a shell. It's usually not set on most Linux server installs, just be aware it exists and is a thing to look for if you're debugging some day.


Thanks I'll give that a try!


If you want to copy your SSH keys to a different machine (so that you need not type your password everytime to login) you just need to do `ssh-copy-id user@remotemachine` and it works like a Charm.


Note that ssh-copy-id just copies your public key to the remote machine.


Yes. And that is what you want. You never want to have your private key leave your machine.


At the risk of self-aggrandizement, I might offer my own adventure.

Keyflips for all!

https://www.linuxjournal.com/content/ssh-key-rotation-posix-...


I develop some SSH apps using Wish

Why is wish useful to make ssh apps? Aren’t they just cli/tui apps? Or is it something different?


> setenv -g SSH_AUTH_SOCK $HOME/.ssh/ssh_auth_sock

I've worked in an environment where $HOME is mounted on a drive that's shared across multiple servers, so you might want to consider including the hostname in the socket name (logging in on another server while already logged in can result in confusing disconnections).


Slightly off topic, I want to shout out the author, Carlos Becker, for maintaining GoReleaser which has been incredibly valuable for us at Caddy to automate most of our release process. It really makes it a breeze. I sponsor him on GitHub, and I think you should too, if you use the tool as well.


Reasonably recent and/or popular discussions referencing SSH tips and/or configuration:

2021+963[year+points] A visual guide to SSH tunnels https://news.ycombinator.com/item?id=26053323

2020+770 SSH hacks – a little sanity for remote workers¹ https://news.ycombinator.com/item?id=23025756

2021+637 Sign arbitrary data with your SSH keys https://news.ycombinator.com/item?id=29208518

2020+584 How to SSH Properly² https://news.ycombinator.com/item?id=22750850

2022+459 If you’re not using SSH certificates you’re doing SSH wrong (2019)¹ https://news.ycombinator.com/item?id=30788544 https://news.ycombinator.com/item?id=20955465

2021+363 SSH Tunneling Explained² https://news.ycombinator.com/item?id=28802493

2022+358 SSH Bastion Host Best Practices² https://news.ycombinator.com/item?id=29924053#29924246

2022+298 How to Store an SSH Key on a Yubikey https://news.ycombinator.com/item?id=31556130

2022+277 SSH Agent Restriction (new in OpenSSH 8.9) https://news.ycombinator.com/item?id=29865876 (use ProxyJump if you can!)

2022+274 Guide to Using YubiKey for GPG and SSH https://news.ycombinator.com/item?id=30081348

2022+240 Free book to master SSH tunneling concepts https://news.ycombinator.com/item?id=29946144

2021+180 The pitfalls of using SSH-agent, or how to use an agent safely https://news.ycombinator.com/item?id=28576617

2022+172 Best Practices for Securing SSH² https://news.ycombinator.com/item?id=29812819

2021+158 Simple SSH Security https://news.ycombinator.com/item?id=29153223

2020+147 How to use FIDO2 USB keys with SSH https://news.ycombinator.com/item?id=23689499

--

Reasonably recent popular discussions of complementary technologies:

2022+759 Tailscale SSH https://news.ycombinator.com/item?id=31837115

2022+319 SSH into private machines from anywhere using Cloudflare Tunnel https://news.ycombinator.com/item?id=30283987

2022+281 Show HN: Caddy-SSH https://news.ycombinator.com/item?id=30830749

--

¹ Content marketing from Smallstep: https://hn.algolia.com/?query=smallstep.com

² Content marketing from Teleport: https://hn.algolia.com/?query=goteleport.com 2020+65 Teleport 4.3: Modern Replacement for OpenSSH https://news.ycombinator.com/item?id=23784925


What is the purpose of forwarding the yubikey-agent? What is it even used for?


Not the author of the article, but it allows you to use your yubikey wherever you would normally use agent forwarding. If I, for example. SSH to server foo, do some work, and then need to connect to server bar from server foo, I can use ssh -A bar. As long as both foo and bar are set up to accept my yubikey, it will work.

This can be useful if bar is configured to only be reachable by foo.


In general it's not a good idea to forward the keyring just for the purpose of jumping to a next machine. If the first machine is compromised someone may get access to your private key. For mere jumping, you should use "ssh -J jumpuser@jumpbox targetuser@targetbox".


Yup, this is true in general, but this question was specifically about yubikey-agent. When configured properly, yubikey-agent completely replaces ssh-agent, so you're no longer forwarding your private keys, you're forwarding the ability to request authentication through your yubikey. When this happens, again, assuming you have it configured right, your yubikey will blink, and will not grant the request unless you touch the little button on it. This makes agent forwarding safer, because an attacker can't impersonate you unless you agree to tap a physical button on your yubikey.

In some workflows, it's easier and faster to open a temporary connection to server bar from server foo using ssh -A, rather than opening a new terminal and using ssh -J.


this one took me days to find, seconds to implement

    $ sudo cat /etc/ssh/sshd_config.d/old-mac.conf 
    HostKeyAlgorithms +ssh-rsa
    PubkeyAcceptedAlgorithms +ssh-rsa


What's the advantage of using `yubikey-agent` instead of key types like ed25519-sk?

Keys like ed25519-sk rely on using the yubikey with support built into ssh itself (without an agent or anything).


This seems like the right place to ask: does anyone know of a hack or modification that will e.g. dump hostname on a ~? -- so many times I'm in a few layers deep and likely to miscount.


Do you mean something like putting below in your .bashrc file?

PS1="\h$ "

This will show the host name on terminal prompt.


Not quite -- I want something that will show me a hostname or instantiating command from the SSH escape sequence subsystem (e.g. if I'm N SSH sessions deep and hit ~~~., where will the kill land).


Well, ~^Z and then figure it out.


True, though I'm not always passing through something that will give me a shell (often enough that this generally works, though)


Is there a way I can rig it so every machine I ssh into has already had 'set -o vi' run for my session, without having to change anything on machine I'm logging into?


I think that's what RemoteCommand would do for you, as mentioned in the post, no?


I did try that but it just runs 'set -o vi' and exits. He shows using it to launch a multiplexer... I suppose it's an alternative to 'ssh -c command'. I tried to figure out a way to invoke 'set' followed by the remote user's $SHELL but couldn't figure it out. I'll keep fiddling; thanks for your reply


From the bash man page:

All of the single-character shell options documented in the description of the set builtin command, including -o, can be used as options when the shell is invoked.

So set RemoteCommand to something like /bin/bash -o vi


ControlMaster is very useful and I start using it. Thanks.


Yeah, this one saves (cumulatively) a lot of time. Particularly when you realise that:

(a) remote tab-completion works when typing out an scp command, and

(b) a ControlMaster config makes this tab-completion near-instant (i.e. doesn't require negotiating a connection every time).


Check the ssh_config manpage for further details on Connection Multiplexing.



Very handy.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: