Linux openssh介绍

SSH 协议

SSH (Secure Shell) 是应用层的一种网络协议,用于加密两台计算机之间的数据通信,以确保数据在传输过程中的安全性和机密性。

一般用于用于远程登录到计算机系统和执行命令和文件传输。在早期使用的是 Telnet 进行远程登录,但 Telnet 数据传输是明文的,不安全,所以SSH的出现,替代了Telnet。

SSH协议采用C/S模型,服务端负责提供服务,等待并接受来自客户端的SSH连接请求。客户端负责请求服务

SSH协议和SSL\TLS协议的区别

  1. SSH协议属于应用层协议,SSL\TLS是介于应用层和传输层之间的安全层协议

  2. SSH主要用于远程登录、命令执行和文件传输(如SCP和SFTP)。SSL/TLS主要用于为上层应用协议(如HTTP、SMTP、FTP等)提供加密和安全功能。

  3. SSH可以使用密码或公钥进行身份验证,而SSL/TLS主要使用基于X.509的证书来验证服务器(以及有时的客户端)身份。

SSH 工作原理

  1. 密钥交换: 客户端和服务器之间首先会进行密钥交换,以建立一个共享的对称密钥。这个过程确保双方都有一个用于后续通信的加密密钥。

  2. 身份验证: 一旦密钥交换完成,服务器会要求客户端进行身份验证,这通常可以是基于密码的,也可以是基于公钥的。

  3. 加密通信: 身份验证成功后,客户端和服务器开始加密的通信,使用之前建立的对称密钥。

所以由此可知,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 密码验证流程

  1. 连接请求:客户端发起连接请求到SSH服务器

  2. 身份提示:SSH服务器会要求提供用户名(如果未在命令中提供)

  3. 密码提示:一旦提供了用户名,服务器会提示输入该用户名对应的密码

  4. 密码验证:客户端输入密码后,该密码会被加密然后发送到服务器,服务器验证密码是否匹配,密码正确,身份验证成功

openssh 密钥交换过程

无论是使用密码验证还是密钥验证,SSH客户端和服务器都会执行一个过程叫做"密钥交换"。这个过程的目的是为双方之间的会话建立一个共享的对称密钥,该密钥将用于加密此次会话的所有数据。

具体过程是这样的:
1、服务端身份验证:客户端首次连接服务端时,服务端将其公钥发送给客户端。这是为了让客户端验证其即将连接的服务器的身份。客户端收到公钥后会存放在known_hosts中

当客户端首次连接到服务器时,它可能没有该服务器的公钥。在这种情况下,客户端会询问用户是否信任该服务器的公钥,并将其存储在 known_hosts 文件中。如果客户端已经拥有公钥,它会使用该公钥验证服务器的身份,以防止中间人攻击。

2、派生对称密钥:使用 Diffie-Hellman 密钥交换或其他算法,客户端和服务器独立地生成一个共享的对称密钥,这个秘密不会在网络上传输。

3、后续通过了身份验证(可以是密码验证,也可以是密钥验证),就使用这个对称密钥进行加密,保证数据的机密性和完整性。

openssh 密钥验证流程

  1. 客户端使用非对称加密生成密钥对,一般使用ssh-keygen工具。

  2. 客户端生成密钥对后,将其公钥复制到远程服务器的/.ssh/authorized_keys文件。可以使用ssh-copy-id工具或手动复制粘贴到服务端的/.ssh/authorized_keys文件(通过配置文件可以指定存放位置,这个位置时配置文件默认指定的)

  3. 进行身份认证时,服务器会生成一个随机数并发送给客户端,客户端使用其私钥加密这个随机数,并将加密的数据发送回服务器。服务器使用之前存储的公钥解密接收到的数据,如果解密后的数据与服务器最初生成的随机数匹配,那么客户端的身份得到了验证。

基于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 复制到该服务器上的指定路径。

posted on 2022-08-01 08:42  背对背依靠  阅读(1920)  评论(0编辑  收藏  举报