ssh密钥认证技术背景
SSH协议密钥认证:SSH 协议支持使用密钥方式认证,正确的使用完全可以替代密码登录,达到既便捷又安全的目标。SSH 的密钥认证是基于非对称加密算法的认证方式,其使用数字签名校验替代密码比对实现用户认证,算法安全性由非对称加密算法本身决定,密钥一般随机生成长度远大于人工可以记忆或有限时间能够枚举的数据长度,从理论上难于被暴力破解。
测试环境
下面我将使用windows10系统和kali系统演示ssh协议密钥认证实现的过程。
window 10(IP:192.168.56.1)系统作为客户端,
kali(IP:192.168.56.3)系统作为ssh要连接的服务器。
使用密钥认证登录 SSH 服务,首先要在客户端电脑上生成 SSH 密钥对。在 Linux、MacOS、BSD、Windows 10/11 主机上,我们使用 OpenSSH中的 ssh-keygen 工具完成这件工作。
进入windows电脑的.ssh目录,按住shift,同时鼠标右键打开"在此处打开powershell窗口。
生成密钥文件
输入ssh-keygen(会提示键值对保存的位置,密钥文件的密码123456,如果不设置密码可以实现免密登录):
查看已经生成了密钥对:id_ed25519(私钥)和id_ed25519.pub(公钥),采用加密算法为ED25519 。
默认情况下,ssh-keygen 将为用户生成 RSA 算法的密钥对,长度为 3072 位。生成密钥时,会提示用户提供密码对私钥加密,不同于用户口令,这个密码仅在本地使用,用于防止私钥泄漏。当然,如果对自己电脑安全完全有信心,私钥也可以不加密存放(不建议)。工具ssh-keygen一般不需要添加参数运行,根据 Linux系统安全理念,成熟的发行版本应实现默认即安全,即用默认参数运行时就能获得安全的结果。需要注意的是,生成的密钥对中,~/.ssh/id_ed25519.pub 是公钥,无需保密;~/.ssh/id_ed25519 是私钥,要时刻保密,不能与他人分享。如果有多台电脑需要访问服务器,应该在每台电脑上使用上述过程生成自己的独立密钥对,而不是将私钥复制到每台电脑上。
从文件名称可以看出,我们生成的是ed25519密钥,我们也可以选择其他算法,从而生成其他类型的密钥文件,但是我们在生成秘钥时并未指定算法类型,所以,默认生成了ED255129类型的密钥,现在大家都在版本2的ssh协议,在版本2的ssh协议中我们可以使用的密钥类型有: "dsa", "ecdsa", "ed25519", "rsa"。
如下:使用-t生成其他类型的密钥对:
ssh-keygen -t dsa
将公钥文件导入到要连接的服务器
我们已经拥有了自己的私钥与公钥,但是,我们并没有把公钥交给任何人,所以,其他人还无法利用我们的公钥对我们进行认证。 比如,我们需要在window10客户端(IP192.168.56.1)连接kali系统的root用户(IP192.168.56.3)。
下一步是将生成的公钥使用ssh-copy-d命令发送到kali机器中,centos6中要在“”添加用户名主机名:
(OpenSSH 服务器在默认情况下已经支持密钥登陆,只要我们将生成的公钥内容添加到服务器指定位置,即可开始使用密钥认证方式。上传公钥到服务器有两种方法,一种是使用 ssh-copy-id 命令自动完成(推荐),也可以手动添加。使用 ssh-copy-id 时,命令行参数与使用 ssh 命令登陆服务器完全相同,直接运行。)
windows命令行powershell中,无法使用ssh-copy-id解决方法(直接复制到powershell中运行:
function ssh-copy-id([string]$userAtMachine, $args){
$publicKey = "$ENV:USERPROFILE" + "/.ssh/id_rsa.pub"
if (!(Test-Path "$publicKey")){
Write-Error "ERROR: failed to open ID file '$publicKey': No such file"
}
else {
& cat "$publicKey" | ssh $args $userAtMachine "umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys || exit 1"
}
}
kali中已经可以查看上传的公钥信息,在authorized.keys文件中。
使用密钥文件登录服务器
使用ssh root@192.168.56.3 -i id_rsa 登录到kali系统中,按照提示输入密钥文件的密码123456。
另外,也可以手工将公钥文件上传到要连接的服务器中:
cat ~/.ssh/id_rsa.pub | ssh username@server_address "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod -R go-rwx ~/.ssh"
命令执行成功时,除了服务器用户认证时输入密码的提示,不会有其它提示。
在服务器上,授权的用户公钥保存于~/.ssh/authorized_keys文件中,上述命令做了三件事 ,一是如果~/.ssh 目录不存在,则创建它;二是将公钥保存在~/.ssh/authorized_keys 文件中;三是修正存放密钥的目录的权限,确保用户以外无人可以访问其中内容。这也是ssh-copy-id 实际完成的工作。
在centos6与centos7中,使用ssh-copy-id指定sshd服务器端口的方法略有不同,假设对方sshd服务器端口号为22222,示例如下
当前系统为centos6:
ssh-copy-id -i ~/.ssh/id_rsa.pub "zsy@192.168.0.221 -p 22222"
当前系统为centos7:
ssh-copy-id -i ~/.ssh/id_rsa.pub zsy@192.168.0.221 -p 22222
关闭密码登录功能:
密钥登陆设置成功后,我们建议关闭密码登陆方式,防止外部暴力破解攻击。关闭密码登陆可以通过编辑 SSH 服务端配置文件完成。使用常用编辑器打开/etc/ssh/sshd_config 文件(需要管理员 root权限)。
vi /etc/ssh/sshd_config
#PasswordAuthentication yes
改为
PasswordAuthentication no
#重启ssh服务
systemctl reload sshd
#或者
service sshd reload
相关命令总结:
ssh-keygen
#上述命令表示在完全交互的模式下生成密钥对
ssh-keygen -f /testdir/test/id_rsa
#上述命令表示在/testdir/test目录下生成私钥id_rsa以及对应的公钥,-f选项表示直接指定密钥生成位置以及密钥的名称,但是还是会交互式的提示用户为私钥设置密码,自定义密钥生成位置与名称后,在使用ssh命令连接到对应主机时,可以使用-i选项指定对应的密钥,比如:
ssh -i /testdir/id_rsa_zsy_testkey zsy@192.168.50.50
ssh-keygen -P '123456' -f /testdir/test/id_rsa
#上述命令表示在/testdir/test目录下生成私钥id_rsa以及对应的公钥,并且为将私钥的密码设置为123456,-P (大写P)表示指定私钥的密码,上述命令不会进入交互模式,所以用户不用输入任何信息即可生成密钥对,如果想要生成没有密码的私钥,只需要将 -P '123456' 改为 -P '' 即可。
ssh-keygen -f /testdir/test/id_rsa -p
#上述命令表示为私钥设置新密码,-p(小写p)表示为私钥设置新密码,无论私钥原来是否有密码,都可以使用此命令对私钥设置新密码,输入上述命令后,会进入交互模式,如果原来私钥没有密码,则会直接提示输入新密码,即为私钥添加密码,如果私钥原来就有密码,则会提示先输入老密码,再提示输入新密码,即为修改私钥密码,如果私钥原来就有密码,现在想要取消原来的密码,只需要在提示输入新密码时直接回车即可。
ssh-keygen -t dsa -P '' -f /testdir/test/id_dsa
#上述命令表示生成dsa类型的密钥对,-t选项表示指定密钥的类型,即指定算法,版本2的ssh协议可以指定的密钥类型有 "dsa", "ecdsa", "ed25519", "rsa"
ssh-keygen -t rsa -b 1024 -P '' -f /testdir/test/id_rsa
#上述命令表示生成1024位长的密钥,-b用于指定密钥的位数。
ssh-keygen -f /testdir/test/id_rsa -y
#上述命令表示根据私钥生成对应的公钥,-y选项表示根据私钥生成对应的公钥,生成的公钥会打印在屏幕中,我们可以使用重定向生成公钥文件。
ssh-keygen -f /testdir/test/id_rsa -y > id_rsa.pub
#如果私钥有密码,则需要在生成公钥是提供密码,用户需要在交互式模式中输入密码,如果不想使用交互式输入密码,可以使用-P选项(大写P)提供密码。
ssh-copy-id -i ~/.ssh/id_rsa.pub zsy@10.1.0.3
#将公钥加入到指定账户的认证文件中
#当ssh服务器未使用默认端口号时,使用如下命令
centos6中:ssh-copy-id -i ~/.ssh/id_rsa.pub "zsy@10.1.0.3 -p 22222"
centos7中:ssh-copy-id -i ~/.ssh/id_rsa.pub zsy@10.1.0.3 -p 22222
#-i 选项用于指定公钥文件
#- p 选项用于指定ssh服务器的端口号