介绍
本章,您将学习有关 OpenSSH 的相关知识。
OpenSSH 服务是 GNU/Linux 上重要的远程管理工具,其底层使用一种建立在应用层和传输层基础上的安全协议,全称「Secure Shell Portocol」(安全外壳协议)。
请注意术语 SSH,有时指的是 OpenSSH 服务,有时指的是 SSH 协议,有时也指 ssh
命令。
SSH 协议:由 IETF(The Internet Engineering Task Force) 进行维护的一种标准化规范,仅定义基本功能且无具体的软件实现。
OpenSSH 软件套件:基于 SSH 协议而实现的一个开源软件套件,由 OpenBSD 项目开发并维护,采用 BSD 开源许可证协议。官网链接 —— https://www.openssh.com/
OpenSSH 软件套件由以下的工具组成:
- 使用
ssh
、scp
、sftp
命令来完成远程操作 - 使用
ssh-add
、ssh-keysign
、ssh-keyscan
、ssh-keygen
进行密钥的管理 - 服务端由
sshd
、sftp-server
和ssh-agent
组成。
GNU/Linux 上的 OpenSSH
默认情况下,常规的 RHEL 发行版都会包含这些软件包:
Shell > rpm -qa | grep -i openssh
openssh-clients-8.0p1-25.el8_10.x86_64 ← OpenSSH 的客户端
openssh-8.0p1-25.el8_10.x86_64 ← 有关协议的软件包
openssh-server-8.0p1-25.el8_10.x86_64 ← OpenSSH 的服务器端
OpenSSH 的服务器端
- 默认占用端口 – 22/tcp、22/udp
- 守护进程 – sshd
- 配置文件 – /etc/ssh/sshd_config
- 主命令 –
sshd
,负责监听来自客户端的连接请求并为其提供安全的加密连接。
OpenSSH 的客户端
ssh
命令sftp
命令scp
命令- 配置文件 – /etc/ssh/ssh_config
对称加密与非对称加密
对称加密
术语:
- 明文:未被加密的原始数据,没有加密的字符串
- 密文:原始数据被某种加密算法加密之后的文字或字符串
- 密钥:密码中的一种参数,用在明文转密文或密文转明文。可划分为对称密钥与非对称密钥,对应的是对称加密与非对称加密。
Q:什么是对称加密?
信息的发送方和接收方使用 同一个密钥 去加密和解密数据。
加密过程:明文 + 加密算法 + 私钥 => 密文
解密过程:密文 + 解密算法 + 私钥 => 明文
如下图所示:
私钥:对称加密中用到的密钥被称为私钥,即私有的密钥,不允许泄露。
「对称」指的是加密过程中的私钥与解密过程中的私钥使用的是 同一个密钥
非对称加密
既然被称为非对称加密,由前文可知,加密过程中的密钥与解密过程中的密钥肯定是不同的。
非对称加密使用一对密钥,即「公钥」(publickey)和「私钥」(privatekey),其特点如下:
- 公钥和私钥成对出现
- 公开的密钥叫公钥,只有自己知道的叫私钥
- 用公钥加密的数据只有对应的私钥可以解
- 用私钥加密的数据只有对应的公钥可以解
- 如果可以用公钥解密,则必然是对应的私钥加密的
- 如果可以用私钥解密,则必然是对应的公钥加密的
加密过程:明文 + 加密算法 + 公钥 => 密文
解密过程:密文 + 解密算法 + 私钥 => 明文
SSH 协议的加密原理
SSH 协议的加密原理就是利用非对称加密算法演变而来的。
当客户端首次连接 SSH 服务器时,服务器会主动发送自己的公钥到客户端。客户端接收到公钥后,会显示该公钥的指纹,并要求用户确认是否信任该公钥,如下图所示:
服务器端配置文件
指的是 /etc/ssh/sshd_config 这个文件,默认情况下,其配置情况如下:
Shell > grep -v -E "^#|^$" /etc/ssh/sshd_config
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
SyslogFacility AUTHPRIV
PermitRootLogin yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication yes
ChallengeResponseAuthentication no
GSSAPIAuthentication yes
GSSAPICleanupCredentials no
UsePAM yes
X11Forwarding yes
PrintMotd no
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
Subsystem sftp /usr/libexec/openssh/sftp-server
一些常见的配置项说明:
Port 22
– OpenSSH 服务器端的默认端口,通常我们都会修改ListenAddress 0.0.0.0
– 监听的 IP 地址,0.0.0.0
表示监听所有 IPv4 地址;::
表示监听所有 IPv6 地址。监听多个地址时请将该配置项写多行。HostKey /etc/ssh/ssh_host_rsa_key
– 定义服务器使用的密钥文件路径和类型。可以书写多行。SyslogFacility AUTHPRIV
– 指定 SSH 日志的设备类型,不同的设备类型代表不同的日志文件路径。AUTHPRIV 表示 SSH 的日志存放在 /var/log/secure 文件中。LogLevel INFO
– 日志等级。日志等级越低,记录的信息量越多。可以的值有:QUIET、FATAL、ERRORINFO、VERBOSE、DEBUG、DEBUG1、DEBUG2、DEBUG3,默认值为 INFOPermitRootLogin yes
– 是否允许 root 用户通过 ssh 登录PubkeyAuthentication yes
– 是否使用公钥验证AuthorizedKeysFile .ssh/authorized_keys
– 公钥的保存位置PasswordAuthentication yes
– 是否允许使用密码验证登录。当开启公钥验证时,这一项可以修改为 no。PermitEmptyPasswords no
– 是否允许空密码登录-
MaxAuthTries 6
– 单次连接中最大的认证尝试次数,若 6 次都无法通过验证,则断开 SSH 连接。这里的认证次数指的是包括键盘交互、密码、公钥等的总次数。在不更改配置文件的默认情况下,SSH 的服务器端允许用户单次登录时重试 6 次身份认证,SSH 的客户端允许重试 3 次密码。我们可以通过手册页看到:Shell > man 5 sshd_config ... MaxAuthTries Specifies the maximum number of authentication attempts permitted per connection. Once the number of failures reaches half this value, additional failures are logged. The default is 6. ... Shell > man 5 ssh_config ... NumberOfPasswordPrompts Specifies the number of password prompts before giving up. The argument to this keyword must be an integer. The default is 3. ... # 在 PowerShell 中指定密码的尝试次数 ## 若不指定该选项,虽然 SSH 服务器端允许尝试的认证次数为 6 次,但 SSH 客户端默认的密码尝试次数只有 3 次 PS > ssh -p 22 -o NumberOfPasswordPrompts=6 [email protected]
管理 OpenSSH 服务
常见操作如下:
Shell > systemctl restart sshd.service
Shell > systemctl status sshd.service
Shell > systemctl cat sshd.service
常见命令
主要是这三个命令:
ssh
– 连接命令。如ssh -p 22 -o NumberOfPasswordPrompts=6 [email protected]
,-p 选项指定连接主机的端口,-o 指定客户端的一些选项。sftp
– 通过 SSH 协议传输文件scp
– 通过 SSH 协议复制文件(上传或下载)
以下我使用 Windows 的 PowerShell 进行演示:
PS > cd E:\
# 使用 scp 将 E 盘下的 nginx.conf 上传到服务器的 /tmp/ 目录中
PS > scp -P 22 .\nginx.conf [email protected]:/tmp
[email protected]'s password:
nginx.conf 100% 2656 2.5MB/s 00:00
PS > ssh -p 22 [email protected]
Shell > ls -l /tmp/nginx.conf
-rw-r--r-- 1 root root 2656 Apr 4 20:39 /tmp/nginx.conf
# 使用 sftp
PS > sftp -P 22 [email protected]
# ls - 列出远程主机的数据
# lls -列出本地主机的数据
# cd - 切换远程主机的目录
# lcd - 切换本地主机的目录
# pwd - 列出远程主机所在的目录
# lpwd - 列出本地主机所在的目录
# get - 下载,下载目录需要加 -r 选项
# put - 上传,上传目录需要 -r 选项
sftp> lcd D:\
sftp> cd /tmp/
sftp> lpwd
Local working directory: d:\
sftp> get /tmp/nginx.conf ./
Fetching /tmp/nginx.conf to ./nginx.conf
nginx.conf 100% 2656 2.5MB/s 00:00
sftp> get -r /etc/ ./
sftp> quit
PS >
常见的 SSH 连接工具
- Putty – https://www.putty.org/
- SecureCRT – https://www.vandyke.com/
- Xshell – https://www.netsarang.com/zh/Xshell/
- Tabby – https://github.com/Eugeny/tabby
- Windows 10/11 中自带的 OpenSSH 客户端 – 直接在 PowerShell 中使用
ssh
命令即可 - …
密钥对登录服务器
操作系统 | 角色 |
---|---|
Windows 10 | OpenSSH 客户端 |
RockyLinux 8.10 | OpenSSH 服务器端 |
步骤如下:
- 在 OpenSSH 客户端中使用
ssh-keygen
命令生成密钥对,私钥文件为 id_rsa,公钥文件为 id_rsa.pub。OpenSSH 客户端需要保存好私钥文件。 - 将生成的公钥上传到服务器上,路径位置以及名称为
~/.ssh/authorized_keys
,这里的~
代表相应用户的家目录(主目录)
假设我需要使用 root 用户进行密钥对登录,以下为操作示例:
PS > ssh-keygen.exe -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (C:\Users\litia/.ssh/id_rsa): E:\id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in E:\id_rsa
Your public key has been saved in E:\id_rsa.pub
The key fingerprint is:
SHA256:OPifILZjkj542gt9soLDiIRVdhE4aiGCPu0JZ++jg9A litia@DESKTOP-T699KU6
The key's randomart image is:
+---[RSA 3072]----+
|. .oo |
|+ . = . |
|o..= o |
| +++ . . |
|.+* + o S |
|ooEo o . |
|O.+.= o |
|B==*o= o . |
|.*=*+.. o |
+----[SHA256]-----+
PS > scp -P 22 E:\id_rsa.pub [email protected]:/tmp/
PS > ssh -p 22 [email protected]
# 覆盖的方式重定向
Shell > cat /tmp/id_rsa.pub > /root/.ssh/authorized_keys
# 配置 OpenSSH 的服务器端
## 禁止使用密码进行登录,我这里用的 sed 命令进行替换
## sed 命令的意思通过 PasswordAuthentication 字符串定位行,然后将该行中的 yes 替换为 no,-i 表示将变更永久写入到文件中
Shell > sed -i '/PasswordAuthentication/s/yes/no/g' /etc/ssh/sshd_config
Shell > systemctl restart sshd.service
Shell > logout
# 重新登录
# 使用 -i 选项指定您的私钥文件
PS > ssh -p 22 -i E:\id_rsa [email protected]
Last login: Fri Apr 4 21:36:59 2025 from 192.168.100.7
# 查阅日志
Shell > tail -n 2 /var/log/secure
Apr 4 21:40:02 M1 sshd[2495]: Accepted publickey for root from 192.168.100.7 port 4898 ssh2: RSA SHA256:OPifILZjkj542gt9soLDiIRVdhE4aiGCPu0JZ++jg9A
Apr 4 21:40:02 M1 sshd[2495]: pam_unix(sshd:session): session opened for user root by (uid=0)
