last_updated: 2026-02-18

SSH#

SSH-Keygen#

4096 RSA, no PW, inline comment, default location:

ssh-keygen -t ed25519 -N '' -f ~/.ssh/id_ed25519 -C "$USER@$HOSTNAME"

print pubkey:

cat ~/.ssh/id_ed25519.pub

Create passwordless throw-away key:

ssh-keygen -t ed25519 -N '' -C '' -f /tmp/throwaway
cat /tmp/throwaway

This creates two files: /tmp/throwaway and /tmp/throwaway.pub.

authorized_keys#

umask 077
mkdir -p ~/.ssh
cat >> ~/.ssh/authorized_keys
<paste stuff here, exit with C-d>

RSA#

If you have a machine that only supports RSA, this might help:

ssh-keygen -t rsa -b 4096 -N '' -C "$USER@$HOSTNAME"
cat ~/.ssh/id_rsa.pub

Throwaway#

ssh-keygen -t rsa -b 4096 -N '' -C '' -f /tmp/throwaway

Tunneling#

I want to use daemon at localhost on port 8080 which is running on serv on port 80:

ssh -NL 8080:localhost:80 serv
echo $!  # the PID

Daemon running on foo on port 1234. Reachable via gate. Mission: Tunnel foo:1234 to localhost:5678:

ssh -NL 5678:foo:1234 gate
echo $!  # the PID

Note: You can add -f to run ssh in the background. Just be sure to get the PID:

echo $!  # the PID

The other way around: Expose localhost:8080 on remote server serv:9999:

ssh -NR 9999:localhost:8080 serv
echo $!  # the PID

SOCKS5-Proxy#

Listens on localhost:1080 and proxies via s3:

ssh -ND 1080 s3

Test:

curl -I --socks5 localhost:1080 felixhummel.de

Config#

Be sure to run mkdir -p ~/.ssh/masters beforehand.

# example entry
Host enterprise
  Hostname 10.1.1.1
  User picard
  Port 1701
  IdentityFile ~/.ssh/picards_id

# use `enterprise` as proxy and the local IdentityFile (shuttle.lan is reachable from enterprise)
# Warning: Use with care (see ForwardAgent in `man ssh_config`)
# To check the keys your current ssh agent offers, run `ssh-add -l`
Host shuttle
  Hostname shuttle.lan
  ForwardAgent yes
  ProxyJump enterprise

# WARNING keep this at the end of this file
# =========================================
# Because "first value wins". From `man 5 ssh_config`:
# "Since the first obtained value for each parameter is used, more
# host-specific declarations should be given near the beginning of the file,
# and general defaults at the end."
Host *
  # Keep Connections Alive
  ServerAliveInterval 60
  # Re-use connections to the same host.
  ControlMaster auto
  # Leave connection open in background.
  ControlPersist 2h
  # We use both the original remote host name (%n) as well as the hash of %l%h%p%r (%C).
  # If you have a Host declaration using ProxyJump to different bastion serviers,
  # then %C looks the same for both hosts. Using only /tmp/ssh-%C would result
  # in the same ControlPath being used. For example the following config snippet
  #
  #     Host foo
  #       Hostname 127.0.0.1
  #       Port 2222
  #       ProxyJump foo-bastion
  #     Host bar
  #       Hostname 127.0.0.1
  #       Port 2222
  #       ProxyJump bar-bastion
  #
  # and running "ssh foo hostname; ssh bar hostname" would result in the output.
  #
  #     foo
  #     foo
  #
  ControlPath /tmp/ssh-%n-%C
  # Use `ssh -o ControlPath=none` to disable this temporarily
  # and `ssh -O exit some_server` to close this.

  # https://www.ssh-audit.com/hardening_guides.html
  Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
  MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,umac-128-etm@openssh.com
  HostKeyAlgorithms sk-ssh-ed25519-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,ssh-ed25519,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-256

Fingerprints#

Get fingerprint of public key:

ssh-keygen -E sha256 -lf ~/.ssh/id_rsa.pub
ssh-keygen -E md5 -lf ~/.ssh/id_rsa.pub