Pages

Wednesday, 16 August 2023

对你个人电脑上的SSH私钥进行加密

 背景 - 为什么要使用 SSH 密钥并对其加密 ?#

    先来抛出三个论点, 要不想看理由可以直接跳到操作步骤,应该不需要 2 分钟就能操作完成了。

第一点 - 应该使用 SSH 密钥而不是密码#

在日常的工作中,我们频繁地与诸如 git、rsync 和 ssh 等工具打交道,传统的密码身份验证方式可能会变得麻烦且容易受到攻击。

    传统的密码输入方式可能会被窥视者观察到,从而导致安全性问题:而 SSH 密钥在传输过程中进行了加密,大大减少了窥探风险。
    在多台远程服务器上使用不同密码,可能会导致密码的混淆和遗忘:而使用 SSH 密钥,你只需要管理少数几个密钥对,大大简化了密码管理的复杂性。
    使用密码登录远程服务器存在被恶意攻击者轻易攻击的风险:而 SSH 密钥的使用使得攻击者更难伪造身份进行访问,提高了远程服务器的安全性。

第二点 - 任何情况下 SSH 私钥都要加密#

即使使用 SSH 密钥,仍然需要注意私钥的保护。不要贪方便不给 SSH 私钥加密~~(很多人都是这样吧?)

    SSH 密钥对中的私钥是身份验证的核心,它等同于你系统和数据的主门钥匙:如果私钥暴露,恶意方可能通过伪造你的身份来访问系统、窃取敏感信息,甚至进行未授权的操作。
    无论是在本地计算机、移动设备还是通过网络传输,私钥可能会在非安全环境中存在:通过加密私钥,即使私钥在未经授权的情况下被访问,也不会立即暴露你的数据和系统。
    如果你的设备遭到盗窃、丢失或被他人访问,加密的私钥会提供额外的安全层:即使恶意者能够获得私钥文件,其加密状态仍将阻碍其直接使用。
    恶意软件和病毒可能会扫描你的系统以寻找未加密的私钥文件:例如大家电脑上总会有几个盗版软件吧?如果私钥加密,它们无法轻易获取到敏感信息,从而减少了受到攻击的风险。

    有时候甚至有人贪方便将明文私钥用 QQ 还是什么的来传输到另外的电脑,这其实是很危险的行为。这可是明文的私钥~~

第三点 - 使用 SSH-Agent 减少输入密码的次数#

单纯使用加密的私钥其实并不能真正解决输入密码的问题,它只是将你所有的密码扭成用同一个密码而已。 而且我们也不可能每一次 git pull 代码都输入一次私钥的密码吧。所以为了解决频繁输入密码的繁琐性以及密码泄露的风险,SSH-Agent 是一个强大的工具,可以显著提升用户体验和系统安全性。以下是使用 SSH-Agent 的一些理由:

    SSH-Agent 可以在用户会话中暂时存储解密的私钥,使得用户只需在会话开始时输入一次密码:之后的连接将自动使用已解密的私钥,从而大幅减少了密码输入的需求,提高了操作效率。
    每次输入密码都存在泄露风险,而 SSH-Agent 可以有效降低这种风险:用户只需在会话开始时输入密码,之后的连接都在加密的私钥的保护下进行,避免了密码被窥视或截获的可能性。
    对于需要频繁与多个远程服务器交互的用户,SSH-Agent 可以显著提高工作效率:用户可以一次性输入密码,然后无需重复输入,轻松地在不同的服务器之间切换。
    ...

    BOSS 语录: agent 本质是把 key 加载到内存了,内存泄漏 key 的可能性是有,但是需要非常复杂的方式和漏洞,也要一定的权限,而且现在 os 都有内存地址随机化来抵抗了

操作步骤#
对本地私钥进行加密#

此处假设你本地已经有现成的 SSH 密钥对了。(使用 GitHub 的大家应该都是有的吧。没有的话可以使用 ssh-keygen 生成,或者看文末的 SSH 相关的文章)

下面这个就是对本地私钥进行加密的命令(<id_rsa_path> 是你本地的 ssh 私钥的路径,一般为 ~/.ssh/id_rsa)

ssh-keygen -p -f <id_rsa_path>

好了,这就完成加密了。下一步就是启动 ssh-agent。
使用 SSH-Agent 管理解密的私钥#

这就是简易的 启动 ssh-agent 并将你电脑上的默认的密钥对加载到 agent 里面的 Shell 代码:

if [ -z "$SSH_AUTH_SOCK" ] ; then
    eval `ssh-agent`
    ssh-add # <id_rsa_path>,不加就是用默认值
fi

但其实这种使用方式是有很多问题的,你重新开一个 Shell 的会话 agent 就要重新开了,并且你前面的会话结束的时候要是没有关 agent ,那么该 agent 会一直存活在你电脑的进程里面。
持久化 SSH-Agent 设置以实现便利和安全#

⚠️⚠️⚠️ 注意:该方案仅仅适合于个人电脑 ⚠️⚠️⚠️

要解决上述问题,我们建议将 SSH-Agent 的启动设置添加到你的 shell 配置文件中,以便每次开启终端会话时都能自动启动 SSH-Agent 并加载你的私钥。这将提供更大的便利性和安全性。

下面是一个示例代码,请将它添加到添加到你的 ~/.bashrc 或 ~/.bash_profile 文件中( zsh 则是 ~/.zshrc 或 ~/.zprofile,我个人是推荐放 rc 文件里面的,毕竟很多情况下是触发不了 login shell 的机制的):

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

(这就是 stackoverflow 里面的高分例子,稍微微调了一下有效时间,电脑一直不关机的话,一天需要打一次密码。虽然会在 ssh forward 情况下存在问题,但个人电脑用是绰绰有余了)

这段代码将在每次开启 shell 会话时检查 SSH-Agent 是否已运行。如果没有运行,它将自动启动并加载你的私钥。 通过这种方式,你将始终享受到 SSH-Agent 带来的便利和安全性。(真看不懂可以找找 ChatGPT, 其实关键就在于用文件存起来了 SSH-Agent 的 SSH_AUTH_SOCK 等信息,让其他的 shell 的会话也可以读的到)

    好了,其实操作就上面那么多

使用 ssh-agent 的注意事项#

当然,使用 ssh-agent 其实也不是说就真的特别安全然后没有后顾之忧了, 其实使用 ssh-agent 还是会有很多问题的。以下就是使用 ssh-agent 的一些注意事项

    切勿在其他人拥有 root 权限的计算机上运行 ssh-agent: 如果在受信任程度较低的计算机上运行 ssh-agent,恶意用户可能通过 ssh-agent 访问你的私密数据,从而危及你的安全。(日常不使用电脑的时候也要进行锁屏,共用的电脑也不要运行)
    代理连接转发的谨慎使用:ssh-agent 可以允许代理连接转发,这在某些情况下非常方便。然而,只应该将代理连接转发到你信任的计算机上,以防止你的私密数据被不可信的主机获取。
    注销时卸载密钥和代理:在你注销计算机或退出 shell 会话时,请确保已卸载密钥和 ssh-agent 以避免无授权的访问。这可以通过使用 ssh-agent -k 命令来实现。
    切勿将你的私钥复制到其他人拥有 root 权限的计算机上:如果这样做,你只是与该人共享了你的密钥。

使用 ssh-agent 时,请遵循以上注意事项以确保你的私密数据和系统安全。 虽然 ssh-agent 提供了便捷性和保护性,但仍然需要用户的谨慎操作来最大程度地减少潜在的安全风险。同时,了解并采取适当的安全措施将有助于提高你的网络安全意识和保护你的私密数据免受威胁。
后记#

其实管理 ssh 密钥的方案不单单是 ssh-agent , 还可以试一下用 1password 的 cli , 虽然说我没怎么用过。

这篇文章,怎么说呢,其实也就只是我本人的一些安全记录而已,很有可能是在班门弄斧。这一个后面应该会写成一个系列吧,CyberSecurity 系列,尽量就是将我生活当中的一些网络安全的知识给用上。将这个一点一点地记下来,虽然很多。

    注意:本文所述内容仅代表个人观点和经验分享,并非绝对准确的安全建议。如需更详细和专业的安全建议,请咨询安全专家或相关文献资料。

参考资料:

  1. SSH 教程 - 网道: 关于 ssh 的基础知识可以看阮一峰的这个教程
  2. Using an ssh-agent, or how to type your ssh password once, safely., 里面有提到了 ssh-agent 在堡垒机的转发的场景,我这边没有对应的使用场景,于是我文章里面就不提了。
  3. The pitfalls of using ssh-agent, or how to use an agent safely, 与上面文章是同一个作者,说到了一些使用 ssh-agent 的注意事项。

-------------------------------------------------------------------------------

 ssh 的 UNPROTECTED PRIVATE KEY FILE问题的解决

问题#

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/home/chris/.ssh/id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/home/chris/.ssh/id_rsa": bad permissions

无法使用 ssh 的私钥,出现如上提示。
解决#
chmod 0700 ~/.ssh/id_rsa
把路径换成自己的私钥路径即可。

前情#
我在重装了 wsl 之后想要把 Windows 正在用到的 ssh key 放到 wsl 里,就直接在文件资源管理器中粘了过去。但是这样的方法导致的文件权限是 0644,也就是说任意用户都可以看、只有所有者用户可以更改,这样不安全的权限会让 sshd 罢工不用这个私钥,导致无论是 ssh 到 vps 还是 git 操作都无法完整进行。解决方案也很简单:权限改下就好。

完整方法
以下内容来自 SSH Error “permissions are too open” for Private Key File:https://www.baeldung.com/linux/ssh-key-permissions,原作者 Hiks Gerganov:https://www.baeldung.com/linux/author/hiksgerganov

1. 简介#
密钥是 Secure Shell (SSH):https://www.baeldung.com/cs/ssh-intro 协议的一部分。实际上,如果使用正确,它们可以提供额外的安全层级。

在本教程中,我们将探讨 SSH 密钥的权限问题。首先,我们生成密钥并配置它们以供给定用户访问。接下来,我们讨论适当的密钥权限。最后,我们将解释如何更正密钥的权限并测试结果。

为简洁和安全起见,我们仅考虑由 OpenSSH 实现的 SSH 版本 2(SSHv2)的最新迭代。

我们在 Debian 11 (Bullseye) 上使用 GNU Bash 5.1.4 测试了本教程中的代码。它应该可以在大多数符合 POSIX 标准的环境中工作。

2. 生成密钥#
首先,让我们使用默认设置生成一些密钥:

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/baeldung/.ssh/id_rsa):
Created directory '/home/baeldung/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/baeldung/.ssh/id_rsa
Your public key has been saved in /home/baeldung/.ssh/id_rsa.pub
The key fingerprint is:
[...]

此时,正如输出所述,我们有一组两个密钥:

    公钥:/home/baeldung/.ssh/id_rsa.pub
    私钥:/home/baeldung/.ssh/id_rsa

重要的是,这些是基于用户(baeldung)的主目录(/home)的默认位置:$HOME (https://www.baeldung.com/linux/tilde-bash)

为了简单起见,我们将本地机器用作 SSH 会话的客户端和服务器。因此,我们将公钥添加到我们的用户的 authorized_keys(https://www.baeldung.com/linux/copy-ssh-keys#manual-copy)文件中:
cat /home/baeldung/.ssh/id_rsa.pub >> /home/baeldung/.ssh/authorized_keys
现在,让我们使用我们的新密钥。

3. 私钥权限#
在创建和设置密钥之后,我们只需连接到 localhost (https://www.baeldung.com/cs/127-0-0-1-vs-localhost):

$ ssh localhost
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0777 for '/root/.ssh/id_rsa' are too open.
It is required that your private key

 files are NOT accessible by others.
This private key will be ignored.
Load key "/root/.ssh/id_rsa": bad permissions
[...]

在这种情况下,我们遇到了一个错误,它指出我们的私钥具有错误的权限(https://www.baeldung.com/linux/cd-without-permission#checking-and-changing-directory-permissions)。具体而言,SSH 客户端不允许使用可以被其他人访问的私钥。

我们使用 ls命令(https://man7.org/linux/man-pages/man1/ls.1.html)来检查私钥的当前权限:

$ ls -l /home/baeldung/.ssh/id_rsa
-rwxrwxrwx 1 baeldung baeldung 2590 Oct 10 06:56 /home/baeldung/.ssh/id_rsa

这里,第三和第四列告诉我们 baeldung 是所有者的用户名和组名。第一列告诉我们所有者、所有者组的成员以及其他所有人都对我们的私钥文件 /home/baeldung/.ssh/id_rsa 拥有完全权限,例如 模式(https://www.baeldung.com/linux/chown-chmod-permissions#chmod) 为 0777。

如果我们追求适当的安全性,这是不可接受的。

4. 更正私钥权限#
正如我们之前看到的错误文本解释的那样,要求是我们的私钥文件 “不可被其他人访问”。换句话说,我们需要为每个私钥文件设置两个极端之间的模式:
    0400,最严格的,例如,只允许所有者读取权限
    0700,最不严格的,例如,只允许所有者完全权限

基本上,我们不能为任何非所有者用户提供任何权限,但所有者仍然必须能够至少读取这些文件。在这种情况下,我们使用 chmod 命令应用最严格的访问权限:
$ chmod 0400 /home/baeldung/.ssh/id_rsa
$ ssh localhost
[...]
baeldung $

最后,让我们看看当我们通过 chown命令(https://www.baeldung.com/linux/chown-chmod-permissions#chown)更改所有者时会发生什么:
$ chown user1:user1 /home/baeldung/.ssh/id_rsa
$ ls -l /home/baeldung/.ssh/id_rsa
-r-------- 1 user1 user1 2590 Oct 10 06:56 /home/baeldung/.ssh/id_rsa

此时,如果我们是 root(https://www.baeldung.com/linux/list-all-superusers),SSH 将允许我们继续操作,因为有以下几个事实:
    作为 root,我们对所有文件都有权限
    就 SSH 客户端而言,文件权限实际上是准确的(0400)

事实上,作为 root,我们只需通过 -l 选项或使用 user@ 语法指定正确的用户,以及使用 -i 标志指定密钥,即可完成设置。

5. 公钥权限#

作为私钥主要问题的附带说明,我们可能会问是否公钥也适用于这些权限要求。实际上,有建议但没有普遍规定。

在大多数情况下,最好保护密钥的本地副本免受第三方的修改。基本上,这意味着建议的模式介于两个极端之间:

    0400,与之前一样,仅允许所有者读取密钥
    0744,使所有者能够

实际上,下限允许进行操作而不进行修改,并阻止外部用户,而上限至少可以防止外部修改。

无论如何,一旦我们的公钥在远程机器的 authorized_keys 文件中,我们实际上不需要它来登录 - 我们只需要私钥。

6. 总结#
本文介绍了 SSH 密钥的权限问题,以及它们可能引起的问题以及如何更正它们。
总之,SSH 客户端可以并且应该为存储和使用私钥定义严格的规则,因为它们可以被视为密码的等效物


 



   

No comments:

Post a Comment