ssh
Updated: October 15, 2024
Secure Shell is used to login to remote machines. It can also be used for executing commands on a remote machine.
Table of Contents
- Syntax
- Escape Characters
- Making a key
- SSH config
- Bastion Server
- SSHD config
- Copy .pub
- Git Shell
- Hardening
- X11
- Examples
- Public Remote
- Delete Keys
Syntax
ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface] [-b bind_address] [-c cipher_spec]
[-D [bind_address:]port] [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11]
[-i identity_file] [-J destination] [-L address] [-l login_name] [-m mac_spec] [-O ctl_cmd]
[-o option] [-p port] [-Q query_option] [-R address] [-S ctl_path] [-W host:port]
[-w local_tun[:remote_tun]] destination [command]
Escape Characters
~. # Disconnect.
~^Z # Background ssh.
~# # List forwarded connections.
~& # Background ssh at logout when waiting for forwarded connection / X11 sessions to terminate.
~? # Display a list of escape characters.
~B # Send a BREAK to the remote system (only useful if the peer supports it).
~C # Open command line. Currently this allows the addition of port forwardings using the -L, -R
# and -D options (see above). It also allows the cancellation of existing port-forwardings
# with -KL[bind_address:]port for local, -KR[bind_address:]port for remote and
# -KD[bind_address:]port fordynamic port-forwardings. !command allows the user to
# execute a local command if the PermitLocalCommand option is enabled in ssh_config(5).
# Basic help is available, using the -h option.
~R # Request rekeying of the connection (only useful if the peer supports it).
~V # Decrease the verbosity (LogLevel) when errors are being written to stderr.
~v # Increase the verbosity (LogLevel) when errors are being written to stderr.
Working with keys
First check to see if a key already exists. (may want to remove it)
for key in ~/.ssh/id_*; do ssh-keygen -l -f "${key}"; done | uniq
If there is a key we want to keep, we should check that it has been added to ssh-agent.
ssh-add -l
If there is no key, let’s make one!
# generate a key w/hostname as comment. All ed25519 are 256 bits
ssh-keygen -t ed25519 -C "$(hostname)" # key would be called id_ed25519
ssh-keygen -t ed25519 -C "$(hostname)" -f "$(hostname)" # key would be called hostname
# May also need to set user permissions over .ssh folder
chown -R megacron:megacron ~/.ssh
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_*
chmod 644 ~/.ssh/id_*.pub
chmod 644 ~/.ssh/authorized_keys
chmod 644 ~/.ssh/known_hosts
chmod 644 ~/.ssh/config
# this will start server
eval "$(ssh-agent -s)"
# add the private key to the ssh agent
ssh-add ~/.ssh/id_ed25519
# generate/change a passphrase
ssh-keygen -f ~/.ssh/id_ed2519 -p
# update password encoding on old key
ssh-keygen -o -f ~/.ssh/id_ed25519
-f # private key filename
-o # use newer safer password encoding
-c # change comment
-C # set comment text
-b # set size (bytes)
-p # change passphrase
-t # type of key, like ed25519
# test if ssh key added correctly for gitlab
ssh -T git@gitlab.com
# if test fails run to see error:
ssh -vvvT git@gitlab.com
# To specify to use a certain key to access remote server
ssh -i ~/.ssh/id_ed25519 megacron@10.0.18.18
# enable the server
sudo systemctl start sshd
sudo systemctl enable sshd
SSH-ADD
eval "$(ssh-agent -s)" # make sure ssh agent is running
ssh-add -d ~/.ssh/id_ed25519 # remove specific identity from ssh agent
ssh-add -D # remove all identities from ssh agent
Create a Config File
~/.ssh/config (client)
Host *
AddKeysToAgent yes
UseKeychain yes
IdentitiesOnly yes
IdentityFile ~/.ssh/id_ed25519
IdentityFile ~/.ssh/id_rsa # keep any old key files if you want
# Set a specific key to a name
Host pi3
HostName 192.168.0.12
Port 4321
User drax
IdentitiesOnly yes
IdentityFile ~/.ssh/id_ed25519
Setup Bastion Server
~/.ssh/config
Host 138.197.177.13 # IP of bastion server
User root
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
LogLevel ERROR
ServerAliveInterval 60
IdentityFile ~/.ssh/id_ed2519
Host 192.168.69.*
ProxyCommand ssh 138.197.177.13 -W %h:%p
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
LogLevel ERROR
ServerAliveInterval 60
to connect to synology through a jump server
ssh -L localhost:5001:user.synology.me:5001 jump
Setup SSHD Config File
/etc/ssh/sshd_config (server)
Port 4321 # change the port to match ~/.ssh/config of client.
Once ssh config file is updated, add the private key to the ssh agent
ssh-add -K ~/.ssh/id_ed25519
When saved you can then ssh to target host with
ssh pi3
Moving Keys to Remote Server
Ideally should use:
# creates necessary folders and permissions as well!
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host
Copy the .pub key is placed on as many computers to grant access to the server.
There are 2 ways to do this on command line:
* Pipe the file though SSH using normal login of connecting computer.
* Secure copy the file using SSH. Either one will use password. After that, no password will be needed.
# Move pub key to remote server authorized_keys file:
scp ~/.ssh/id_rsa.pub megacron@10.0.18.18:.ssh/authorized_keys
# Copies the contents of the id_rsa.pub file to your clipboard
pbcopy < ~/.ssh/id_ed25519.pub # OSX
cat ~/.ssh/id_rsa.pub | clip # windows
xclip -sel clip < ~/.ssh/id_ed25519.pub # linux
cat ~/.ssh/id_ed25519.pub | ssh user@remotehost 'cat >> ~/.ssh/authorized_keys' # appends key
scp ~/.ssh/id_ed25519.pub pi@10.0.18.18:.ssh/authorized_keys # overwrites existing keys
sudo chmod 600 authorized_keys # change mod u=rw
Git Shell for SSH
If you want to restrict access to a git server you can set it up with a git shell instead of a sh like zsh, csh, zsh and the like. This starts with editing /etc/passwd bottom line. git:x:1000:1000::/home/git:/bin/sh Change:
/bin/sh to /usr/bin/git-shell
A custom message can be made if users try to use ssh. run: git help shell
SERVER HARDENING
Perform hardening only after passwordless ssh key if fully working.
Set idle timeout interval, don’t allow empty password, turn off x11forwarding, limit max authentication attempts.
sudo vim /etc/ssh/sshd_config
# Add time for a timeout:
ClientAliveInterval 300
# Remove empty password by uncommenting:
PermitEmptyPasswords no
# Make sure x11forwarding is off
X11Forwarding no
# Lower auth tries
MaxAuthTries 3
# restart sshd server
sudo systemctl restart sshd # pacman, macOS
sudo service ssh restart # apt
- Changing ports on macOS
sudo vim /etc/services
# after finished edit
sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist
sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist
X11
REALLY GOTTA LOOK INTO THIS!! options -nf
ALSO
-S ControlPath && ControlMaster && ControlPersist
Send commands to other machines w/o logging in:
ssh USER@SERVER_IP "ls /etc" # pulls list from etc on other machine to yours.
ssh -t USER@SERVER_IP "sudo COMMAND" # use -t if sudo needs to be used.
POPULAR USES
# install and run an apache server. Check to see if running by going to http://loacalhost:80
ssh -R 8080:localhost:80 user@192.168.10.20 # creates a remote of the service on local machine to extend to another server for clients to access. So the clients can connect from a cloud on the remote server on port 8080 which then forwards through firewall by ssh tunnel to port 80 of the apache server running locally, while the clients only know they are connecting to 8080.
# create a loopback connection to get past firewall by first connecting locally to machine then going to internet. (tcp forward)
ssh -L 5901:localhost:5901 ardwolf@rrs5204q6n.hak5.org # for instance when using VNCVIEWER as a remote desktop application. This is mapping the 5901 port on the remote VNC server to the 5901 port on local machine.
need to configure VNC server to then only listen on lo (local)
then to connect ssh >> VNC all you need to put in for the command is:
vncviewer localhost:1
# create a dynamic connection
ssh -D 8080 # go to *. Allow to go anywhere. Where -L mapped to another specific port, -D does not map any specific relationship.
Quids shows some very basic setup.
Install SSH SERVER & give Authorization.
This is the Debian/Ubuntu version of sshd.
sudo apt-get install openssh-server
sudo chmod 700 .ssh # change mod u=rwx
sudo service ssh status
Then edit sshd_config to your liking and check local networking. (Default PORT 22).
sudo vim /etc/ssh/sshd_config # edit conf file
ssh localhost # get localhost name
allowUsers billy@192.168.0.17
PORTS
ssh -p 4321 user@192.168.10.12 # creates shell env on remote computer on local network.
REMOTING FROM ANOTHER NETWORK (Public Access)
For our example lets say the following variables:
- machine IP: 192.168.0.12
- public IP: 123.123.123.123
- ssh port: 4321
- username: drax
In order to gain access from outside the port needs to be forwarded by the router where the machine running sshd we want access to is located. Forward port 4321 Internal & External to 192.168.9.12
Now we can use following command to ssh to that machine from anywhere on the internet.
ssh -p 4321 drax@123.123.123.123
DELETE OR REPLACE OLD KEYS
Edit ~/.ssh/known_hosts with your favourite text editor and remove the line containing the old key. It is also possible to not do this manually using the following command:
ssh-keygen -R <strong>computer_name_or_ip</strong>
PER REPOSITORY KEYS If you want different keys depending on the repository you are working on, you can issue the following command while inside your repository.
git config core.sshCommand "ssh -o IdentitiesOnly=yes -i ~/.ssh/id_somePrivateKey -F /dev/null"