# 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>
```