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