赞
踩
简单说,SSH是一种网络协议,用于计算机之间的加密登录。需要指出的是,SSH只是一种协议,存在多种实现,既有商业实现,也有开源实现。SSH的默认端口是22,也就是说,你的登录请求会送进远程主机的22端口。SSH之所以能够保证安全,原因在于它采用了公钥加密
。整个过程是这样的:(1)远程主机收到用户的登录请求,把自己的公钥发给用户。(2)用户使用这个公钥,将登录密码加密后,发送回来。(3)远程主机用自己的私钥,解密登录密码,如果密码正确,就同意用户登录。
上面那个过程本身是安全的,但是实施的时候存在一个风险:如果有人截获了登录请求,然后冒充远程主机,将伪造的公钥发给用户,那么用户很难辨别真伪。因为不像https协议,SSH协议的公钥是没有证书中心(CA)公证的,也就是说,都是自己签发的。
可以设想,如果攻击者插在用户与远程主机之间(比如在公共的wifi区域),用伪造的公钥,获取用户的登录密码。再用这个密码登录远程主机,那么SSH的安全机制就荡然无存了。这种风险就是著名的"中间人攻击"(Man-in-the-middle attack)。
SSH协议是如何应对的呢?
如果你是第一次登录对方主机,系统会出现下面的提示:
$ ssh user@host
The authenticity of host 'host (12.18.429.21)' can't be established.
RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d.
Are you sure you want to continue connecting (yes/no)?
这段话的意思是,无法确认host主机的真实性,只知道它的公钥指纹,问你还想继续连接吗?
所谓"公钥指纹",是指公钥长度较长(这里采用RSA算法,长达1024位),很难比对,所以对其进行MD5计算,将它变成一个128位的指纹。
很自然的一个问题就是,用户怎么知道远程主机的公钥指纹应该是多少?回答是没有好办法,远程主机必须在自己的网站上贴出公钥指纹,以便用户自行核对
。
假定经过风险衡量以后,用户决定接受这个远程主机的公钥。
Are you sure you want to continue connecting (yes/no)? yes
系统会出现一句提示,表示host主机已经得到认可。
Warning: Permanently added 'host,12.18.429.21' (RSA) to the list of known hosts.
然后,会要求输入密码。
Password: (enter password)
如果密码正确,就可以登录了。
当远程主机的公钥被接受以后,它就会被保存在文件$HOME/.ssh/known_hosts之中。下次再连接这台主机,系统就会认出它的公钥已经保存在本地了,从而跳过警告部分,直接提示输入密码。
每个SSH用户都有自己的known_hosts文件,此外系统也有一个这样的文件,通常是/etc/ssh/ssh_known_hosts,保存一些对所有用户都可信赖的远程主机的公钥。
SSH主要用于远程登录。假定你要以用户名user,登录远程主机host,只要一条简单命令就可以了。
$ ssh user@host // 或者 ssh root@公网IP
使用密码登录,每次都必须输入密码,非常麻烦。好在SSH还提供了公钥登录,可以省去输入密码的步骤。
ssh-keygen
默认名称为id_rsa和id_rsa.pub,也可以自定义名称,方便区分,例如:
在上面截图里的.ssh文件夹下有个authorized_keys文件,这个代表授权的key,也就是你往目标登录主机上放的公钥。
scp id_ed25519.pub root@公网IP:/root/.ssh
cat >> authorized_keys < id_xxx.pub
systemctl restart sshd
Serveo 是一款免费的 SSH 隧道服务,可以将内网服务映射到公网上,以便外部用户能够访问。以下是使用 Serveo 的简单步骤:
ssh -R 80:localhost:8080 serveo.net
这将将本地的 8080 端口映射到 Serveo 提供的公网域名上的 80 端口。
Serveo 将为您生成一个随机的公网域名,并将其与您的本地服务绑定。例如,Serveo 可能会生成一个类似于 https://randomname.serveo.net
的域名。
您现在可以通过访问生成的公网域名来访问您的内网服务。例如,在上述示例中,您可以通过 https://randomname.serveo.net
访问本地的服务。
需要注意的是,Serveo 的免费服务是基于 SSH 隧道实现的,并且每次启动都会生成一个新的随机域名。如果您需要使用固定的公网域名或其他高级功能,则可能需要考虑使用其他付费的内网穿透工具或服务。
The authenticity of host ‘serveo.net (138.68.79.95)’ can’t be established.RSA key fingerprint is SHA256:07jcXlJ4SkBnyTmaVnmTpXuBiRx2+Q2adxbttO9gt0M.Are you sure you want to continue connecting (yes/no/[fingerprint])?
这是一个 SSH 连接时的提示信息
,询问您是否确认连接到指定的主机(serveo.net),并显示了该主机的 RSA 密钥指纹。您可以输入 “yes” 确认连接,然后您的 SSH 客户端会将该密钥指纹保存到本地,以便以后连接时进行验证。如果您不确定该密钥指纹是否正确,可以比对该指纹是否与服务提供商提供的指纹匹配。
上面的 RSA key fingerprint 是 SSH 服务器的公钥
经过某一个hash算法计算出来的值。
SSH 服务器的公钥指纹用于验证 SSH 服务器的身份,以确保客户端连接的是正确的服务器,而不是中间人攻击者伪造的服务器。在 SSH 连接时,客户端会将其保存在本地的已知主机列表中,以便将来连接时进行验证。
在第一次连接时,用户怎么知道远程主机的公钥指纹应该是多少?回答是没有好办法,远程主机必须在自己的网站上贴出公钥指纹,以便用户自行核对
。
下面以阿里云为例,我们通过密码登录云主机,查看云主机 /etc/ssh下面的公私钥对,然而我们发现好多对:
在 SSH 服务器上,通常有一个主机密钥对应的公钥以及每个用户账户都有一个 authorized_keys
文件,其中包含了该用户允许连接到该账户的公钥列表。
当远程用户尝试连接到服务器时,服务器会使用以下步骤来选择正确的公钥进行验证:
主机密钥:
服务器使用主机密钥对应的公钥进行初始连接的身份验证。这是服务器身份的一部分,用于确保你连接到的是预期的服务器
。主机密钥通常存储在 /etc/ssh
目录下的 ssh_host_*_key.pub
文件中。
用户密钥:
一旦通过了主机密钥的验证,服务器将要求用户提供其对应的密钥进行用户身份验证。这是通过检查用户的 ~/.ssh/authorized_keys
文件,其中包含了允许连接到该用户账户的所有公钥。
如果用户提供了有效的密钥,连接将被授予;否则,连接将被拒绝。
多个用户公钥:
如果用户在 authorized_keys
文件中有多个公钥,服务器将逐个尝试进行验证,直到找到匹配的公钥或者所有的公钥都被尝试完毕。验证通过即允许连接。
总之,服务器在连接时会先使用主机密钥进行验证,然后再使用用户提供的公钥进行用户身份验证。用户的公钥列表存储在其 authorized_keys
文件中,如果有多个公钥,服务器会逐个尝试验证。连接将在找到有效的公钥或者所有公钥都尝试完毕后被授予或拒绝。
当然,我们也可以通过ssh免密登录远程服务器:
使用 SSH 公私钥对连接远程服务器,通常遵循以下步骤:
生成 SSH 密钥对:
在本地机器上使用以下命令生成 SSH 密钥对。如果你已经有密钥对,可以跳过这一步。
ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa
上述命令会生成一个 2048 位的 RSA 密钥对,并将私钥保存在 ~/.ssh/id_rsa
,公钥保存在 ~/.ssh/id_rsa.pub
。
复制公钥到远程服务器:
将本地生成的公钥复制到远程服务器的 ~/.ssh/authorized_keys
文件中。你可以使用 SSH 命令或其他文件传输工具完成此操作。
连接到远程服务器:
ssh user@remote_server
如果一切设置正确,你应该能够通过公私钥进行连接,而无需输入服务器密码,但是需要输入本机密码,以便安全访问你本机的私钥。
SSH 是一个常用的网络协议,用于安全地远程连接和管理服务器。以下是在常见操作系统上安装 SSH 的简要步骤:
生成 SSH 公钥和私钥通常使用的软件是 OpenSSH。以下是在 Linux、macOS 和 Windows 上生成 SSH 公钥和私钥的步骤:
在 Linux 和 macOS 上:
ssh-keygen -t rsa -b 4096
这将使用 RSA 算法生成一个 4096 位的密钥对。
3. 按提示输入密钥的保存路径和密码(可选)。
4. 生成的公钥和私钥文件默认保存在 ~/.ssh
目录下,分别是 id_rsa.pub
(公钥)和 id_rsa
(私钥)。
生成的公钥文件(以 .pub
结尾)是用于共享给其他人或服务器,而私钥文件应妥善保管,不应泄露给他人。公钥可用于身份验证和加密通信
。
这些只是 SSH 的一些常见使用场景,它在保护数据传输安全、远程管理和访问控制等方面发挥着重要作用。
例如:
ssh username@hostname
其中,username
是您在远程主机上的用户名,hostname
是远程主机的 IP 地址或域名。
在实际应用中,常常会将RSA与SHA算法结合使用
,以提供更安全的加密和签名机制。在数字签名过程中,通常会使用RSA与SHA算法结合,先使用SHA算法对数据进行哈希,然后使用RSA私钥对哈希值进行加密生成数字签名,再使用RSA公钥进行验证。
公钥验证数字签名的过程如下:
公钥验证通常是1. 通过使用公钥对数字签名解密后,得到hash值;2. 对data数据进行hash。3. 比较两个hash值是否一样来实现的。
以下是一个使用 Node.js 进行公钥验证的示例代码:
const crypto = require('crypto'); const fs = require('fs'); // 要验证的数据 const data = '要验证的数据'; // 读取公钥文件 const publicKey = fs.readFileSync('public_key.pem', 'utf8'); // 读取数字签名文件,一般跟随接口下发 const signature = fs.readFileSync('signature.txt', 'utf8'); // 创建 Verify 对象 const verifier = crypto.createVerify('SHA256'); // 将要验证的数据传递给 verifier 对象 verifier.update(data); verifier.end(); // 进行验证 const isValid = verifier.verify(publicKey, signature, 'base64'); if (isValid) { console.log('数字签名验证通过'); } else { console.log('数字签名验证失败'); }
在上述代码中,我们使用 Node.js 的 crypto
模块进行公钥验证。首先,我们读取公钥文件和数字签名文件的内容。然后,创建一个 Verify
对象,并设置要验证的数据。接下来,我们使用 verify
方法对数据进行验证,传入公钥、数字签名和编码方式(这里使用了 base64 编码)。最后,根据验证结果输出相应的消息。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。