---
# System prepended metadata

title: SSH

---

# SSH

SSH provides a secure way to log into a remote machine.
Unlike telnet, SSH uses encryption and boasts useful features in addition to merely remote login.

[man page](https://www.openssh.com/manual.html)

Main feature: remote login
- client `ssh` connects to server `sshd` to login

Additional feature:
- client `scp` connects to server `sshd` to copy file
- client `sftp` connects to server `sshd` which will then call the `sftp-server` for ftp

To accept connections, the server has to run the ssh daemon which listens to port 22 by default.
The ssh daemon reads configurations from `/etc/ssh/sshd_config`.
One can change the port the daemon listens to, among other things, by adding the line `Port <port>` to the config.

To start connections, the client has 

## commands
### basic
```bash
ssh [-p port] <user>@<host>
```
### run command, print output to stdout
```bash
ssh <user>@<host> [command]
```
### X11 forwarding
```bash
ssh -X <user>@<host>
```
:::danger
DO NOT USE `ssh -Y <user>@<host>` !
A program with access to the display, is trusted with access to the **entire display**. It can screenshot, keylog, and inject input into all the windows of other programs.
* -X: X11 forwarding.
* -Y: Trusted X11 forwarding.
:::
### Execute command in background
```bash
ssh -f <user>@<host> <command>
```
### Debug
```bash
ssh -v <user>@<host>
```
### SSH tunneling

1. **Local :arrow_right: Remote**
```bash
ssh -NL <local_port>:<local_host>:<remote_port> <remote_host>
```

2. **Remote :arrow_right: Local**
```bash
ssh -NR <local_port>:<local_host>:<remote_port> <remote_host>
```
-N: Do not execute command (Useful for local forwarding)

-L: Forward **local** socket to **remote** socket

-R: Forward **remote** socket to **local** socket


## ssh_config

Unless that `StrictModes no` is effective in the system wide ssh config files, your home directory cannot be group-writable nor others-writable.
```
chmod go-w ~
```
If you do `umask 077` prior to performing the following operations, file permission will be correct.
Create `~/.ssh` with the correct permission.
```
mkdir -m 700 ~/.ssh
```
Create the ssh config file with the correct permission.
```
touch ~/.ssh/config
chmod 600 ~/.ssh/config
```
Generate ssh keys.
More accurately, an rsa public/private key pair -- `~/.ssh/id_rsa.pub`/`~/.ssh/id_rsa` -- of length 4096.

Set a password for security; you'll be asked for the password each time the ssh private key is used.
If you don't care, just leave the password field empty as you progress.
Then, you won't have to ssh login with password.
At the end of the key creation process, you will be prompted to enter a comment.
It is suggested to add a comment.
```
ssh-keygen -t rsa -b 4096
```
If you want to log into multiple machines using the same username and private key, set up your SSH config file as:
```
Host *
    User user
    IdentityFile <privatekey> # Typically, ~/.ssh/id_rsa
Host <host1>
    Hostname <hostname1>
    Port <port1>
Host <host2>
    Hostname <hostname2>
    Port <port2>
Host <host3>
    Hostname <hostname3>
    Port <port3>
```
Then, you can copy your public key to some host with `ssh-copy-id <host>`.  In the future, log into to the remote machine like a breeze: `ssh <host>`.

## Others

```
700 .ssh
600 authorized_keys private_key config
644 public_key
chmod 644 ~/.ssh/known_hosts
chmod 644 ~/.ssh/config
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
```

These multiline fields should be a space-separated on a single line.

```
ssh-keygen
    [-q] # quiet
    [-b bits]
    [-t dsa | ecdsa | ed25519 | rsa]
    [-N new_passphrase]
    [-C comment]
    [-f output_keyfile]
ssh-keygen -p # change passphrase
    [-P old_passphrase]
    [-N new_passphrase]
    [-f keyfile]

ssh-keygen -t rsa -b 4096
```

```
ssh-copy-id
    [-i keyfile]
    [-p port]
    [user@]hostname

ssh-copy-id <host>
```

```
[option1[,option2[,...]]]
(
    ecdsa-sha2-nistp256 |
    ecdsa-sha2-nistp384 |
    ecdsa-sha2-nistp521 |
    ssh-ed25519 |
    ssh-dss |
    ssh-rsa
)
base64-encoded-key
[comment]

restrict,port-forwarding ssh-rsa <key> <host>
```

```
sudo chsh <user> /sbin/nologin
```

```
local -> user1@hostname1:port1 -> user2@hostname2:port2 -> user3@hostname3:port3

Host host1
    User user1
    HostName hostname1
    Port port1
    IdentitiesOnly yes
    IdentityFile ~/.ssh/key1

Host host2
    User user2
    HostName hostname2
    Port port2
    IdentitiesOnly yes
    IdentityFile ~/.ssh/key2
    ProxyJump host1

Host host3
    User user3
    HostName hostname3
    Port port3
    IdentitiesOnly yes
    IdentityFile ~/.ssh/key3
    #LocalForward host0:port0 host4:port4
    ProxyJump host2
```

## Other
### Check fingerprint
```bash
ssh-keygen -lE md5 -f <public_key>
```
### key change (MITM?)
```
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
...
```

Solution: remove `~/.ssh/known_hosts`.

### Don't want to type yes everytime you connect to a new server
```bash
ssh -o StrictHostKeyChecking=no <user>@<host>
```

### Randomart
讓人比較容易辨識這個金鑰而已 :face_with_raised_eyebrow: 
```bash
ssh -o VisualHostKey=yes <user>@<host>
```