Background - Why Use SSH Keys and Encrypt Them?#
Let's start with three reasons. If you don't want to read them, you can skip directly to the steps. (It takes less than 2 minutes to complete)
First - Use SSH Keys Instead of Passwords#
In our daily work, we frequently deal with tools like git
, rsync
, and ssh
. Traditional password authentication methods can be cumbersome and vulnerable to attacks. There may be the following issues:
- Risk of Eavesdropping: Traditional password input methods can be observed by onlookers, leading to security issues. Using SSH keys eliminates the need to enter passwords, greatly reducing the risk of eavesdropping.
- Complexity of Password Management: Using different passwords on multiple remote servers can lead to confusion and forgetfulness. With SSH keys, you only need to manage a few key pairs, greatly simplifying password management complexity.
- Security of Remote Servers: Logging into remote servers with passwords exposes the risk of being easily attacked by malicious attackers. The use of SSH keys makes it more difficult for attackers to forge identities and access remote servers, thereby improving the security of remote servers.
Second - Encrypt SSH Private Keys in Any Situation#
Even when using SSH keys, it is still important to protect the private keys. Don't take the convenience of leaving SSH private keys unencrypted. (Many people do this, right?)
- Private Key is the Core of Authentication: It is equivalent to the master key of your system and data. If the private key is exposed, malicious parties may access the system, steal sensitive information, or perform unauthorized operations by impersonating you.
- Private Key May Exist in Insecure Environments: Whether it's on a local computer, mobile device, or transmitted over a network, these environments are insecure. By encrypting the private key, even if it is accessed without authorization, your data and system will not be immediately exposed.
- In Case of Theft, Loss, or Unauthorized Access to the Device: Encrypted private keys provide an additional layer of security. Even if an attacker gains access to the private key file, its encrypted state will hinder its direct use.
- Malware and Viruses: They may scan your system to find unencrypted private key files. For example, there may be several pirated software on your computer, right? If the private key is encrypted, they cannot easily obtain sensitive information, thereby reducing the risk of being attacked.
Sometimes people even send plaintext private keys to other computers using QQ or something similar, which is very dangerous. It's a plaintext private key~~
Third - Reduce Password Input with SSH-Agent#
Using an encrypted private key alone does not completely solve the problem of password input. It simply transforms all your passwords into one. We don't want to enter the password for the private key every time we git pull
, right? So, to solve the inconvenience of frequent password input and the risk of password leakage, we introduce SSH-Agent here.
It can temporarily store decrypted private keys, allowing users to enter the password only once at the beginning of the session, and subsequent connections will automatically use the decrypted private key. This greatly reduces the number of password inputs and avoids the possibility of password eavesdropping or interception. It also significantly improves work efficiency for users who need to interact frequently with multiple remote servers.
BOSS Quote: The agent essentially loads the key into memory. There is a possibility of memory leakage of the key, but it requires complex methods, vulnerabilities, and certain permissions. Moreover, modern operating systems have randomization of memory addresses to resist this.
Steps#
Encrypt the Local Private Key#
Assuming you already have an existing SSH key pair locally (those who use GitHub should have one, if not, you can generate one using ssh-keygen
or refer to the SSH-related articles at the end of the document).
Below is the command to encrypt the local private key (<id_rsa_path>
is the path to your local SSH private key, usually ~/.ssh/id_rsa
):
ssh-keygen -p -f <id_rsa_path>
Alright, encryption is complete. The next step is to start the ssh-agent.
Use SSH-Agent to Manage Decrypted Private Keys#
Here is a simple shell code to start ssh-agent
and load your default key pair on your computer into the agent:
if [ -z "$SSH_AUTH_SOCK" ] ; then
eval `ssh-agent`
ssh-add # <id_rsa_path>, add if you want to use a different path
fi
However, this method has many issues. If you open a new shell session, the agent needs to be restarted. If you don't close the agent when ending the previous session, it will continue running as a process on your computer.
Persist SSH-Agent Settings for Convenience and Security#
⚠️⚠️⚠️ Note: This solution is only suitable for personal computers ⚠️⚠️⚠️
To address the above issues, we recommend adding the SSH-Agent startup settings to your shell configuration file so that SSH-Agent can automatically start and load your private key every time you open a terminal session. This provides greater convenience and security.
Here is an example code, please add it to your ~/.bashrc
or ~/.bash_profile
file (for zsh, it's ~/.zshrc
or ~/.zprofile
. Personally, I recommend putting it in the rc file since the mechanism to trigger a login shell is often not met):
For fish shell, please see here
Please add it to this file ~/.config/fish/config.fish
set SSH_ENV_FILE "$HOME/.ssh/agent-environment"
set SSH_TIMEOUT 86400 # 24 hours in seconds
function ssh_start_agent
ssh-agent -c -t "$SSH_TIMEOUT" > "$SSH_ENV_FILE"
chmod 600 "$SSH_ENV_FILE"
source "$SSH_ENV_FILE"
ssh-add # [<id_rsa_path>] Change to your path
end
if test -f "$SSH_ENV_FILE"
source "$SSH_ENV_FILE"
if not ps -p "$SSH_AGENT_PID" > /dev/null
ssh_start_agent
end
else
ssh_start_agent
end
SSH_ENV_FILE="$HOME/.ssh/agent-environment"
SSH_TIMEOUT=86400 # 24 hours in seconds
ssh_start_agent(){
ssh-agent -t $SSH_TIMEOUT | sed 's/^echo/#echo/' > "${SSH_ENV_FILE}"
echo "Initialising new SSH agent succeeded"
chmod 600 "${SSH_ENV_FILE}"
. "${SSH_ENV_FILE}"
ssh-add # [<id_rsa_path>] Change to your path
}
if [ -f "${SSH_ENV_FILE}" ]; then
. "${SSH_ENV_FILE}"
if ! ps -p "$SSH_AGENT_PID" > /dev/null; then
start_ssh_agent
fi
else
ssh_start_agent
fi
(This is a highly-rated example from Stack Overflow, with slight modifications to the expiration time. If your computer is always on, you only need to enter the password once a day. Although there may be issues with ssh forwarding, it is more than sufficient for personal computers.)
This code will check if SSH-Agent is running every time you open a shell session. If it is not running, it will automatically start and load your private key. This way, you will always enjoy the convenience and security provided by SSH-Agent. (If you don't understand, you can try using ChatGPT. The key is to store the SSH-Agent's SSH_AUTH_SOCK
and other information in a file so that other shell sessions can read it.)
Alright, that's all for the steps.
Considerations When Using ssh-agent#
Of course, using ssh-agent does not mean that all security concerns are eliminated. There are still many issues to consider when using ssh-agent. Here are some considerations when using ssh-agent:
- Do not run
ssh-agent
on a computer where others have root privileges: If you runssh-agent
on a computer with lower trustworthiness, malicious users may access your private data throughssh-agent
, compromising your security. (When you don't use your computer, remember to lock the screen and don't run it on shared computers) - Be cautious when using agent connection forwarding:
ssh-agent
allows agent connection forwarding, which is very convenient in certain situations. However, agent connection forwarding should only be used to trusted computers to prevent your private data from being obtained by untrusted hosts. - Unload keys and agent when logging out: When you log out of your computer or exit the shell session, make sure to unload the keys and
ssh-agent
to prevent unauthorized access. This can be done using thessh-agent -k
command.
When using ssh-agent
, please follow the above considerations to ensure the security of your private data and system.
Afterword#
In fact, managing SSH keys is not limited to ssh-agent. You can also try using the 1Password CLI, although I haven't used it much.
This article is just a record of my personal security practices and may be redundant for some. This will probably become a series in the future, the CyberSecurity series, to apply some of my knowledge of network security in my daily life.
Note: The content described in this article represents personal opinions and experiences and is not an absolute and accurate security advice. For more detailed and professional security advice, please consult security experts or relevant literature.
References#
- SSH Tutorial - WangDoc: For basic knowledge about SSH, you can refer to this tutorial by Ruanyifeng.
- Using ssh-agent and How to Safely Enter Password Only Once: This article mentions the scenario of ssh-agent forwarding in a bastion host, which I don't have a corresponding use case for, so I won't mention it in the article.
- Pitfalls of SSH Agents and How to Safely Use Forwarding: Written by the same author as the previous article, it discusses some considerations when using ssh-agent.
Updates#
- 2023-08-17 19:11 v0.7 Added fish version of the code
- 2023-08-22 22:17 v0.8 Received feedback from a colleague that there were too many bold parts, making the article look too fancy and affecting the reading experience. Therefore, I made changes.
- 2023-08-22 23:05 v1.0 Made minor adjustments and removed some unnecessary words. It should be passable now.