ssh 远程登录优化

1 背景

我们使用ssh远程登录一个服务器时,一般都是直接使用输入密码的形式进行登录:

1
ssh -p 端口号 用户名@服务器ip地址 

使用这种形式进行登录的缺点在于:容易有密码被暴力破解的问题

当然针对于上面的这个问题,我们也有一些相应的应对策略:

  • ssh 的端口设置为默认的 22 以外的端口
  • 禁用 root 账户登录

虽然上述策略能够对密码被暴力破解起到一定的防治作用,但是最好的解决办法还是通过密钥的方式进行登录。

这篇文章主要介绍如何通过密钥的方式进行ssh远程登录,然后进一步针对ssh登录流程进行优化,以求能够在保证足够安全的情况下,用最少的输入远程登录服务器。

2 具体操作

具体的解决办法是通过密钥验证的方式,代替手动输入密码,登录远程服务器

2.1 生成公、私钥文件

通过使用OpenSSH认证密钥实用程序ssh-keygen可以生成公、私钥文件。

1
ssh-keygen [-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa] 

其中,常用到的参数-t用来指定加密算法,通常使用dsarsa

下面给一个生成公私、钥文件的实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
❯ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/用户名/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/用户名/.ssh/id_rsa
Your public key has been saved in /Users/用户名/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:70bmJt6sSEo+9AlT880IJCWBIufLX/pqdG3kS7xDZiE username@host
The key's randomart image is:
+---[RSA 3072]----+
| .oo. |
|o o ... |
|.+ o |
| . E o |
| . . . XS= |
| o = o %.= |
| +.B.B *. |
| o=oo.=++ |
| .++o.o*+ |
+----[SHA256]-----+

在上面的实例中可以看到,当没有指定加密的算法时,默认使用rsa作为加密算法。

注意,这里“密码”的英文单词是 passphrase,这是为了避免与 Linux 账户密码单词 password 混淆,表示这不是用户系统账户密码。

生成公、私钥文件的过程中会让回答几个问题:(可以直接按回车,表示采用默认选项)

  • 存放公、私钥文件的位置以及公、私钥文件的名称(默认:/Users/用户名/.ssh/id_rsa,这个是私钥的文件名,对应的公钥文件/Users/用户名/.ssh/id_rsa.pub是自动生成的)
  • 是否要为私钥文件设定密码保护(passphrase),这样的话如果私钥文件不小心泄漏,也可以有密码保护。(默认:不设置)。

最后,就会生成私钥和公钥,屏幕上会给出生成的公、私钥的存放位置及名称,还会给出公钥的指纹,以及当前的用户名(username)和主机名(host)作为注释,用来识别密钥的来源。

公钥文件和私钥文件都是文本文件,可以用文本编辑器看一下它们的内容。

公钥文件的内容类似下面这样:

1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQwg4vsQ+2UNCPcNJz6MN0RhOkKwFzuDzYr/lemZ6fck1SeVoEX8no5a75b6dFrEUjn47TB+oEq9pvS3W/w0SRdTiDnWgoPzoAlqCr9PDQaAA7zNPbOdIqksRcEZcCG3V/QN2RpgfQ+MiEs6vD/mTKjQfw0wg9iZfmkl5ARHBCxStIDxWpLqfwchH9h8xAtPYebfy+C70pkUKEJlsPQi3GgU7bV4W9OSzkxoT4XyTfo4isWV8oICokOs80Up+sTsgvMrDpGS3PS8BbzPZr1TwdpebzMW0CQrKe7l1rpO48cjEbPzX6fJ+9k6KL7pi1oxkIcILVzeZ5odm2jyhZ0Nx0Rycq8hYjaWI76SsKJHVhtcOvoDnnN99mq2dFJWxMDMGD9S7K5Oo5dk6lMngjIZTywIcdGssLChCodE37ys1TDmHewcC+0MDWma/8pz8IgJK25X50jNzQpGzSjPoXj8rVHN+Xe3GeT3GNO+s9BfnXB66ncWiV/kPRovSDfRH6WYk= username@host

上面示例中,末尾的username@host是公钥的注释,用来识别不同的公钥,表示这是哪台主机(host)的哪个用户(username)的公钥,不是必需项。

注意,公钥只有一行,因为它太长了,所以上面可能分成三行显示。

2.2 上传公钥

为了能够实现密钥验证方式的远程登录,还需要将生成好的公钥上传服务器。(当然,也可以在服务器上生成公、私钥,将私钥传回本地。)

OpenSSH 规定,用户公钥保存在服务器的~/.ssh/authorized_keys文件。

你要以哪个用户的身份登录到服务器,密钥就必须保存在该用户主目录的~/.ssh/authorized_keys文件。

只要把公钥添加到这个文件之中,就相当于公钥上传到服务器了,每个公钥占据一行,如果该文件不存在,可以手动创建。

通过下面命令可以将公钥上传服务器(也可以手动进行上传):

1
$ cat ~/.ssh/id_rsa.pub | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

上面实例中,user@host要替换成所要登录的用户名和主机名。

注意,authorized_keys文件的权限要设为644,即只有文件所有者才能写。如果权限设置不对,ssh 服务器可能会拒绝读取该文件。

2.3 配置ssh服务器config文件

编辑服务器的/etc/ssh/sshd_config 文件,进行如下设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ vim /etc/ssh/sshd_config

# 禁用root账户登录,非必要,但为了安全性,可以选择配置
PermitRootLogin no

# 是否让 sshd 去检查用户家目录或相关档案的权限数据,这是为了担心使用者将某些重要档案的权限设错,可能会导致一些问题所致。例如使用者的 ~/.ssh/ 权限设错时,某些特殊情况下会不许用户登入
StrictModes no

# 是否允许用户自行使用成对的密钥系统进行登入行为,仅针对 version 2。至于自制的公钥数据就放置于用户家目录下的 .ssh/authorized_keys 内
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys

# 有了证书登录了,就禁用密码登录吧,安全要紧
PasswordAuthentication no

最后,重启 ssh 服务,使得配置生效:

1
service sshd restart

2.4 配置ssh客户端config文件

ssh除了命令行配置参数外,还可以通过配置文件来辅助管理,有两个级别的配置文件:

  • 用户级(user-specific file):~/.ssh/config,通常不存在,如果需要自己新建
  • 系统级(system-wide file):/etc/ssh/ssh_config,内置有一些默认配置

当需要管理多个远程服务器时,可以用配置文件进行管理,其格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Host 服务器名A
user 用户名
hostname 服务器ip
port 端口号
identityfile 本地私钥地址(可选,默认:~/.ssh/id_dsa)
...
Host 服务器名B
user 用户名
hostname 服务器ip
port 端口号
identityfile 本地私钥地址(可选,默认:~/.ssh/id_dsa)
...
...
...
Host *
...
...

3 原理阐述

通过密钥验证的方式进行远程登录主要的原理是利用了非对称密码算法,也被称为公钥算法。该算法使用一个秘钥(又被称为公钥)进行加密,用另外一个秘钥(又被称为私钥)进行解密。

常见非对称算法包括 RSA、SM2(国密)、DH、DSA、ECDSA、ECC 等。

4 参考文献

[1] Linux系列 | SSH 如何使用密钥登录服务器 - 腾讯云开发者社区-腾讯云

[2] 使用 SSH-Key 登录远程服务器 - 简书

[3] 设置 SSH 通过密钥登录 | 菜鸟教程

[4] [SSH]客户端配置文件config - Network Guide