Linux openssh介绍
SSH 协议
SSH (Secure Shell) 是应用层的一种网络协议,用于加密两台计算机之间的数据通信,以确保数据在传输过程中的安全性和机密性。
一般用于用于远程登录到计算机系统和执行命令和文件传输。在早期使用的是 Telnet 进行远程登录,但 Telnet 数据传输是明文的,不安全,所以SSH的出现,替代了Telnet。
SSH协议采用C/S模型,服务端负责提供服务,等待并接受来自客户端的SSH连接请求。客户端负责请求服务
SSH协议和SSL\TLS协议的区别
-
SSH协议属于应用层协议,SSL\TLS是介于应用层和传输层之间的安全层协议
-
SSH主要用于远程登录、命令执行和文件传输(如SCP和SFTP)。SSL/TLS主要用于为上层应用协议(如HTTP、SMTP、FTP等)提供加密和安全功能。
-
SSH可以使用密码或公钥进行身份验证,而SSL/TLS主要使用基于X.509的证书来验证服务器(以及有时的客户端)身份。
SSH 工作原理
-
密钥交换: 客户端和服务器之间首先会进行密钥交换,以建立一个共享的对称密钥。这个过程确保双方都有一个用于后续通信的加密密钥。
-
身份验证: 一旦密钥交换完成,服务器会要求客户端进行身份验证,这通常可以是基于密码的,也可以是基于公钥的。
-
加密通信: 身份验证成功后,客户端和服务器开始加密的通信,使用之前建立的对称密钥。
所以由此可知,SSH是先进行密钥交换,再进行身份验证。
OpenSSH
OpenSSH 最初是为 OpenBSD 操作系统开发的,后面迅速被移植到了其他 Unix-like 系统(Linux、Unix、FreeBSD等)以及windows系统,现在OpenSSH 是各大平台上最广泛使用的 SSH 实现。
所以目前的Linux发行版系统中,一般使用OpenSSH软件服务来实现客户端功能。实现客户端的软件就比较多了,例如xshell、scp、ssh、putty等。
openssh官网: https://www.openssh.com/
安装openssh
一般情况下Linux发行半默认就安装了OpenSSH,如果是最小安装,可能就没有该服务。如果没有安装,可以去官网下载源码包编译安装或者直接时候软件包工具进行安装。
例如:
# ubuntu
apt install openssh-server
# centos
yum install openssh-server
说明: 安装服务端的时候,客户端一般会作为依赖的方式自动进行安装。客户端对应的软件包是:openssh-clients
openssh配置文件
因为openssh是C/S架构的,由服务端和客户端组成,他们各有一个主要的配置文件。
服务端配置文件
服务端的配置文件一般是 /etc/ssh/sshd_config ,通过修改这个配置文件,可以实现对openssh服务端一些属性的修改:
基本配置
Port 22 # 指定ssh服务使用的端口号,默认22
ListenAddress 0.0.0.0 # shd服务器绑定的IP地址
PermitRootLogin yes # 是否允许root用户登录
PasswordAuthentication yes # 是否支持密码验证。no表示没法用密码来远程登录
PermitEmptyPasswords no # 是否允许空密码连接
PubkeyAuthentication yes # 是否允许公钥认证
AuthorizedKeysFile # 定义公钥存放位置
例如:
PermitEmptyPasswords设置为no,Linux主机上创建了一个用户,没有给这个用户指定密码,那么就不能用这个用户来进行登录。
持续连接配置
ClientAliveInterval 60 # 服务器间隔多长时间发送一个心跳给客户端检查连接是否仍然活跃。lientAliveInterval 值设置为0以禁用超时。
ClientAliveCountMax 0 # 客户端响应之前,服务器允许发送空数据包的最大次数。如果这个数目达到了而客户端没有回应,服务器就会断开连接。
说明:
当 ClientAliveInterval 设置为 0 时,ClientAliveCountMax 的设置将不再有影响。这是因为 ClientAliveInterval 控制的是服务器发送保持活动状态检查消息的频率。如果 ClientAliveInterval 被设置为 0,意味着服务器根本不会发送这些检查消息。
例如:
ClientAliveInterval设置为60,ClientAliveCountMax设置为0。服务器每60秒向客户端发送一个空数据包,客户端收到了没响应就断开连接。
连接速度优化
优化客户端连接服务端的连接速度
# 禁用DNS反向查找
UseDNS no
# 禁用GSSAPI认证
GSSAPIAuthentication no
身份验证、会话管理和安全性配置
LoginGraceTime 2m # 指定开始 SSH 会话后完成认证的时间,超过这个时间就断开连接
MaxAuthTries 6 # 一个 SSH 会话中可以尝试认证的最大次数,超过指定次数就断开连接
MaxSessions 10 # 同一个用户可以同时建立多少个SSH会话连接到服务器,超过这个数量就会连接拒绝
PermitEmptyPasswords no # 是否允许用户使用空密码登录(假设该用户的密码确实是空的)
例如:
LoginGraceTime设置为2m,一个用户连接ssh服务端时,超过2m还没有完成身份认证就断开连接。
未认证的连接数配置
# 同一时间内可以进行的并发未认证的连接数
MaxStartups 10:30:60 # 超过10个连接,每一个新的连接有30%的概率被拒绝,超过60个就全部拒绝
例如:
MaxStartups设置为10,当有10个用户(或连接请求)同时尝试与SSH服务器建立连接,但尚未完成身份验证时,超过这个数量的其他用户或连接请求将无法继续,直至其中一些连接完成认证或被断开。
客户端配置文件
openssh客户端的配置文件一般是 /etc/ssh/ssh_config 这个文件,相对于服务端来说,客户端的配置文件很多内容都不需要进行修改,使用默认的就行了。
默认连接参数
如果连接的时候不指定端口,用户名,默认就用配置文件中的。
Port # 要连接的远程SSH服务器的默认端口
User # 连接时要使用的默认用户名
例如:
[ehigh@centos7 ~]$ ssh 10.0.0.10
在ehigh主机上执行ssh 10.0.0.10时,如果你没有指定用户名,SSH 默认会使用当前登录的用户(ehigh)来尝试连接到指定主机,但是如果在客户端中指定了User选项,那么不指定用户名进行连接时,将使用配置文件中指定的用户名进行连接,而不是默认的ehigh
openssh客户端工具
ssh
ssh [user_name@]ip_host [CMD]
说明:
-
省略用户名,就使用当前主机登录的用户的身份登录到远程主机
-
不指定需要在远程主机上执行的命令,就直接停留在远程主机上了,会在当前计算机上获得一个shell(shell是由远程系统上的用户帐户设置决定)
-
默认使用的是22端口(客户端配置文件指定)连接到远程服务器,也可以使用 -p 参数来手动指定端口号
-
如果是要使用基于key验证的方式来远程连接,可以通过 -l 参数来指定私钥的位置
-
如果想 登录的时候不用确认,直接下载公钥 通过 -o StrictHostKeyChecking=no 来实现
例如:
ssh ehigh@192.168.13.66
表示从当前计算机远程登录到IP地址为192.168.13.66的计算机,并使用用户名ehigh进行身份验证,验证成功后会在当前计算机上获得一个shell(shell是由远程系统上的用户帐户设置决定),可以开始在那里执行命令。
例如:
ssh 192.168.0.102
因为没有指定用户名,会默认尝试使用当前本地用户的用户名来登录远程计算机,如果远程主机上不存在这个用户账户,登录将失败。
当前本地机器上的用户名是ehigh,远程主机上也必须存在一个叫作ehigh的用户才能正常登录。
ssh客户端的指纹验证
当第一次连接远程服务器的时候,会有以下提示:
The authenticity of host '192.168.0.102 (192.168.0.102)' can't be established.
ECDSA key fingerprint is SHA256:9wXl1SPQb2dj7pkc3ygLveZjJ0GGUTUqfthAKiL7nKQ.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
这个的作用是使用SSH客户端首次连接到某个SSH服务器时经常看到的。其目的是为了让你知道你正在连接到一个未知或不受信任的服务器。
客户端会在它的known_hosts文件中没有找到这个服务器的公钥信息,如果没有,说明未连接过这个服务器,集体是不受信任。
服务器会返回一个摘要,让你确认是否正在连接到预期的服务器,如果你确认,就输入yes回车就行了。
openssh 密码验证流程
-
连接请求:客户端发起连接请求到SSH服务器
-
身份提示:SSH服务器会要求提供用户名(如果未在命令中提供)
-
密码提示:一旦提供了用户名,服务器会提示输入该用户名对应的密码
-
密码验证:客户端输入密码后,该密码会被加密然后发送到服务器,服务器验证密码是否匹配,密码正确,身份验证成功
openssh 密钥交换过程
无论是使用密码验证还是密钥验证,SSH客户端和服务器都会执行一个过程叫做"密钥交换"。这个过程的目的是为双方之间的会话建立一个共享的对称密钥,该密钥将用于加密此次会话的所有数据。
具体过程是这样的:
1、服务端身份验证:客户端首次连接服务端时,服务端将其公钥发送给客户端。这是为了让客户端验证其即将连接的服务器的身份。客户端收到公钥后会存放在known_hosts中
当客户端首次连接到服务器时,它可能没有该服务器的公钥。在这种情况下,客户端会询问用户是否信任该服务器的公钥,并将其存储在 known_hosts 文件中。如果客户端已经拥有公钥,它会使用该公钥验证服务器的身份,以防止中间人攻击。
2、派生对称密钥:使用 Diffie-Hellman 密钥交换或其他算法,客户端和服务器独立地生成一个共享的对称密钥,这个秘密不会在网络上传输。
3、后续通过了身份验证(可以是密码验证,也可以是密钥验证),就使用这个对称密钥进行加密,保证数据的机密性和完整性。
openssh 密钥验证流程
-
客户端使用非对称加密生成密钥对,一般使用ssh-keygen工具。
-
客户端生成密钥对后,将其公钥复制到远程服务器的/.ssh/authorized_keys文件。可以使用ssh-copy-id工具或手动复制粘贴到服务端的/.ssh/authorized_keys文件(通过配置文件可以指定存放位置,这个位置时配置文件默认指定的)
-
进行身份认证时,服务器会生成一个随机数并发送给客户端,客户端使用其私钥加密这个随机数,并将加密的数据发送回服务器。服务器使用之前存储的公钥解密接收到的数据,如果解密后的数据与服务器最初生成的随机数匹配,那么客户端的身份得到了验证。
基于key验证的实现
1、生成本地密钥对
ehigh@ubuntu:~$ ssh-keygen
2、将公钥发送给服务端
ssh-copy-id 192.168.6.121
3、使用ssh的 -i 参数来指定一个私钥文件用于进行公钥认证,这样就能基于密钥的方式来远程到目标主机了
ehigh@ubuntu:~$ ssh -i .ssh/id_rsa 192.168.6.121
这里使用 -i 指定私钥的原因是服务器会发送一个随机字符串过来,需要使用私钥加密,然后再返还给服务器。
如果不使用 -i 参数指定私钥位置的话,默认使用 ~/.ssh/id_rsa 这个文件(通过客户端配置文件中的 IdentityFile 指令指定的)
多台主机之间彼此都能基于Key验证方法:
通过多个主机公用一个密钥对来实现
1、现在本机上生成密钥对
ssh-keygen
2、将公钥文件保存到自己的authorized_keys文件中
ssh-copy-id 127.0.0.1
3、将生成的公钥、私钥还有authorized_keys文件再每个主机上拷贝一份即可。
可以直接拷贝整个.ssh目录文件
rsync -av .ssh ip_host:/~/.ssh
known_hosts和 authorized_keys
在openssh服务端,有两个文件容易搞混淆:
known_hosts
作用: 存储已知远程服务器的公钥信息,在密钥交换过程中服务端发送过来的公钥。
原理: 当客户端首次尝试连接到某个SSH服务器时,它会询问是否信任服务器的公钥。如果客户端选择信任,那么该服务器的公钥将被添加到 known_hosts 文件中。此后,每当客户端再次尝试连接到该服务器时,SSH客户端会检查 known_hosts,以确保服务器的公钥没有变化。
authorized_keys
作用: 存储允许连接到服务器的客户端公钥。使用密钥进行身份验证的时候,客户端发送过来的公钥。
原理: 客户端尝试使用公钥身份验证方式连接到SSH服务器时,服务器会检查 authorized_keys 文件以确定是否已存储与客户端提供的公钥匹配的公钥。如果匹配,则服务器信任客户端,并允许建立连接。
scp
scp也是openssh客户端提供的一个工具,用来实现跨主机文件拷贝的。
scp的是使用方法和ssh差不多
# 本地文件拷贝到远程主机
scp 本地文件 [user@]IP_host:远程路径
# 远程主机文件拷贝到本地
scp [user@]IP_host:远程路径 本地文件
说明:
-
如果拷贝的是一个目录,要加 -r 参数才行
-
默认使用的是22端口,如果openssh服务端的端口变了,要使用 -P(大写) 参数来指定端口
-
scp中,冒号 (😃 用于区分文件或目录的位置是在本地还是在远程服务器。它是一个界定符,告诉 scp 你正在引用一个远程路径,而不是本地路径
-
复制目录的时候,如果目录后面有斜线表示复制文件夹里面的内容,无斜线表示复制整个文件夹。
例如:
scp file.txt user@192.168.1.1:/path/on/remote/
通过冒号标识符,scp 会认识到 user@192.168.1.1:/path/on/remote/ 是一个远程路径,所以它会尝试连接到远程服务器 192.168.1.1 并将 file.txt 复制到该服务器上的指定路径。