Best Practices for Using SSH to Connect to a Remote Server | My Note

Best Practices for Using SSH to Connect to a Remote Server

Updated: Oct 4th, 2023


When you want to connect to a remote Linux server, the most common method is to use ssh. In this post, I will explain the usage of ssh at different levels and hope that it will help you become familiar with ssh. After getting the higher level of ssh, you can ensure both security and convenience without making any compromises.

Level 1: ssh command line

If you are a newbie and not familiar with SSH, you can simply use the command line to utilize SSH.

Use password

The most simple method to use ssh is to use password to connect. Just like this:

ssh ${username}@${host}

If you need to specific the port number of ssh, you can use this

ssh -p ${port} ${username}@${host}

The ssh will ask you to type in the password in a invisible line. And here you are ! You can connect every server if you have the host ip, username and password.

Use the public / private key pair to connect

The password method is not safe because hackers on the internet can scan all open SSH ports and attempt to exploit these ports by using a directory of passwords. A more secure alternative is to use a key pair generated by an algorithm, which provides stronger security than passwords.

Step 1: generated key pair by command ssh-keygen . If we do not provide extra information and just type “Enter”, ssh-keygen will generate the private key in ~/.ssh/id_rsa and public key in ~/.ssh/id_rsa.pub.

Step 2: provide the public key ~/.ssh/id_rsa.pub to the server provider and the server maintainer will add these public key to ~/.ssh/authorized_keys on the server.

Step 3: You can connect to the server using your private key without having to enter a password.

ssh -i ~/.ssh/id_rsa -p ${port} ${username}@${host}

Since ~/.ssh/id_rsa is the default path for ssh, we can safely ignore specifying this path as ssh will automatically locate it.

If you want to connect to the mike account of a server (ip : 1.1.1.1) and it use 49823 as the ssh port with your private key, you can just :

ssh -i ~/.ssh/id_rsa -p 49823 [email protected]

Level 2: ssh config file

In the level 2 , you will know some thing about the ssh config file.

Using ssh config file

To avoid the inconvenience of specifying all arguments in the command line, we can utilize the ssh config file to connect to a server using an alias.

The default path for the ssh config file is ~/.ssh/config. In order to connect to a specific server, we can create a configuration with the following contents(use the previous example):

$ cat ~/.ssh/config

Host one_alias
    User mike
    HostName 1.1.1.1
    Port 49823
    IdentityFile ~/.ssh/id_rsa

By utilizing this config file, we can establish a connection to the server by executing the following command:

ssh one_alias

You have the flexibility to set your preferred alias as one_alias.

ssh a server through a jumpserver

If the server maintainer provides a jump server, they may inform us that the server can only be accessed through the jump server. The network of your PC can not route to the network of one_alias. However, it is inconvenient for us to first log in to the jump server and then connect to the desired server. To address this issue, I would like to introduce the use of ProxyJump in the ssh config file.

To implement this, we need to modify our ssh config file (add ProxyJump ) as shown below:

$ cat ~/.ssh/config

Host jump_server
    User mike
    HostName 1.1.1.1
    Port 49823
    IdentityFile ~/.ssh/id_rsa

Host one_alias
    User mike
    HostName 1.1.1.1
    Port 49823
    IdentityFile ~/.ssh/id_rsa
    ProxyJump jump_server

By utilizing the ssh config file and specifying ProxyJump, we can establish a chain connection automatically: first connecting to jump_server and then connecting from there to one_alias. This allows us to access the desired server by simply using ssh one_alias, even if there is a jump server separating our network between one_alias and our ssh client.

Level 3: ssh-agent

We often use an SSH key pair for authentication when connecting to servers or cloning a GitHub repository. Therefore, it is crucial to safeguard our private key file from being leaked. If the private key file is compromised, unauthorized individuals can gain access to our private server or GitHub repository, posing a significant risk.

Protect the private key using passphrase

When using ssh-keygen to create a key pair with default parameters, it will generate an RSA key pair without a passphrase. Having a key file without a passphrase means that your private content is unprotected and anyone with access to this file can view it. Therefore, the first step is to protect our private key by setting a strong passphrase. When prompted by ssh-keygen, please input a robust password!

ssh-keygen -t rsa -f ~/.ssh/newkeys/test_rsa_key  -C "xxxxx"

You can also use ed25519 algorithm to create key, which is more secure and have better performance.

ssh-keygen -t ed25519 -f ~/.ssh/newkeys/test_ed25519_key -C "xxxxx"

After setting a passphrase, you will need to enter it each time you use this private key in order to unlock it. Even if the private key file is leaked, others cannot use your private key unless they also know the passphrase for that specific key file.

Use ssh-agent to temporarily store the unlock key.

The obstacle to use passphrase is the trouble of enter the passphrase. And the ssh-agent just solve this trouble.

Step 1: we can add some private key into ssh-agent by this command. You need to enter the passphrase to unlock the private key.

ssh-add ~/.ssh/newkeys/test_ed25519_key

Step 2: we can use ssh-add -L to list the public key of the private key we have added.

After we add the private key into the ssh-agent, we can use this private key without the trouble of enter passphrase !

We should note that when we reboot our computer, we need to re-add the private key and re-enter the passphrase.

Leverage MacOS Keychain to store the passphrase

To store the passphrase in the MacOS Keychain and allow ssh-agent to retrieve it, follow these steps:

Step 1: Add the private key using the --apple-use-keychain option.

ssh-add --apple-use-keychain ~/.ssh/newkeys/test_ed25519_key

You can open Keychain Access on your MacOS device and search the stored passphrase within that application. ( just a check)

Step 2: Whenever you use ssh-add --apple-load-keychain, all private keys already stored in the keychain will be loaded.

Step 3: You also need to modify the ssh config , add UseKeychain yes and let ssh know it should use keychain.

Step 4: You can use AddKeysToAgent yes and tell the ssh to add the key in the ssh-agent on demand.

$ cat ~/.ssh/config

Host jump_server
    User mike
    HostName 1.1.1.1
    Port 49823
    UseKeychain yes
    AddKeysToAgent yes
    IdentityFile ~/.ssh/newkeys/test_ed25519_key

Host one_alias
    User mike
    HostName 1.1.1.1
    Port 49823
    UseKeychain yes
    AddKeysToAgent yes
    IdentityFile ~/.ssh/newkeys/test_ed25519_key
    ProxyJump jump_server

Make sure the key is loaded automatically

To ensure that the key is automatically loaded into the ssh-agent, you can also append these lines to either ~/.zshrc or ~/.bashrc:

{ eval "$(ssh-agent -s)"; ssh-add --apple-load-keychain; } &>/dev/null

This will load the key every time you start a terminal session.

Level 4: forward ssh-agent

If you want to clone your private GitHub repository on a remote server that does not have permission to access it, what should you do?

One option is to create a new key pair on the remote server and add this key pair to your GitHub account. However, this can be risky as anyone on the server could potentially access your new key pair and gain access to your private content.

To avoid this risk, you can use ssh-agent for authentication. By forwarding the local ssh-agent to the remote server, it can utilize your local ssh-agent without exposing any private keys on the remote server. ( details in Using SSH agent forwarding - GitHub Docs )

To enable this feature, simply add ForwardAgent yes to your ssh config file. For example:

$ cat ~/.ssh/config

Host jump_server
    User mike
    HostName 1.1.1.1
    Port 49823
    UseKeychain yes
    AddKeysToAgent yes
    IdentityFile ~/.ssh/newkeys/test_ed25519_key

Host one_alias
    User mike
    HostName 1.1.1.1
    Port 49823
    UseKeychain yes
    AddKeysToAgent yes
    ForwardAgent yes
    IdentityFile ~/.ssh/newkeys/test_ed25519_key
    ProxyJump jump_server

After executing the ssh one_alias, you can check whether the ssh-agent forward is enabled by these commands in the one_alias server.

echo "$SSH_AUTH_SOCK"
ssh-add -L

There are a few important points to consider. It is recommended that you only forward the ssh-agent to your trusted server, as others may find and use your ssh-agent connection socket for authentication. However, this is still better than someone directly obtaining your key file. The risk of ssh-agent forwarding exists only when you have established a connection with the remote server; once you disconnect from the server, the risk disappears.

How to reproduce this risk ?

find the path of ssh-agent socket (like /tmp/ssh-XXXXjxmBlW/agent.388161)

When you export SSH_AUTH_SOCK=/tmp/ssh-XXXXjxmBlW/agent.388161 in your terminal session with the same user account, you can use this ssh-agent to authentication. (other account do no have permission to connect this socket.)

Conclusion

Now you can use the key pair with enhanced security and convenience!

  1. The private key file is protected by a passphrase.
  2. The passphrase is stored in the MacOS keychain, which is also secure.
  3. You do not need to enter the passphrase every time because ssh will retrieve it from the MacOS keychain.
  4. You can utilize your local ssh-agent to authenticate yourself when accessing private information on remote servers (e.g., ssh or git) without the need to expose any key files.

Reference

  1. 脱线道士维克多 - macOS 配置 ssh-agent
  2. Generating a new SSH key and adding it to the ssh-agent - GitHub Enterprise Cloud Docs
  3. Using SSH agent forwarding - GitHub Docs
  4. 使用 Ed25519 算法生成你的 SSH 密钥 - 知乎

Instead of authenticating the giscus application, you can also comment directly on GitHub.


Notes mentioning this note