Linux] 使用密码/公钥的 SSH 远程登录摘要使用密码/公钥的 SSH 远程登录摘要
前言
本文是笔者查阅网上资料做的总结,关于SSH原理,什么是对称加密和非对称加密,本文不过多介绍。这里介绍一下SHH的工作过程、配制方法,可能出现的问题及解决方法。
说明:本文中涉及的例子,SSH客户端为:本地主机A,SSH服务器为:服务器B
SSH的工作过程
SSH协议采用C-S(客户端-服务器端)架构进行双方的身份验证以及数据的加密。
服务器端组件监听指定的端口,负责安全连接的建立、对连接方的身份认证、以及为通过身份认证的用户建立正确的环境。
客户端负责发起最初的TCP握手、安全连接的建立、验证服务器的身份与之前记录中的一致、并将自己的验证信息提供给服务器。
一个SSH会话的建立过程分为两个阶段。第一阶段,双方沟通并同意建立一个加密连接通道以供后续信息传输用。第二阶段,对请求接入的用户进行身份验证以确定服务器端是否要给该用户开放访问权限。
建立加密通道
当客户端发起TCP连接时,服务器端返回信息说明自己支持的协议版本,如果客户端上支持的协议与之匹配,则连接继续。服务器会提供自己的公共主机密钥(public host key)以让客户端确认自己访问的是正确的机器。
然后,双方采用一种Diffie-Hellman算法共同为该会话建立密钥。每一方的一部分私有数据,加上来自对方的一部分公共数据,通过这种算法计算,能够得出完全相同的密钥用于本次会话。
整个会话的通讯内容都使用该密钥进行加密。这个阶段使用的公钥/私钥对与用户验证身份用的SSH密钥是完全无关的。
经典Diffie-Hellman算法的计算步骤如下:
1、双方共同选择一个大值素数作为种子值(seed value)
2、双方共同选择一个加密生成器(通常是AES),用于后续的数值操作
3、双方分别各自选择一个素数,该素数的值对对方保密,用于生成本次通讯的私钥(与SSH身份认证私钥无关)
4、双方分别用各自的私钥、共同的加密生成器、和共同的素数生成各自的公钥
5、双方将各自的公钥共享给对方
6、双方用各自的私钥和对方发过来的公钥生成另一个密钥。根据该算法,双方各自计算出来的两个密钥是完全一样的,即“共同的秘密”
7、该密钥被用于本次通讯所有内容的加密
这个共享密钥的加密方式被称为二进制数据包协议(binary packet protocol)。该过程能够让双方平等的参与密钥生成的过程,而不是由单方掌握。这种共享密钥生成的过程是安全的,双方没有交换过任何未经加密的信息。
生成的密钥是对称式密钥,一方用于加密信息的密钥等同于另一方用于解密信息的密钥,而任何第三方由于不持有该密钥,是无法解密双方传递的内容的。
会话加密通道建立后,SSH开始进入用户认证阶段。
服务器验证用户
下一步,服务器验证用户身份以决定是否准许其访问。验证有不同的方式,选择的验证方式取决于服务器的支持。
最简单的验证是密码验证:服务器要求客户端输入密码,客户端输入的密码经过上述的通道加密传输给服务器。
虽然密码是加密过的,然而该方法仍然不被推荐,因为用户经常为了省事而使用过于简单的密码,而这类密码很容易就能够被自动化脚本破解。
最流行的验证方式是SSH密钥对,这也是当前最推荐的方式。SSH密钥对是非对称密钥,私钥和公钥分别用于不同的功能。
公钥用于加密,而私钥用于解密。公钥可以随意上传、共享,因为公钥的流通并不会危及到私钥的保密性。
SSH密钥对的验证过程起始于上一部分加密通道建立之后,其具体执行步骤如下:
1、客户端发送自己的密钥ID给服务器端
2、服务器在自己的authorized_keys文件中检查是否有此ID的公钥
3、如果有,则服务器生成一个随机数,用该公钥加密之
4、服务器将加密后的随机数发给客户端
5、客户端用私钥解密该随机数,然后在本地为随机数做MD5哈希
6、客户端将该MD5哈希发给服务器端
7、服务器端为一开始自己生成的随机数也做一个MD5哈希,然后用通讯通道“公共的密钥”将该哈希加密,再跟客户端发来的内容进行对比。如果双方内容一致,则通过验证,开放访问权限给客户端
简单来说,服务器端用公钥加密信息,客户端用私钥解密信息以证明自己持有私钥。该过程同时使用了对称加密和非对称加密,两种方式各有自己的功用。
用户密码登录
客户端
命令如下:
$ ssh 用户名@IP地址 -p 端口号
用户名:为要登录的服务器B中已存在的用户账户名
IP地址:为服务器B的IP地址
-p 端口号:用来指定端口号,默认为22
第一次登录时,会提示如下提示:
The authenticity of host 'IP地址 (IP地址)' can't be established.
RSA key fingerprint is SHA256:4bYWLpgE6x+NhFcweGtZuKLsHX7IQOGhS06t5dpByHQ.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'IP地址' (RSA) to the list of known hosts.
大概意思是说,你正在访问的主机不能验证它的真实性,它的RSA key(当前访问主机的公钥)指纹是怎样的,你确定要继续连接吗?
输入yes继续,会提示,已永久把当前访问主机的RSA key添加到了已知主机文件(用户目录下,.ssh 文件夹中的knwon_hosts文件)中。之后再次 SSH 登录就不再有该提示了。
接着,输入登录账户的密码即可。
服务器
SSH 密码登录,需要服务器开启密码验证权限,编辑服务器SSH配置命令如下:
$ sudo vim /etc/ssh/sshd_config
在 sshd_config 文件中,Protocol 2 下面 #PasswordAuthentication yes,将前面的#号去掉,保存退出。
公钥登录
公钥登录,即免密码登录。避免的每次登录都要输入的麻烦,也防止了中间人攻击。是SSH远程登录最常用的登录方式。
公钥登录:方法一
Step 1:创建公钥/私钥对ssh-keygen
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/cloudera/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
提示输入密钥对名称,直接回车,使用默认名称即可;
提示输入密码(使用私钥时,要输入密码),直接回车,不使用密码即可。
Step 2:将id_rsa.pub上传到要远程登录到的机器上
$ scp ~/.sshid_rsa.pub root@IP地址:~/.ssh
Step 3:将公钥添加到authorized_keys中
首先,登录服务器B,在进行下面的操作。
$ cd ~/.ssh
$ cat id_rsa.pub >> ~/.ssh/authorized_keys
Step 4:更改文件权限
$ chmod 600 ~/.ssh/authorized_keys
Step 5:编辑SSH服务器配置文件
$ sudo vim /etc/ssh/sshd_config
找到 #PubkeyAuthentication yes,删除 #号,保存退出。
重启 ssh 服务
$ sudo service sshd restart
Step 6:SSH公钥登录
$ ssh root@IP地址
也可指定验证私钥:
$ ssh -i id_rsa root@ip地址
公钥登录:法二
本地主机A,生成密钥对后:
$ ssh-copy-id root@IP地址
```
然后如方法一,配置服务器即可。
##SSH免密码失败原因定位分析
a) 服务器B上.ssh目录的权限必须是700
b) 服务器B上.authorized_keys文件权限必须是600或者644
c) 服务器B上用户家目录文件权限必须是700,比如用户名是aischang,则/home/aischang这个目录权限必须是700
d) 服务器B上SELinux关闭为disabled,可以使用命令修改setenforce 0 ,查看状态的命令为getenforce或者 查看/etc/selinux/config 文件中是否是disabled
注:SELinux共有3个状态enforcing (执行中)、permissive (不执行但产生警告)、disabled(关闭)。
setenforce 设置的状态是临时的,重启失效。setenforce 1 设置SELinux 成为enforcing模式,setenforce 0 设置SELinux 成为permissive模式。
可以通过一下命令编辑SELinux配置:
sudo vim /etc/selinux/config
将 SELinux=disabled 修改为 SELinux=enforce,然后重启服务器
e) 有可能是StrictModes问题
编辑 vi /etc/ssh/sshd_config
找到#StrictModes yes改成StrictModes no
f) 有可能是PubkeyAuthentication问题
编辑 vi /etc/ssh/sshd_config
如果还不行,可以在服务器A上用ssh -vvv 机器B的ip 查看详情,根据输出内容具体问题具体分析了
注:ssh_config 为SSH客户端配置文件,sshd_config 为SSH服务端配置文件。
推荐阅读
-
如何使用Xshell设置SSH无密码登录 - 公钥与私钥的配置方法
-
轻松理解:SSH密码登录与公钥认证登录的差异
-
如何实现服务器无密码登录:SSH公钥的配置方法
-
了解公钥和私钥 - 公钥加密算法又称非对称加密算法,使用不同的密码进行加密和解密,其中一个用于公钥,另一个用于私钥: 公钥和私钥成对使用 公钥称为公钥,私钥称为私钥。 用公钥加密的数据只能用相应的私钥解密 用私钥加密的数据只能用相应的公钥解密。 如果数据可以用公钥解密,则必须用相应的私钥加密。 如果数据可以用私钥解密,则必须用相应的公钥加密。 公钥和私钥是相对的,没有规定哪一个必须是公钥或私钥。 第二,实现数据的安全传输 要实现数据的安全传输,当然要对数据进行加密。 如果使用对称加密算法,加密和解密使用同一个密钥,除了自己要保存外,对方也必须知道密钥才能解密数据。如果把密钥传给对方,就有可能泄露密码。所以我们使用非对称算法,过程如下: 首先,接收方生成一对密钥,即私钥和公钥; 然后,接收方将公钥发送给发送方; 发送方用收到的公开密钥加密数据并发送给接收方; 接收方收到数据后使用自己的私钥解密。 由于在非对称算法中,用公钥加密的数据必须用相应的私钥解密,而私钥只有接收方知道,这就确保了数据传输的安全性。 第三,信息的数字签名 除了确保数据的安全传输,公钥系统的另一个用途是对数据进行签名。通常,"数字签名 "用于验证发送者的身份,帮助保护数据的完整性。 例如,发送者 A 想向所有人发送一些信息,他用自己的私人密钥对信息进行了加密,即签名。这样,每个收到数据的人都能用发送者的公开密钥验证数据,并确认数据是由 A 发送的(因为只有 A 用他的私人密钥签署了数据,所以无法验证发送者的身份)。(因为只有用 A 的私钥签名的信息才能用公钥解密)。使用数字签名可以确认两件事: 保证信息是由签名者本人签名发送的,签名者无法否认或难以否认。 保证信息从发出到收到都没有被以任何方式修改过。 之所以能确认这两点,是因为公钥的解密必然要有相应的私钥加密,而私钥只有签名者持有。 四、公钥算法的缺陷 在现实中,公钥机制也有其缺点,那就是效率很低,比常用的私钥算法(如 DES 和 AES)慢上一两个数量级都有可能。因此,它不适合对大量原始信息进行加密。为了兼顾安全性和效率,我们通常会将公钥算法和私钥算法结合起来使用: 首先,发送方使用对称算法加密原始信息。 接收方使用公钥机制生成一对密钥,一个是公钥,一个是私钥。 接收方将公钥发送给发送方。 发送方用公钥加密对称算法的密钥,然后发送给接收方。 接收方用私人密钥解密对称算法的密钥。 发送方将加密后的原始信息发送给接收方。 接收方使用对称算法的密钥解密信息。 摘要
-
ssh工作流程及原理-SSH(Secure Shell Protocol,安全的壳程序协议),它可以通过数据包加密技术将等待传输的数据包加密后再传输到网络上。ssh协议本身提供两个服务器功能:一个是类似telnet的远程连接使用shell的服务器;另一个就是类似ftp服务的sftp-server,提供更安全的ftp服务。 连接加密技术简介 目前常见的网络数据包加密技术通常是通过“非对称密钥系统”来处理的。主要通过两把不一样的公钥与私钥来进行加密与解密的过程。 公钥(public key):提供给远程主机进行数据加密的行为,所有人都可获得你的公钥来将数据加密。 私钥(private key):远程主机使用你的公钥加密的数据,在本地端就能够使用私钥来进行解密。私钥只有自己拥有。 SSH工作过程:在整个通讯过程中,为实现SSH的安全连接,服务端与客户端要经历如下五个阶段: 版本号协商阶段 SSH目前包括SSH1和SSH2两个版本,双方通过版本协商确定使用的版本 密钥和算法协商阶段 SSH支持多种加密算法,双方根据本端和对端支持的算法,协商出最终使用的算法 认证阶段 SSH客户端向服务器端发起认证请求,服务器端对客户端进行认证 会话请求阶段 认证通过后,客户端向服务器端发送会话请求 交互会话阶段 会话请求通过后,服务器端和客户端进行信息的交互 一、版本协商阶段 服务器端打开端口22,等待客户端连接; 客户端向服务器端发起TCP初始连接请求,TCP连接建立后,服务器向客户端发送第一个报文,包括版本标志字符串,格式为“SSH-<主协议版本号>.<次协议版本号>.<软件版本号>”,协议版本号由主版本号和次版本号组成,软件版本号主要是为调试使用。 客户端收到报文后,解析该数据包,如果服务器的协议版本号比自己的低,且客户端能支持服务器端的低版本,就使用服务器端的低版本协议号,否则使用自己的协议版本号。 客户端回应服务器一个报文,包含了客户端决定使用的协议版本号。服务器比较客户端发来的版本号,决定是否能同客户端一起工作。如果协商成功,则进入密钥和算法协商阶段,否则服务器断开TCP连接。 说明:上述报文都是采用明文方式传输。 二、密钥和算法协商阶段 服务器端和客户端分别发送算法协商报文给对端,报文中包含自己支持的公钥算法列表、加密算法列表、MAC(Message Authentication Code,消息验证码)算法列表、压缩算法列表等等。 服务器端和客户端根据对端和本端支持的算法列表得出最终使用的算法。 服务器端和客户端利用DH交换(Diffie-Hellman Exchange)算法、主机密钥对等参数,生成会话密钥和会话ID。 由此,服务器端和客户端就取得了相同的会话密钥和会话ID。对于后续传输的数据,两端都会使用会话密钥进行加密和解密,保证了数据传送的安全。在认证阶段,两端会使用会话用于认证过程。 会话密钥的生成: 客户端需要使用适当的客户端程序来请求连接服务器,服务器将服务器的公钥发送给客户端。(服务器的公钥产生过程:服务器每次启动sshd服务时,该服务会主动去找/etc/ssh/ssh_host*文件,若系统刚装完,由于没有这些公钥文件,因此sshd会主动去计算出这些需要的公钥文件,同时也会计算出服务器自己所需要的私钥文件。) 服务器生成会话ID,并将会话ID发给客户端。 若客户端第一次连接到此服务器,则会将服务器的公钥数据记录到客户端的用户主目录内的~/.ssh/known_hosts。若是已经记录过该服务器的公钥数据,则客户端会去比对此次接收到的与之前的记录是否有差异。客户端生成会话密钥,并用服务器的公钥加密后,发送给服务器。 ****服务器用自己的私钥将收到的数据解密,获得会话密钥。 服务器和客户端都知道了会话密钥,以后的传输都将被会话密钥加密。 三、认证阶段 SSH提供两种认证方法: 基于口令的认证(password认证):客户端向服务器发出password认证请求,将用户名和密码加密后发送给服务器,服务器将该信息解密后得到用户名和密码的明文,与设备上保存的用户名和密码进行比较,并返回认证成功或失败消息。 基于密钥的认证(publickey认证):客户端产生一对公共密钥,将公钥保存到将要登录的服务器上的那个账号的家目录的.ssh/authorized_keys文件中。认证阶段:客户端首先将公钥传给服务器端。服务器端收到公钥后会与本地该账号家目录下的authorized_keys中的公钥进行对比,如果不相同,则认证失败;否则服务端生成一段随机字符串,并先后用客户端公钥和会话密钥对其加密,发送给客户端。客户端收到后将解密后的随机字符串用会话密钥发送给服务器。如果发回的字符串与服务器端之前生成的一样,则认证通过,否则,认证失败。 注:服务器端对客户端进行认证,如果认证失败,则向客户端发送认证失败消息,其中包含可以再次认证的方法列表。客户端从认证方法列表中选取一种认证方法再次进行认证,该过程反复进行。直到认证成功或者认证次数达到上限,服务器关闭连接为止。实例
-
Linux] 使用密码/公钥的 SSH 远程登录摘要使用密码/公钥的 SSH 远程登录摘要
-
AWS 分配给 IAM 用户--允许使用 MFA、自我管理自己的密码、访问密钥和 SSH 公钥权限
-
使用Vscode进行SSH远程开发的无密码自动登录教程
-
理解与实战:Java SSH库JSch - 用途解析、四大认证法、无密码登录设置、SSH公钥验证深入讲解、三种选择方案、SFTP文件传输详解、Maven集成及实用代码实例 - 专讲JSch在SFTP文件传输中的应用