Using SSH to Connect to Remote Servers
SSH (Secure Shell) is a network protocol that provides secure, encrypted communication between two untrusted hosts over an insecure network. It’s commonly used for logging into remote servers, executing commands, transferring files securely, and setting up virtual private networks (VPNs). SSH provides a secure alternative to traditional Telnet and FTP protocols.
Installation
To install openssh, run the following command:
sudo pacman -Syu openssh
To use openssh as a client and connect to a server, run:
ssh remote_user@remote.server.com
This command uses the standard port 22. If a different port is needed, you can specify it with the -p flag, like this: -p 2222. In this example, you are logging in as the user remote_user on the server remote.server.com. The server can be specified using a domain name, local domain name, or IP address.
Client Configuration
You can configure the client in ~/.ssh/config to store common options and hosts. Options can be declared globally or restricted to specific hosts. Here’s an example:
Host github.com
AddKeysToAgent yes
User local_user
Hostname github.com
IdentityFile ~/.ssh/local_user-github
In this example, you’re specifying options for github.com for the user local_user. The AddKeysToAgent option adds SSH keys to the ssh-agent automatically, and the IdentityFile points to the private key used for github.com.
The server-side configuration is specified in /etc/ssh/sshd_config. Here, you can make changes such as disabling password authentication, changing ssh ports, enabling X11 forwarding, etc. You can also specify config settings on a per-user basis.
Executing Commands Directly
With SSH, you can not only log into a user account but also execute a single command without logging in. For example:
ssh remote_user@remote.server.com ls
This command will execute ls in the home folder of remote_user. SSH works with pipes, so you can run commands like this:
ssh remote_user@remote.server.com ls | grep PATTERN
This will grep locally the remote output of ls. Or you can run:
ls | ssh remote_user@remote.server.com grep PATTERN
This will grep remotely the local output of ls.
SSH Keys
SSH keys are a secure authentication method used to access remote machines over a network. They offer a secure and convenient alternative to password-based authentication, which can be vulnerable to brute-force attacks and other security breaches.
An SSH key pair consists of a private key and a public key. The private key is kept on the client machine and should be kept confidential, while the public key is copied to the remote host and stored in the authorized_keys file. When a client tries to access the remote host, the host checks the client’s public key against the authorized_keys file. If there is a match, the host grants access without requiring a password.
To ensure the security of SSH keys, it is recommended to use a passphrase. In the event that the key is stolen, the attacker will not be able to use it without knowing the passphrase.
SSH Key Types
There are several types of SSH keys in use, including ECDSA keys, which are small in size and perform well but may have some patent-related issues, Ed25519 keys, which are similar to ECDSA keys in terms of size, performance, and security but require newer versions of OpenSSH, and RSA keys, which are widely used and are an established standard but are less secure for the same key size and have the best compatibility. If possible, it is preferred to use Ed25519 keys.
Key Generation
To generate a key pair, you can run the following command:
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519
It is important to choose a strong and memorable passphrase to prevent unauthorized access if the private key is stolen. You can use ssh-agent or gpg-agent so you don’t have to type the passphrase every time.
Key-Based Authentication
The ssh program looks into the .ssh/authorized_keys file to determine which clients should be granted access. To copy a public key, you can use the following commands:
cat ~/.ssh/id_ed25519.pub | ssh remote_user@remote.server.com "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"
Or, you can use the simpler ssh-copy-id command if it’s available:
ssh-copy-id -i .ssh/id_ed25519 remote_user@remote.server.com
Copying Files with SCP
scp (Secure Copy) is a command used to transfer files securely over SSH. It operates in a similar way to the regular cp command, but uses an encrypted connection for added security.
To copy a local file named file.txt to the remote host remote.server.com as the user remote_user, run the following command:
scp file.txt remote_user@remote.server.com:/path/to/destination/
To copy a file from the remote host to the local machine, use this syntax:
scp remote_user@remote.server.com:/path/to/remote/file.txt /path/to/local/destination/
Entire directories can also be copied recursively by using the -r option:
scp -r remote_user@remote.server.com:/path/to/remote/directory/ /path/to/local/destination/
scp uses the same authentication mechanism as SSH, and you can choose between password-based or key-based authentication when connecting to the remote host.
If the remote machine is behind a firewall, you may need to use a specific port to connect. The -P option can be used to specify the port number that should be used for the firewall passthrough."
Executing Commands on a Remote Machine Without a Full Login
You can execute commands on a remote machine via SSH without logging in to the host. Simply use the following syntax:
ssh remote_user@remote.server.com 'command'
For example, to check the available disk space on the remote machine, you can use the df -h command like this:
ssh remote_user@remote.server.com 'df -h'
remote_user@remote.server.com's password:
udev 16G 0 16G 0% /dev
tmpfs 3.2G 5.3M 3.2G 1% /run
/dev/md2 96G 6.2G 85G 7% /
The single command line is executed by a shell on the remote machine and the output is displayed. The remote output can also be redirected into a local file:
ssh remote_user@remote.server.com 'curl wttr.in' > weather.txt
Note that you only receive the output of the command, but don’t log in to the remote machine.
Reverse SSH
Reverse SSH is a technique that allows you to establish a secure shell connection from a remote server that is behind a Network Address Translation (NAT) to a local machine with at least one accessible port from the outside. To establish a connection, the remote server first needs to connect to the local machine
The following command should be executed on the remote server:
ssh -R 2222:localhost:22 -p 55555 local_user@local_machine
And on the local machine, execute this simpler command:
ssh remote_user@localhost -p 2222
In this example, port 55555 is an open port configured in the ssh daemon configuration file (sshd_config), and port 2222 is an arbitrary unused port. According to the documentation the port 22 in the ssh command executed on the remote machine refers to the port on the local machine, but in practice it seems to refer to the ssh port on the remote machine. More experementation is needed.
I faced some challenges while setting up the reverse SSH tunnel and encountered errors when trying to connect from my local machine to an Arch setup. However, I was able to successfully connect to a Raspbian remote machine. I think it would take more experimentation to grasp the concept of reverse SSH fully. Here are the errors I encountered:
(local_user@local_machine) Password:
Authenticated to local_machine ([local_machine]:55555) using "keyboard-interactive".
debug1: Remote connections from LOCALHOST:2222 forwarded to local address localhost:22
debug1: channel 0: new session [client-session] (inactive timeout: 0)
debug1: Requesting no-more-sessions@openssh.com
debug1: Entering interactive session.
debug1: pledge: filesystem
debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0
debug1: client_input_hostkeys: searching /home/remote_user/.ssh/known_hosts for [local_machine]:55555 / (none)
debug1: client_input_hostkeys: searching /home/remote_user/.ssh/known_hosts2 for [local_machine]:55555 / (none)
debug1: client_input_hostkeys: hostkeys file /home/remote_user/.ssh/known_hosts2 does not exist
debug1: client_input_hostkeys: host key found matching a different name/address, skipping UserKnownHostsFile update
debug1: remote forward success for: listen 2222, connect localhost:22
debug1: pledge: network
Last login: Mon Feb 6 11:03:40 2023 from 192.168.xx.xx
Welcome to macOS, local_user
Today is 02-06-2023 11:04:27
[local_user@local_machine ~]$ debug1: client_input_channel_open: ctype forwarded-tcpip rchan 3 win 2097152 max 32768
debug1: client_request_forwarded_tcpip: listen localhost port 2222, originator ::1 port 49381
debug1: connect_next: start for host localhost ([::1]:22)
debug1: connect_next: connect host localhost ([::1]:22) in progress, fd=7
debug1: channel 1: new forwarded-tcpip [::1] (inactive timeout: 0)
debug1: confirm forwarded-tcpip
debug1: channel 1: connection failed: Connection refused
debug1: connect_next: start for host localhost ([127.0.0.1]:22)
debug1: connect_next: connect host localhost ([127.0.0.1]:22) in progress, fd=8
debug1: channel 1: connection failed: Connection refused
connect_to localhost port 22: failed.
debug1: channel 1: free: ::1, nchannels 2
If anyone knows how to solve this problem, please let me know.
References
https://wiki.archlinux.org/title/OpenSSH
http://teaching.idallen.com/cst8207/15w/notes/445_quotes_for_remote.html
https://austingwalters.com/configure-ssh-on-an-arch-linux-server/
https://www.freecodecamp.org/news/the-ultimate-guide-to-ssh-setting-up-ssh-keys/
https://www.youtube.com/watch?v=lRMAJwMQ0Vc
https://missing.csail.mit.edu/2020/command-line/#remote-machines