SSH
SSH is the standard OpenSSH workflow for encrypted remote login, command execution, file transfer, port forwarding, and X11 forwarding.
Basic Use
ssh user@host
ssh -p 2222 user@host
ssh -i ~/.ssh/id_ed25519 user@host
ssh -J bastion user@internal-host
ssh user@host 'uname -a'
Useful client checks:
ssh -V
ssh -G host | less
ssh -vvv user@host
ssh -G prints the final client configuration after Host and Match blocks are applied. ssh -vvv is the fastest way to see which keys, algorithms, and authentication methods are being attempted.
Key Authentication
Generate a modern user key:
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519 -C "user@host"
Install the public key on the server:
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host
Manual install on the server:
install -d -m 700 ~/.ssh
cat /tmp/id_ed25519.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
Load a key into the local agent:
ssh-add ~/.ssh/id_ed25519
ssh-add -l
Client-side permissions:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
[ -f ~/.ssh/config ] && chmod 600 ~/.ssh/config
Server-side permissions:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R "$USER:$USER" ~/.ssh
Client Config
Put repeatable settings in ~/.ssh/config:
Host lab
HostName 192.0.2.10
User user
Port 22
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
ServerAliveInterval 30
ServerAliveCountMax 3
Jump host:
Host internal
HostName 10.10.10.25
User user
IdentityFile ~/.ssh/id_ed25519
ProxyJump bastion
Connection reuse:
Host *
ControlMaster auto
ControlPath ~/.ssh/cm-%r@%h:%p
ControlPersist 10m
Server Config
Edit /etc/ssh/sshd_config and test before reloading:
sudo sshd -t
sudo systemctl reload ssh || sudo systemctl reload sshd
Common key-only server settings:
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
Restrict login users when the host should only accept named accounts:
AllowUsers user deploy
Keep UsePAM yes on normal Linux distributions unless there is a specific reason to disable PAM-backed account and session handling.
Public-Key Failures
Permission denied (publickey) usually means the client did not offer the expected key, the server rejected the key, or the target account cannot use the configured authorized_keys file.
Debug from the client:
ssh -vvv -i ~/.ssh/id_ed25519 -o IdentitiesOnly=yes user@host
Check the server logs:
sudo journalctl -u ssh -u sshd -n 100 --no-pager
Check effective server options:
sudo sshd -T | grep -Ei 'pubkey|password|authorizedkeys|permitroot|strictmodes|allowusers'
Common fixes:
chmod go-w ~
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R "$USER:$USER" ~/.ssh
Also verify:
- The login user is correct.
- The public key is in that user’s
~/.ssh/authorized_keys. AuthorizedKeysFilepoints to the expected path.AllowUsers,DenyUsers,AllowGroups, orDenyGroupsare not blocking the account.- The client is not offering too many keys before the right one. Use
IdentitiesOnly yes. - The server is not too old for the key or signature algorithm being offered.
Tunneling
Use -N when the SSH session only exists for forwarding. Add -f only when you want the client to go into the background after authentication.
Local Forward
Forward a local port to a service reachable from the remote side:
ssh -N -L 127.0.0.1:8080:127.0.0.1:80 user@server
Then open http://127.0.0.1:8080 locally. From the server’s point of view, the target is 127.0.0.1:80.
Config form:
Host web-tunnel
HostName server
User user
LocalForward 127.0.0.1:8080 127.0.0.1:80
ExitOnForwardFailure yes
Remote Forward
Expose a local service through the remote server:
ssh -N -R 127.0.0.1:9000:127.0.0.1:3000 user@server
On the server, 127.0.0.1:9000 forwards back to the local machine’s 127.0.0.1:3000.
To bind the remote forwarded port beyond localhost, request an explicit bind address and allow it on the server:
ssh -N -R 0.0.0.0:9000:127.0.0.1:3000 user@server
GatewayPorts clientspecified
Dynamic Forward
Create a local SOCKS proxy:
ssh -N -D 127.0.0.1:1080 user@server
curl --socks5-hostname 127.0.0.1:1080 https://example.com
Config form:
Host socks
HostName server
User user
DynamicForward 127.0.0.1:1080
ExitOnForwardFailure yes
X11 Forwarding
X11 forwarding runs a graphical application on the remote host and displays it through the local X server over SSH.
Client side:
- Linux desktop sessions usually already provide an X server or Xwayland bridge.
- macOS needs an X server such as XQuartz.
- Windows needs an X server such as VcXsrv, Xming, or a terminal package that includes one.
Server side, install xauth and the graphical program you want to run:
sudo apt update
sudo apt install xauth x11-apps
Enable forwarding in /etc/ssh/sshd_config:
X11Forwarding yes
X11UseLocalhost yes
Reload SSH after testing the config:
sudo sshd -t
sudo systemctl reload ssh || sudo systemctl reload sshd
Connect with untrusted X11 forwarding:
ssh -X user@host
xeyes
Use trusted forwarding only for applications that require it:
ssh -Y user@host
Troubleshoot with:
echo "$DISPLAY"
xauth list
ssh -vvv -X user@host
Legacy Algorithms
Modern OpenSSH disables weak legacy algorithms by default. Prefer fixing or upgrading the old server. If a temporary exception is required, scope it to one host:
Host old-host
HostName old.example
User user
HostKeyAlgorithms +ssh-rsa
PubkeyAcceptedAlgorithms +ssh-rsa
Remove the exception after the server supports modern host keys and signatures.