为什么要做安全防护?
Linux 服务器的安全防护是一个纷繁复杂的巨大课题。无数的网站、APP、服务、甚至线下基础设施都建立在 Linux 的基石之上,这背后牵涉到巨大的经济利益和商业价值,当然也就就意味着黑灰产有巨大的攻击动力。但是这些服务是如此重要、根本不允许出现重大的安全漏洞。于是无数的运维专业人员都在安全攻防的战场上拼搏努力,这才让大家能享受到基本稳定的现代化数字生活。
现在,你拥有了一台 VPS,并且将会敞开他的数据访问渠道来达到流量转发的目标,那就相当于你已经置身于安全攻防战场的第一线、直面所有风险。但与此同时,新人由于知识和信息的不足,看待安全问题是总是难免两极分化:要么觉得轻如鸿毛和自己没有半点关系,要么觉得重于泰山甚至惶惶不可终日。
- 对于前者,我的建议是:安全无小事,尽量多查一些安全方面的信息,免得自己真的受了损失才后悔莫及
- 对于后者,我的建议是:不用紧张,我们的服务器仍不具有太高的价值、一般不会吸引到高水平的攻击,需要面对的基本都是一些自动化脚本的恶意扫描和登录尝试,跟着本文做一些基础的防护即可
具体的风险到底是什么
任何人只需要知道 【IP 地址】
+【端口】
+【用户名】
+【密码】
这四个要素,就能登录你的 VPS 服务器。那很显然,这四要素的安全就是我们要防护的底线。我们来逐一分析:
-
【IP 地址】:恶意脚本会随机尝试和扫描 IP 段,可以简单认为是公开信息、无法隐藏
-
【端口】:如果使用默认端口,那么【端口 =
22
】 -
【用户名】:如果使用默认用户,那么【用户名 =
root
】 -
【密码】:密码不存在默认值,一定是由 VPS 后台随机生成或由你自行设置的。也就是说,如果你的服务器都是默认设置,则四要素中的三个已经是已知的,那么你整个服务器的安全,就全部寄托在一串小小的密码上了。这时有几种情况:
- 如果你用了 VPS 管理后台随机生成密码,它一般包含随机的十几个大小写混杂的字母和符号,相对比较安全
- 如果你为了好记、把密码改成了类似
123456
这种超弱的密码,破解你的 VPS 服务器可谓不费吹灰之力 - 如果你为了好记、把密码改成了比较复杂、但在别的地方用过的密码,其实也并不安全。你要明白黑客手里有作弊器,比如说
密码表
,包含数万、数十万、数百万甚至更多曾经泄漏的真实密码)
-
但你要明白,没有哪个黑客真的要坐在电脑前一次一次的尝试你的密码,全部的攻击尝试都是恶意脚本自动进行的,它会 24 小时不眠不休的工作。也许每天你酣睡之时,你的服务器都在经受着一轮又一轮的冲击。
一旦密码被成功撞破,意味着你的四要素全部被攻击者掌握,恶意脚本就会快速登录服务器、获取服务器的最高
root
控制权、安装部署它的恶意服务,然后就可以用你的服务器来 24 小时做各种坏事(比如挖矿、传播病毒、发送垃圾邮件、欺诈邮件、做 BT 中继、甚至暗网公众节点等等等等)。如果恶意脚本比较克制,其实可以做到相当的隐蔽性。而新人一般也不会去观察留意 VPS 的登录记录、进程变化、CPU 占用变化、流量变化等指标,你其实就很难发现自己被黑了。直到你的 VPS 服务商封禁你的账号、或者收到律师函为止。 -
别忘了,你获得 VPS 时大概率需要使用真实的支付信息,你登录各种网站、社交平台时也会留下你的 IP 地址,这些都与你的身份有直接或者间接的关系。于是,一旦这些坏事发生,它们就不可避免的与你产生了关联。
基于上述分析,我们要做的,自然就是对【端口】、【用户名】、【密码】这三要素进行加强,来降低被攻破的风险
开始配置
1. 安装UFW防火墙
在对三要素进行加强前,你需要确认防火墙是否已经安装。若直接修改SSH端口,预置的防火墙将会拒绝你使用新端口访问
UFW
(Uncomplicated Firewall)是一个用于简化防火墙配置和管理的工具,常见于基于 Debian 的 Linux 发行版,如 Ubuntu。对于这些发行版,UFW
通常已经包含在默认的包管理系统中,但不一定默认安装和启用。
- 检查是否已安装
UFW
你可以使用以下命令检查系统中是否已经安装了 UFW
:
ufw status
如果 UFW
已安装且未启用,你会看到如下输出:
Status: inactive
如果未安装,你会收到类似于“command not found”的错误消息。
- 安装
UFW
如果 UFW
未安装,可以使用以下命令进行安装:
apt update
apt install ufw
- 启用
UFW
安装后,可以使用以下命令启用 UFW
:
ufw enable
- 配置
UFW
规则
你可以使用以下命令来配置 UFW
规则:
ufw allow 22/tcp #放行22端口
ufw delete allow 22/tcp #阻止22端口
- 禁用
UFW
如果需要禁用 UFW
,可以使用以下命令:
ufw disable
- 检查
UFW
状态
ufw status
这会显示当前的防火墙状态以及所有的已配置规则。
2. 更改 SSH 端口
第一步,我们先来解决【端口 = 22】的问题。(注意:有些 VPS 服务商,默认的端口已经是非 22 端口,那么你可以忽略这一步,当然也可以跟着本文改成别的端口)
我们要做的第一件事,当然就是【用 nano 这个文本编辑器打开SSH远程登录程序设置】,在 Windows 下,你会【找到文件并双击】,在 Linux 下该怎么办呢?仔细看看上面的命令说明,是不是就很简单了?没错,就是:
nano /etc/ssh/sshd_config
文件打开后,你就进入了 nano 的界面,稍微观察一下,你会发现,它把重要的快捷键都显示在屏幕下方了(下图红框内),直接开卷考试、不用死记硬背,是不是很贴心呢?
我们要做的第二件事,是【在打开的文件中找到 Port
这一项,并修改它的端口】。Port 后面的数字就是 SSH 的端口,一般建议把它改成一个大于 1024
小于 65535
的整数(本文以 2333
为例)。结合 nano 的快捷键,想一下该怎么操作呢?
使用 ctrl+w
进入搜索模式,然后输入 Port 22
并回车
删除 22
并改成 2333
说明:如果这一行开头有个 #
,证明这一行【不生效】(被注释掉了),你可像我一样在文件最后写一个不带 #
的,或者把 #
删掉就好。
我们要做的第三件事,是【保存文件并退出】
如果第 3 步你有仔细观察,就会发现保存并不是常见的 ctrl+s。
正确的快捷键:保存是 ctrl+o
+ 回车,退出是 ctrl+x
在进行下一步前,不要忘记修改防火墙配置
ufw allow 2333/tcp comment 'SSH' #添加2333为新端口
ufw delete allow 22/tcp #删除22端口
再次查看 UFW 状态
ufw status
可以看到规则已进行了更新
我们最后要做的事,是【重启 SSH 服务,使变更生效】
service sshd restart
3. 使用复杂的密码
如果你想给当前的用户设置重设密码,那么可以到这个网站,生成一个复杂的密码,当作你服务器的密码。
https://1password.com/zh-cn/password-generator/
- 修改 root 密码
passwd
出现提示让你修改密码。然后粘贴进去就行了。
注意为了安全的考量,Linux下输入密码是没有显示的
新建普通用户
接下来,我们来解决【用户名 = root】的问题。
首先你要理解, Linux 系统中的 root,不仅仅是一个管理员账号那么简单。它是整个系统的【根基】、是系统的主宰、至高无上的神。一旦 root 账号出现安全问题,整个系统都只能任人鱼肉、无处可逃。那么就跟随我进行操作吧:
我们要做的第一件事,是【新增一个用户并设定登录密码】,名字你可以随便起,我这里以 botai
为例:
adduser botai
adduser botai 10RLvEg43Xhmt5rg1tU7
执行命令后,根据提示操作即可。请务必设置一个用户密码(别忘记设置密码时你时看不到 ****** 的)。之后系统会询问你一些用户的附加信息,这些就可以无视,一路回车即可。
我们要做的第二件事,是【安装 sudo
功能】( sudo 就是在关键时刻,让普通账户临时获得 root
的神力,战力全开拯救世界)
apt update && apt install sudo #Debain默认没有,Ubuntu自身应该是已经有安装的
聪明的你大概已经发现,这一行命令其实是两个命令。前一半 apt update
你之前已经见过并且用过了,是去服务器刷新软件版本信息。后面的 apt install
就是这一次要用到的【安装命令】。两条连接在一起,就是让系统去【刷新可用的最新软件,然后安装最新版的 sudo 程序】。 && 则是把两个命令连起来执行的意思。
我们要做的第三件事,是【把用户 botai
加入 sudo 名单里,让他有资格借用 root 的神力】
visudo
在 User Privilege Specification
下加入一行 botai ALL=(ALL) NOPASSWD: ALL
即可。
我要特别说明的是
NOPASSWD
这个设置,它的意思是用户临时使用 root 权限时,不用额外输入密码。这与一般的安全建议相反。我之所以如此推荐,是因为很多新人不顾危险坚持使用 root 账号就是因为用 root 时不用重复输入密码、觉得轻松。“两害相权取其轻”,我认为【直接用 root 用户的风险】大于【使用 sudo 时不用输密码的风险】,所以做了以上的建议。如果你希望遵守传统习惯、每次使用 sudo 时需要输入密码,那么这一行改成vpsadmin ALL=(ALL:ALL) ALL
即可。
4. 禁止 root 登陆
现在你已经逐渐熟悉 Linux 了,所以这次换你思考,我们要做的第一件事是什么呢?没错,还是【用 nano 编辑器打开 SSH 远程登录程序设置】,什么,你想不起来怎么操作了?那去复习一下上面的内容再回来吧!............ 正确答案:
nano /etc/ssh/sshd_config
找到 PermitRootLogin Yes
这一项,然后把它后面的设定值改为 no
即可。还记得怎么操作吗?............ 正确答案:
使用 ctrl+w
进入搜索模式,然后输入 PermitRootLogin
并回车
删除 yes
并改成 no
保存文件并退出。还记得怎么操作吗?............ 正确答案:
保存是 ctrl+o
,然后 回车
确认退出是 ctrl+x
重启 ssh
服务,让变更生效。还记得............ 算了直接公布正确答案:
sudo service sshd restart
下次通过远程登录,root 用户已无法连接,
用户名就要换成 botai
了!如果你用的是类似 PuTTY、FinalShell 的软件,为方便起见,我们可以把 botai
设置成默认登录用户名。(别忘了保存 Session)
ssh botai@你的服务器IP -p 2333 #2333是你定义的SSH端口
5. 启用 RSA 密钥验证登录并禁止密码登陆
接下来,我们来解决【密码】可能被撞破的问题。
前面我说过,黑客并不是很蠢的用穷举法破解你的密码,而是会用一些比如“密码表”的作弊手段。除非你用的是随机生成的超长密码(比如借助 1Password,或者 macOS 的 keychain 等密码管理工具),否则很容易中招。
超长随机密码虽然安全性有所提高,但是基本上无法记忆,手动输入也十分麻烦易错。为了解决这个困境,我们可以直接弃用【密码验证】方式,改用更安全的【密钥验证】。
所谓的【密钥验证】,就是生成【一对】相关联的密钥文件(公钥和私钥),然后把【公钥】上传到 VPS 备用。每次登录时,SSH 会将【公钥】和【私钥】进行匹配,若验证是正确的【密钥对】,则验证通过。(换言之,你无需记忆和输入复杂的密码,只要保护好【私钥】这个文件不外泄即可)
本文以
RSA
密钥举例,是因为RSA
密钥在各种设备、各种 SSH 客户端中有广泛悠久的支持历史,且目前依然能提供够用的安全性。但它绝非唯一选择。其他的常见密钥还有:
- DSA - 已经从数学层面被证明不安全,所以永远不要用它
- ECDSA - 密钥小安全性高,但其算法被指留有 NSA 的后门,如果你的 VPS 上有值得 NSA 关注的东西就不要用它
- Ed25519 - 这是一个与 ECDSA 十分类似的算法,故具有相似的性能优势。同时其文档全部公开,所以普遍认为无后门
所以,如果你的设备和软件都支持的话,我建议优先选择
Ed25519
密钥。
当你使用 ssh-keygen
命令生成 SSH 密钥对时,并不会自动将公钥添加到远程服务器的 authorized_keys
文件中。这个文件通常位于远程服务器上的 ~/.ssh/authorized_keys
。
添加 SSH 公钥到远程服务器的 authorized_keys 文件
要将你生成的 SSH 公钥添加到远程服务器的 authorized_keys
文件中,需要执行以下步骤:
-
生成 SSH 密钥对
在本地计算机上使用 ssh-keygen 命令生成 SSH 密钥对:
ssh-keygen -t rsa -b 4096 -C "myvps"
这将生成
id_rsa
(私钥)和id_rsa.pub
(公钥)文件,默认存储在~/.ssh/
目录中。 -
连接到远程服务器
使用 SSH 连接到你的远程服务器,确保你有权限访问服务器:
ssh botai@你的服务器IP -p 2333
-
创建 authorized_keys 文件
mkdir -p ~/.ssh touch ~/.ssh/authorized_keys
-
添加公钥到 authorized_keys 文件
在本地执行:
ssh-copy-id -i ~/.ssh/id_rsa.pub -p 2333 [email protected]
-
设置正确的文件权限
确保
~/.ssh/
目录和authorized_keys
文件的权限设置正确,通常应该是:chmod 600 ~/.ssh/authorized_keys
这样可以确保只有你的用户可以读取这些文件。
-
编辑 SSH 配置文件
sudo nano /etc/ssh/sshd_config
搜索 PasswordAuthentication,把
yes
改成no
重启 SSH 服务。(啰嗦君:别忘了现在需要使用
sudo
来获得权限)sudo systemctl restart ssh
用另一个没有秘钥的服务器测试一下,可以看到已经无法连接了
-
测试 SSH 登录
现在,你可以尝试使用新生成的密钥对进行 SSH 登录:
ssh -i ~/.ssh/id_rsa username@remote_host ssh [email protected] -p 2333 #这两个都可以,我通常用下面这个
这里的
-i
选项指定使用id_rsa
私钥文件进行认证,username
是你在远程服务器上的用户名,remote_host
是远程服务器的 IP 地址或域名。成功!现在全世界也只有这台机子能连上我的服务器了!!!
注意事项
- 备份私钥:私钥 (
id_rsa
) 是你在本地计算机上的身份证明,请确保它的安全存储和备份。- 公钥传输:在添加公钥到服务器之前,请确保你在本地生成的公钥的内容是正确的。
- 权限设置:确保
~/.ssh/
目录和authorized_keys
文件的权限设置正确,以避免安全问题。
到这里为止,你的 VPS 已经完成了【端口】、【用户名】、【密码】这三要素的基本安全保障,虽然远称不上固若金汤,但一般的恶意脚本应该已经无法对你造成伤害了!
还没完成!让我们继续加固我们的”防线“
6. 禁止 Ping
禁止 ICMP echo 请求(ping)到服务器可以有以下几个理由:
- 减少暴露:
禁止 ping 可以防止潜在攻击者轻易发现你的服务器存在。ping 请求是网络扫描工具中最常用的方法之一,通过禁止 ping,可以在一定程度上隐藏服务器的存在,增加被发现的难度。 - 防止 DDoS 攻击:
ICMP echo 请求可以被滥用于 DDoS 攻击(如 Ping Flood )。通过禁止 ping,可以减少这种类型的攻击对服务器的影响。 - 减少不必要的流量:
在高流量环境中,ping 请求可能会消耗一定的带宽和服务器资源。虽然单个 ping 请求的资源占用很小,但如果有大量的 ping 请求,可能会影响服务器性能。 - 更严格的管理策略:
禁止 ping 可以作为网络策略的一部分,确保只有经过身份验证的用户或设备才能与服务器通信。这有助于网络管理员更好地管理和监控网络流量。
尽管如此,禁止 ping 也有其缺点,特别是在网络诊断和故障排除时。如果决定禁止 ping,需要权衡安全性与便利性之间的利弊。可以选择在某些环境中禁用 ping,而在受控环境或内部网络中保持 ping 的可用性,以便于管理和诊断。
sudo nano /etc/ufw/before.rules
搜索:echo-request
,把 ACCEPT
改成 DROP
重新加载 UFW 规则:
sudo ufw disable
sudo ufw enable
重新启用 ping
如果你需要重新启用 ping 请求,只需将之前修改的 DROP
改回 ACCEPT
:
-A ufw-before-input -p icmp --icmp-type echo-request -j ACCEPT
7. 安装 Fail2ban 禁止暴力破解
- 安装
sudo apt update && sudo apt install fail2ban
- 进入 Fail2ban 目录
cd /etc/fail2ban
- 复制一份配置文件
sudo cp jail.conf jail.local
- 检查一下
ls
- 编辑配置文件
sudo nano fail2ban.local
在 [sshd]
的位置添加以下内容,具体数值可以根据自己实际情况自行设置
[sshd]
enable = true
port = 2333
filter = sshd
logpath = %(sshd_log)s
backend = %(sshd_backend)s
maxretry = 5 #最大尝试次数
bantime = -1 #按秒算 -1则为永久
应该还记得怎么保存吧?(忘了的话向上翻翻)
- 启动和启用 Fail2ban 服务
sudo systemctl start fail2ban
sudo systemctl enable fail2ban
- 查看一下状态
systemctl status fail2ban
如果你的 Fail2ban 启动失败(系统使用 Debian12),原因可能是找不到日志文件,你可以尝试安装:
sudo apt install rsyslog
sudo apt install iptables
然后重新启动并查看状态
sudo systemctl restart fail2ban
systemctl status fail2ban
- 其他命令
sudo fail2ban-client status sshd #查看sshd的详细状态
sudo fail2ban-client set sshd unbanip 0.0.0.0 #解禁指定IP
现在我们终于有了一个安全的系统基础,下一章,我们就可以开始逐步配置需要的基础设施了!(什么基础设施呢?一个网页,一张证书)