SSH 登录方式的防护
# 20.SSH 登录方式的防护
介绍下我们如何从密码暴力破解中保护我们的服务器。
# 默认登录方式的问题
如果你使用默认的 ssh 登录方式,非常容易被攻击的。每次登录后,都会有提示上次登录失败的时间,和登录失败的次数:
Last failed login: Mon Mar 6 20:13:48 CST 2023 from 182.246.58.5 on ssh:notty
There were 15474 failed login attempts since the last successful login.
2
可以看看有一万五千次登录失败……很明显,这肯定不是我自己登录失败的问题(谁会短期内输错密码一万多次啊 🤷♂️),而是因为有攻击者想通过暴力破解的方式来获取服务器密码。
登录后,也可以使用 lastb 命令来查看尝试登录但失败的用户信息(-n 选项表示显示多少个):
lastb -n 4
tahiry ssh:notty 143.198.85.60 Mon Mar 6 21:33 - 21:33 (00:00)
tahiry ssh:notty 143.198.85.60 Mon Mar 6 21:33 - 21:33 (00:00)
kajal ssh:notty 143.198.85.60 Mon Mar 6 21:32 - 21:32 (00:00)
kajal ssh:notty 143.198.85.60 Mon Mar 6 21:32 - 21:32 (00:00)
2
3
4
5
建议使用 -n 参数,我没加防护之前用 lastb 直接刷屏了。
大部分云服务器默认使用 root 用户以及 22 端口号 进行登录,这样很容易通过暴力破解密码。所以我们有必要修改下默认的登录方式:
- 修改 SSH 默认端口
- 不使用 root 用户登录
- 使用密钥登录
- ……
# 修改 SSH 默认端口
首先修改 SSH 的配置文件:
vim /etc/ssh/sshd_config
在文件最后增加两行配置:
port 22
port 12345
2
这两行就是配置我们可以用 22 和 12345 端口来进行 SSH 的登录。挑选端口时最好挑 10000~65535 之间的端口号,10000 以下容易被系统或一些特殊软件占用,或是以后新安装的应用可能占用该端口,所以 10000 以下的端口号都不要使用。
重启 SSH 服务(不同版本的服务器可能重启的方式不同,以 Centos 7 为例):
systemctl restart sshd.service
然后就可以使用新端口连接了,例如我用 Xshell,在设置里指定端口号 :
如果你用用命令行登录,也可以通过 -p 选项指定端口:
ssh root@你的IP地址 -p 12345
此时 22 和 23456 两个端口都可以成功登录 SSH ,确认新端口可登录后,就注释掉 22 端口,这样就不能用默认的端口登录了。
特别注意:
- 这里只所以先保留 22 端口,是担心读者配置错了,导致 22 端口都登录不了;此时就只能去云服务器控制台里登录了,比较麻烦。
- 如果你使用了云服务器,记得修改后记得配置云服务器的安全组,增加你新分配的端口。
- 如果你使用了系统默认防火墙,例如 iptables 、Firewalld,也要放开这个端口。
# 禁用 root 用户登录
一般来说,我们都不会轻易使用 root 用户,因为 root 用户的权限太大了。在笔者所在的公司里,都是一个应用一个用户的,例如 Nginx 服务就有一个 web 用户,MySQL 服务就有一个 MySQL 的用户。
当然,我们自己的服务器可以不用那么多用户,但还是不建议有 root 用户可以直接登录的情况。
# 添加用户
增加一个 PeterJXL 的用户:
$ useradd PeterJXL
$ passwd PeterJXL
Changing password for user PeterJXL.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
2
3
4
5
6
说明:
- 命令 useradd PeterJXL,增加了普通用户名 PeterJXL(可以修改为你自己喜欢的登录用户名)
- 命令 passwd PeterJXL,为用户 PeterJXL 设置登录密码
- 然后我们就可以用这个用户进行的登录了。
然后就可以登录该用户了。用命令行登录时,也要修改对应用户名:
ssh PeterJXL@你的IP -p 23456
# 添加到 sudoers
普通用户基本没什么权限,有时候一些操作需要使用 root 权限,那么就需要切换到 root 用户。
默认情况下,普通用户切换到 root 用户是不允许的:
$ sudo -s
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
[sudo] password for PeterJXL:
PeterJXL is not in the sudoers file. This incident will be reported.
2
3
4
5
6
7
8
9
10
11
最后一行告诉我们,该用户不在 sudoers 的文件里,因此不被认为有管理员权限。
我们需要添加该用户为管理员的话,就先用 root 用户登录,然后修改文件权限,拥有编辑文件写的权限:
chmod u+w /etc/sudoers
然后编辑文件 /etc/sudoers:
vim /etc/sudoers
再在 root ALL=(ALL) ALL
下添加一行 PeterJXL ALL=(ALL) NOPASSWD:ALL
(注意修改为你自己的用户名)
## Allow root to run any commands anywhere
root ALL=(ALL) ALL
PeterJXL ALL=(ALL) NOPASSWD:ALL # PeterJXL为你自己的用户名
2
3
改回 sudoers 文件的原权限,提高其安全性:
chmod u-w /etc/sudoers
# 自动切换为 root
如果你想更方便点,可以设置普通用户登录后自动切换为 root 用户。
修改当前用户目录下的 .bash_profile 文件:
vim ~/.bash_profile
在该配置文件中添加一行:
sudo su root
然后我们再以 PeterJXL 的用户登录,就可以看到自动切换为了 root 用户了。
# 禁用 root 用户登录
现在我们可以开始禁用 root 用户登录了。
修改配置文件:
vim /etc/ssh/sshd_config
在文件最后添加一行:
PermitRootLogin no
重启 ssh 服务:
systemctl restart sshd.service
验证 root 能否登录:可以看到确实禁用了
ssh root@你的IP -p 23456
root@1xx.xx.xx's password:
Permission denied, please try again.
2
3
# 密钥登录
除了密码登录外,我们还可以使用密钥来进行身份认证与登录。
# 切换回普通用户
我们需要用到普通用户,但由于我们刚刚设置了自动切换为 root 用户,因此得切换回普通用户。
可以输入 exit 或者按快捷键 ctrl + D 即可切换回原用户,切换后用 who 来确定下当前用户是谁:
$ exit
$ who
PeterJXL pts/0 2023-03-07 07:29 (116.21.29.96)
2
3
# 安装 openssl
先确认有没安装 openssl:输入 openssl version
,如果有输出 openssl 的版本,则说明安装了。
$ openssl version
OpenSSL 1.1.0f 25 May 2017
2
如果没有,则说明没安装,需要安装:(不同服务器的安装命令可能不同)
yum install openssl -y
# 生成密钥
我们进入当前用户的 home 目录并生成密钥:
cd ~
ssh-keygen
2
根据提示,输入生成 rsa 的密码(使用密钥文件时需输入的密钥,增强安全性,也可以不设置)
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/PeterJXL/.ssh/id_rsa):
Enter passphrase (empty for no passphrase): # 设置密钥文件的密码
Enter same passphrase again: # 重复一次设置密钥文件的密码
Your identification has been saved in /home/PeterJXL/.ssh/id_rsa.
Your public key has been saved in /home/PeterJXL/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:h9inbBVu0V+fBlx88+VJ6zC+U0y1mW6dz+wOiBWoYTs PeterJXL@mail.peterjxl.com
The key's randomart image is:
+---[RSA 2048]----+
| .. |
| o. .++|
| o + oo..&|
| + * o =.O=|
| . E * o Oo+|
| . B o o.B.|
| + . . =o.|
| . o .+|
| .oo|
+----[SHA256]-----+
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
生成后的密钥在当前用户的 home 目录下的 .ssh
目录里(是一个隐藏文件夹,可以用 ls -a
查看)
# 配置公钥
我们接下来就是授权:
cd ~/.ssh/
cp id_rsa.pub authorized_keys
2
修改密钥文件的权限,免得被其他用户查看和修改:
chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh
2
# 配置公钥登录
修改配置文件:
sudo vim /etc/ssh/sshd_config
在文件最后一行添加:
PasswordAuthentication yes
重启以使配置文件生效:
sudo systemctl restart sshd
至此,服务器上的配置就完成了。然后下载私钥文件到本地:
$ sz ~/.ssh/id_rsa
然后就可以用该密钥登录了。
# 使用 Xshell 登录
登录的时候指定密钥文件(例如 Xshell,其他 SSH 连接工具同理,这里就不演示了):选择用 Public Key 登录,然后选择密钥文件,并输入密码(就是我们刚刚生成 rsa 密钥文件时输入的密码,如果没设置就空着)
# 使用 Windows 命令行登录
如果你用 Windows 下的命令行登录,可能会遇到这样的问题:
$ ssh PeterJXL@你的IP -p 23456 -i id_rsa
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions for 'id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "id_rsa": bad permissions
2
3
4
5
6
7
8
注意第 6 行,告诉我们你的文件不能被其他人访问到,也就是说中这个文件是可以被其他人看到的,不安全,所以不允许用来登录。
解决办法:修改文件属性。在文件上右键(或者按住 Alt 双击文件),打开文件属性,然后:
- 进入安全页
- 可以看到,许多主体拥有这个文件的权限,如 SYSTEM、Administrators。我们要把这些主体从权限目录中删掉
- 我们点击高级
我们禁用继承,选择从此对象中删除所有已继承的权限;
这时权限目录应该变空了。选择添加,点击选择主体,输入用户名(就是你登录 Windows 时的用户名,可以从 C:\Users 目录下查看)。输入完后可以选择检查名称,查看输入的是否正确
然后就可以登录了:
ssh PeterJXL@你的IP -p 23456 -i id_rsa
Enter passphrase for key 'id_rsa':
Last login: Tue Mar 7 07:59:25 2023 from 116.21.29.96
Welcome to Alibaba Cloud Elastic Compute Service !
2
3
4
5
登录过程中提示我们输入密钥文件的密钥,即刚刚我们设置的,最后成功登录。
# 使用 Linux 下命令行登录
如果你在 Linux 下登录其他远程服务器,也出现了这个问题的话:
It is required that your private key files are NOT accessible by others.
修改权限就可以:
chmod 600 id_rsa
# 取消私钥密码
若不想使用 rsa 密钥文件时输入密码,可以取消私钥密码。
openssl rsa -in ~/.ssh/id_rsa -out ~/.ssh/id_rsa_nopassword
然后,通过无密码的私钥文件登录:
ssh -i id_rsa_nopassword PeterJXL@你的IP -p 23456 # 不需要输入私钥的密码
此时,加密的私钥文件 + 密码,和无密码的私钥文件,都可以用来登录服务器。
# 禁用密码登录
如果你只想用密钥登录,可以取消密码登录。修改配置文件:
sudo vim /etc/ssh/sshd_config
找到关键字"PasswordAuthentication
",修改 PasswordAuthentication yes
为 PasswordAuthentication no
这里特别要注意:即使注释掉了此行,默认还是允许密码登录的。要禁用密码登录一定要明确地改为 no。
最后别忘了重启:
systemctl restart sshd
# 多个服务器共享密钥
当你有多台 Linux 服务器, 懒得一个个生成密钥的时候,就可以多个服务器共享一个密钥:
- 在一台服务器上生成密钥,然后将公钥拷贝到其他 Linux 服务器上(路径为~/.ssh/ )
- 将公钥内容输出到 ~/.ssh/authorized_keys
# 带密码登录
在使用 SSH 登录远程服务器的时候,在执行完 ssh user@ip
后,要输入登录密码,有没有一种在 SSH 的参数中直接加入密码的方法呢?目前是没有的,因为命令会被存储在历史记录中(可以用 history 来查看输入过的命令),非常不安全,因此即使能也不建议这么做。
ssh
命令的完整格式如下:
usage: ssh [-1246AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]
[-D [bind_address:]port] [-E log_file] [-e escape_char]
[-F configfile] [-I pkcs11] [-i identity_file] [-L address]
[-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]
[-Q query_option] [-R address] [-S ctl_path] [-W host:port]
[-w local_tun[:remote_tun]] [user@]hostname [command]
2
3
4
5
6
如果你实在想要用密码去交互,也是可以的。考虑这样的场景:几个人维护几十台服务器,如果每个服务器都要升级某个工具,此时我们可以通过脚本或工具来进行批量操作(通过命令登录服务器后执行升级命令),例如 sshpass 和 expect。
# 总结
本文介绍了如下措施,提高服务器安全性:
- 修改 SSH 默认端口
- 禁用 root 用户登录
- 使用密钥登录,禁用密码登录
以上方式中,强烈 1 和 2 都实施,至于第三种则按需选择使用。此外,如果使用密码登录,定期修改密码也是很重要的。
如果你选择了密码登录,那么即使换了端口,还是有被暴力破解的风险,指不定啥时候某个密码比较弱的用户就被攻陷了,此时我们可以使用第三方软件,当检测到暴力破解的时候,就封禁掉对方的 IP,我们在下一篇博客介绍。
# 参考
Linux lastb 命令 | 菜鸟教程 (opens new window)
Linux 修改默认端口、增加普通用户、使用密钥等安全登录 SSH - 米扑博客 (opens new window)
win 10 修改文件权限为 600 - 知乎 (opens new window)
windows 下 CMD 中使用 ssh 登录远程服务器报 Permissions for ‘xxx‘ are too open. (opens new window)