使用SSH访问远程命令行
目标
完成本节内容后,你能够登录到远程系统并使用ssh运行命令。
什么是openssh?
OpenSSH在Red Hat企业级Linux系统中实现了安全shell或SSH协议。SSH协议使系统能够通过不安全的网络以加密和安全的方式进行通信。
您可以使用 ssh 命令创建一个安全的远程系统连接,以特定用户的身份进行身份验证,并以该用户的身份在远程系统上获得交互式 shell 会话。您也可以使用 ssh 命令在远程系统上运行单独的命令,而无需运行交互式 shell。
安全shell的例子
下面的 ssh 命令将使用与当前本地用户相同的用户名登录远程服务器 remotehost。在这个例子中,远程系统会提示你使用该用户的密码进行身份验证。
[user01@host ~]$ ssh remotehost
user01@remotehost's password: redhat
...output omitted...
[user01@remotehost ~]$
你可以通过退出命令退出远程系统。
[user01@remotehost ~]$ exit logout Connection to remotehost closed.
[user01@host ~]$
接下来的ssh命令会让你用用户名user02登录到远程服务器remotehost上。同样,远程系统会提示你使用该用户的密码进行认证。
[user01@host ~]$ ssh user02@remotehost
user02@remotehost's password: shadowman .
..output omitted...
[user02@remotehost ~]$
这条ssh命令将以user02用户的身份在远程主机的远程系统上运行hostname命令,无需访问远程交互式shell。
[user01@host ~]$ ssh user02@remotehost hostname
user02@remotehost's password: shadowman
remotehost.lab.example.com
[user01@host ~]$
注意,前面的命令显示的是本地系统终端中的输出。
鉴别远程用户
w命令显示了当前登录到计算机的用户列表。这对于显示哪些用户从哪些远程位置使用ssh登录,以及他们在做什么,特别有用。
[user01@host ~]$ ssh user01@remotehost
user01@remotehost's password: redhat
[user01@remotehost ~]$ w
16:13:38 up 36 min, 1 user, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
user02 pts/0 172.25.250.10 16:13 7:30 0.01s 0.01s -bash
user01 pts/1 172.25.250.10 16:24 3.00s 0.01s 0.00s w
[user02@remotehost ~]$
前面的输出显示,user02的用户于今天16:13从172.25.250.10 IP地址的主机上登录到伪终端0上的系统,并在shell提示符下空闲了7分30秒。前面的输出也显示,user01用户在伪终端1上登录了系统,并在执行w命令后的最后三秒起,一直处于空闲状态。
SSH 主机秘钥
SSH通过公钥加密来保证通信安全。当SSH客户端连接到SSH服务器时,服务器会在客户端登录前向客户端发送一份公钥副本。这是用来设置通信通道的安全加密,并对服务器与客户端进行身份验证。
当用户使用 ssh 命令连接到 SSH 服务器时,该命令会检查它在本地已知主机文件中是否有该服务器的公钥副本。系统管理员可能已经在/etc/ssh/ssh_known_hosts中预先配置了它,或者用户可能在其主目录中的~/.ssh/ known_hosts文件中包含了该密钥。
如果客户端有一个密钥的副本,ssh会将该服务器的已知主机文件中的密钥与它收到的密钥进行比较。如果密钥不匹配,客户机就会假设服务器的网络流量可能被劫持,或者服务器已经被入侵,并询问用户确认是否继续连接。
如果客户端的已知主机文件中没有公钥的副本,ssh命令会问你是否要登录。如果你想,公钥的副本将保存在你的
~/.ssh/known_hosts文件,这样以后就可以自动确认服务器的身份。
[user01@host ~]$ ssh newhost
The authenticity of host 'remotehost (172.25.250.12)' can't be established.
ECDSA key fingerprint is SHA256:qaS0PToLrqlCO2XGklA0iY7CaP7aPKimerDoaUkv720.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'newhost,172.25.250.12' (ECDSA) to the list of known hosts.
user01@newhost's password: redhat
...output omitted...
[user01@newhost ~]$
SSH已知的主机密钥管理
如果服务器的公钥因为硬盘故障导致的密钥丢失,或者因为一些合法的原因被更换,那么你需要编辑已知的主机文件,确保旧公钥的条目被替换成新公钥的条目,这样才能登录。
公钥存储在/etc/ssh/ssh_known_hosts和每个用户的~/.ssh/ known_hosts文件中。每个密钥都在一行中。第一个字段是共享该公钥的主机名和IP地址列表。第二个字段是密钥的加密算法。最后一个字段是密钥本身。
[user01@host ~]$ cat ~/.ssh/known_hosts
remotehost,172.25.250.11 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOsEi0e+FlaNT6jul8Ag5Nj
+RViZl0yE2w6iYUr+1fPtOIF0EaOgFZ1LXM37VFTxdgFxHS3D5WhnIfb+68zf8+w=
你连接到的每个远程SSH服务器都会在/etc/ssh目录下的扩展名为.pub的文件中存储其公钥。
[user01@remotehost ~]$ ls /etc/ssh/*key.pub
/etc/ssh/ssh_host_ecdsa_key.pub /etc/ssh/ssh_host_ed25519_key.pub /etc/ssh/ ssh_host_rsa_key.pub
配置基于SSH密钥的身份验证
目标
完成本节后,您能够配置用户账户,使用基于密钥的身份验证来安全地登录到远程系统,而无需密码。
基于SSH密钥的认证
您可以配置 SSH 服务器,允许您通过使用基于密钥的身份验证来验证而无需密码。这是基于私钥-公钥方案。
要做到这一点,你需要生成一对匹配的加密密钥文件。一个是私钥,另一个是匹配的公钥。私钥文件被用作认证凭证,和密码一样,必须保密和安全。公钥被复制到用户要连接的系统中,用来验证私钥。公钥不需要保密。
你把公钥的副本放在服务器上的账户中。当你尝试登录时,SSH服务器可以使用公钥发出一个只有使用私钥才能正确回答的挑战。因此,你的SSH客户端可以用你唯一的私钥副本自动验证你登录到服务器上。这样一来,你就可以以不需要每次都交互式输入密码的方式安全地访问系统。
生成SSH密钥
要创建一个私钥和匹配的公钥进行身份验证,请使用 ssh-keygen 命令。默认情况下,你的私钥和公钥分别保存在 ~/.ssh/id_rsa 和 ~/.ssh/id_rsa.pub 文件中。
[user@host ~]$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa): Enter Created directory '/home/user/.ssh'.
Enter passphrase (empty for no passphrase): Enter
Enter same passphrase again: Enter Your identification has been saved in /home/user/.ssh/id_rsa.
Your public key has been saved in /home/user/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:vxutUNPio3QDCyvkYm1oIx35hmMrHpPKWFdIYu3HV+w user@host.lab.example.com The key's randomart image is:
+---[RSA 2048]----+
| |
| . . |
| o o o |
| . = o o . |
| o + = S E . |
| ..O o + * + |
|.+% O . + B . |
|=*oO . . + * |
|++. . +. |
+----[SHA256]-----+
如果你在ssh-keygen提示时没有指定密码,那么生成的私钥是不受保护的。在这种情况下,任何拥有您的私钥文件的人都可以使用它进行身份验证。如果你设置了一个密码,那么当你使用私钥进行身份验证时,你需要输入这个密码。(因此,您将使用私钥的口令而不是远程主机上的密码来进行身份验证。)
你可以运行一个名为 ssh-agent 的辅助程序,它可以在会话开始时将你的私钥口令暂时缓存在内存中,以获得真正的无密码认证。这将在本节后面讨论。
下面的ssh-keygen命令的例子显示了在创建公钥的同时创建了受密码保护的私钥。
[user@host ~]$ ssh-keygen -f .ssh/key-with-pass
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in .ssh/key-with-pass.
Your public key has been saved in .ssh/key-with-pass.pub.
The key fingerprint is:
SHA256:w3GGB7EyHUry4aOcNPKmhNKS7dl1YsMVLvFZJ77VxAo user@host.lab.example.com The key's randomart image is:
+---[RSA 2048]----+
| . + =.o ... |
| = B XEo o. |
| . o O X =.... |
| = = = B = o. |
|= + * * S . |
|.+ = o + . |
| + . |
| |
| |
+----[SHA256]-----+
ssh-keygen 命令的 -f 选项决定了密钥的保存位置。在前面的例子中,私钥和公钥分别保存在 /home/user/.ssh/user/.ssh/keywith-pass和 /home/user/.ssh/key-with-pass.pub 文件中。
SSH密钥生成后,默认情况下会被存储在用户主目录的.ssh/目录下。私钥的权限模式必须为600,公钥的权限模式必须为644。
共享公钥
在使用基于密钥的身份验证之前,需要将公钥复制到目标系统。ssh-copy-id 命令会将 SSH 密钥对的公钥复制到目标系统。如果您在运行 ssh-copy-id 命令时省略了公钥文件的路径,它将使用默认的 /home/user/.ssh/id_rsa.pub 文件。
[user@host ~]$ ssh-copy-id -i .ssh/key-with-pass.pub user@remotehost
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/user/.ssh/ id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
user@remotehost's password: redhat
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'user@remotehost'" and check to make sure that only the key(s) you wanted were added.
当公钥成功地传输到远程系统后,你可以在通过SSH登录远程系统时,使用相应的私钥认证到远程系统。如果你在运行ssh命令时省略了私钥文件的路径,它将使用默认的/home/user/.ssh/id_rsa文件。
[user@host ~]$ ssh -i .ssh/key-with-pass user@remotehost
Enter passphrase for key '.ssh/key-with-pass': redhatpass
...output omitted...
[user@remotehost ~]$ exit
logout
Connection to remotehost closed.
[user@host ~]$
使用 ssh-agent 进行非交互式身份验证
如果你的SSH私钥有口令保护,通常你必须输入口令才能使用私钥进行认证。但是,你可以使用一个叫ssh-agent的程序来临时缓存密码。这样,当你使用SSH登录到另一个系统的私钥时,ssh-agent就会自动为你提供口令。这样做很方便,而且可以通过提供更少的机会让别人看到你输入密码的机会来提高安全性。
根据本地系统的配置,如果您最初登录到 GNOME 图形化桌面环境,ssh-agent 程序可能会自动启动并为您配置。
如果你在文本控制台上登录,使用 ssh 登录,或者使用sudo 或 su,你可能需要手动启动该会话的 ssh-agent。你可以用下面的命令来完成这个操作:
[user@host ~]$ eval $(ssh-agent)
Agent pid 10155
[user@host ~]$
ssh-agent运行后,你需要告诉它你的私钥或密钥的密码。你可以通过ssh-add命令来完成这个操作。
以下 ssh-add 命令分别从 /home/user/.ssh/user/.ssh/id_rsa(默认值)和 /home/user/.ssh/key-with-pass 文件中添加私钥。
[user@host ~]$ ssh-add
Identity added: /home/user/.ssh/id_rsa (user@host.lab.example.com)
[user@host ~]$ ssh-add .ssh/key-with-pass
Enter passphrase for .ssh/key-with-pass: redhatpass
Identity added: .ssh/key-with-pass (user@host.lab.example.com)
在成功将私钥添加到ssh-agent进程中后,你可以使用ssh命令调用SSH连接。如果你使用的是默认的 /home/user/.ssh/id_rsa 文件以外的任何私钥文件,那么你必须使用 ssh 命令中的 -i 选项来指定私钥文件的路径。
下面的ssh命令示例使用默认的私钥文件验证到SSH服务器。
[user@host ~]$ ssh user@remotehost
Last login: Fri Apr 5 10:53:50 2019 from host.example.com
[user@remotehost ~]$
下面的 ssh 命令示例使用 /home/user/.ssh/key-with-pass (nondefault) 私钥文件来验证到 SSH 服务器。下面的例子中的私钥已经被解密并添加到其父SSH-agent进程中,所以ssh命令不会提示你通过交互式输入密码来解密私钥。
[user@host ~]$ ssh -i .ssh/key-with-pass user@remotehost
Last login: Mon Apr 8 09:44:20 2019 from host.example.com
[user@remotehost ~]$
当你从启动 ssh-agent 的会话中注销时,该进程将退出,你的私钥的密码将从内存中清除。
自定义openssh服务配置
目标
完成本节后,您应该能够限制以root身份直接登录并禁用OpenSSH服务的密码验证。
配置openssh服务器
OpenSSH服务是由一个名为sshd的守护进程提供的。它的主要配置文件是/etc/ssh/ sshd_config。
OpenSSH服务器的默认配置运行良好。但是,你可能需要做一些改变来加强系统的安全性。有两个常见的改动,你可能要做的是。你可能想禁止直接远程登录到根账户,并且禁止基于密码的身份验证(改用SSH私钥验证)。
禁止超级用户使用SSH登录
禁止从远程系统直接登录到根用户账户是一个好的做法。允许以根用户身份直接登录的一些风险包括:
- 每个Linux系统中默认都存在用户名root,所以潜在的攻击者只需要猜测密码,而不是有效的用户名和密码组合。这就降低了攻击者的复杂性。
- 根用户拥有不受限制的权限,所以它的泄露会导致系统受到最大的破坏。
- 从审计的角度来看,很难跟踪哪个授权用户以root身份登录并进行了更改。如果用户必须以普通用户的身份登录,然后切换到根账户,这就会产生一个日志事件,可以用来帮助提供问责。
OpenSSH服务器使用/etc/ssh/ssh/ sshd_config配置文件中的PermitRootLogin配置来允许或禁止用户以root身份登录系统。
PermitRootLogin yes
如果把PermitRootLogin参数设置为yes,就像默认的那样,允许人们以root身份登录。要防止这种情况,请将值设置为no。另外,要防止基于密码的验证,但允许基于私钥的root验证,可以将PermitRootLogin参数设置为without-password。
必须重新加载 SSH 服务器 (sshd) 才能生效。
[root@host ~]# systemctl reload sshd
禁止基于密码的SSH认证
只允许基于私钥的远程命令行登录有各种优点:
- 攻击者无法使用密码猜测攻击来远程破解系统上的已知账户。
- 对于受密码保护的私钥,攻击者需要密码和私钥的副本。对于密码,攻击者只需要密码。
- 通过使用受密码保护的私钥与ssh-agent配合使用,由于输入密码的频率较低,所以暴露的频率较低,用户登录更方便。
OpenSSH服务器使用/etc/ssh/ sshd_config配置文件中的PasswordAuthentication参数来控制用户是否可以使用基于密码的身份验证来登录系统。
PasswordAuthentication yes
在 /etc/ssh/ssh/ sshd_config 配置文件中,PasswordAuthentication 参数的默认值为 "yes "会使 SSH 服务器允许用户在登录时使用基于密码的身份验证。PasswordAuthentication 参数的值为"no",则会阻止用户使用基于密码的身份验证。
请记住,每次更改 /etc/ssh/sshd_config 文件时,必须重新加载 sshd 服务才能生效。
总结
ssh命令允许用户使用SSH协议安全地访问远程系统。
客户端系统在~/.ssh/known_hosts和/etc/ssh/ssh_known_hosts中存储远程服务器的身份。
SSH支持基于密码和基于密钥的身份验证。
ssh-keygen命令生成一个SSH密钥对,用于验证。ssh-copy-id命令将公钥导出到远程系统。
sshd服务在Red Hat Enterprise Linux系统上实现了SSH协议。
推荐的做法是将 sshd 配置为禁止以 root 身份远程登录,并要求公钥认证而不是基于密码的认证。