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!
- The private key file is protected by a passphrase.
- The passphrase is stored in the MacOS keychain, which is also secure.
- You do not need to enter the passphrase every time because ssh will retrieve it from the MacOS keychain.
- 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
- 脱线道士维克多 - macOS 配置 ssh-agent
- Generating a new SSH key and adding it to the ssh-agent - GitHub Enterprise Cloud Docs
- Using SSH agent forwarding - GitHub Docs
- 使用 Ed25519 算法生成你的 SSH 密钥 - 知乎