一、先搞定最基础的账户安全:锁死暴力猜解的口子

新装好的Ubuntu服务器,默认的账户体系是最容易被盯上的薄弱点,尤其是密码猜解攻击,要是没做账户锁定,黑客可能会用工具批量试几千次密码,总有一次能蒙对。这一步必须先做,相当于给服务器的“大门”加了一道防撞锁。

1.1 账户锁定策略的配置逻辑

其实这个策略的核心就是:同一个账户,短时间内连续输错密码的次数超过限制,就临时把这个账户锁起来,不让再试。你可以自己调整“试错次数”“锁定时长”“统计时间范围”这三个参数,比如试错3次锁10分钟,10分钟内没解锁就再统计新的试错次数。

1.2 具体配置步骤(技术栈:Ubuntu系统默认的PAM认证模块)

PAM是Linux系统用来管认证的核心模块,我们改它的配置文件就能生效。首先打开对应的配置文件:

# 打开账户锁定的配置文件,用nano编辑器(新手友好,操作简单)
sudo nano /etc/pam.d/common-auth

打开后找到里面开头是auth的行,在最后加一行配置,这里给个完整的示例(带注释):

# 原有的行(不用改,只是给你看位置)
auth	[success=1 default=ignore]	pam_unix.so nullok_secure
# 新增的账户锁定配置(必须加在pam_unix.so这行后面)
auth	required	pam_tally2.so deny=3 unlock_time=600 even_deny_root root_unlock_time=300

这里的参数解释很重要,你得对应自己的需求改:

  • deny=3:连续输错3次就锁
  • unlock_time=600:普通账户锁600秒(10分钟)
  • even_deny_root:连root账户也会被锁(防止黑客专门攻击root)
  • root_unlock_time=300:root账户只锁300秒(5分钟,避免自己不小心把root锁太久)

改完保存退出nano(按Ctrl+O,回车,再按Ctrl+X),然后测试一下:故意输错密码3次,再用这个账户登录,会提示Account locked,说明配置生效了。

1.3 配置的优缺点和注意事项

优点:完全免费,系统自带,不用装额外软件,生效快,能直接挡住批量猜解的初级攻击; 缺点:如果是自己不小心输错密码,也会被锁,所以要把root的锁定时间设短一点;另外,这个策略只针对密码登录,要是用密钥登录的话,不触发这个锁定,所以后面还要配密钥登录。 注意事项:改配置前一定要备份原文件,万一改错了能恢复,备份命令是:

# 备份common-auth文件到当前用户目录,命名为common-auth.bak
sudo cp /etc/pam.d/common-auth ~/common-auth.bak

二、彻底关掉密码登录:只留安全的SSH密钥登录

SSH是我们远程连服务器的唯一通道(生产环境一般不用图形界面),默认的SSH是支持密码登录的,哪怕你做了账户锁定,还是有被破解的风险,所以必须改成只允许密钥登录,相当于给大门装了一把只有特定钥匙能开的锁。

2.1 SSH密钥的原理(用生活化的话讲)

密钥是一对东西:私钥和公钥。私钥只有你自己有,相当于你的“身份证原件”,公钥可以给服务器,相当于服务器门口的“门禁读卡器”。你连服务器的时候,服务器会给你发一个随机的“挑战”,你用私钥加密这个挑战发给服务器,服务器用公钥解密,能对上就允许你进,全程不用输密码,也不会在网络上传输密码,所以特别安全。

2.2 具体配置步骤(技术栈:Ubuntu系统默认的OpenSSH服务)

首先要在你自己的电脑上生成密钥对,注意:生成密钥的地方是你自己的电脑,不是服务器!

步骤1:本地生成密钥对

如果你是Windows电脑,用PowerShell;如果是Mac或Linux,用终端,输入下面的命令:

# 生成RSA密钥对,-t指定类型是rsa,-b指定密钥长度4096位(越长越安全),-C指定备注(方便你区分)
ssh-keygen -t rsa -b 4096 -C "your-email@example.com"

输入命令后会提示你指定密钥的保存路径,直接回车默认就好;然后会提示你输入密码短语(Passphrase),这个是给你的私钥加的二次保护,比如你电脑丢了,别人拿到私钥也得知道这个短语才能用,建议设置,要是嫌麻烦也可以直接回车跳过。

生成完后,你会得到两个文件:私钥(默认是~/.ssh/id_rsa)和公钥(默认是~/.ssh/id_rsa.pub)。

步骤2:把公钥传到服务器

接下来要把公钥放到服务器上,让服务器“认识”这个公钥,用下面的命令:

# 把本地的公钥传到服务器,替换成你的服务器IP和用户名(比如root)
ssh-copy-id root@你的服务器IP

执行这个命令后,会提示你输入服务器的密码(这是最后一次输服务器密码了),输入完就会把公钥传到服务器的~/.ssh/authorized_keys文件里。

步骤3:关掉服务器的密码登录

最后一步,改服务器的SSH配置,关掉密码登录,只留密钥登录。在服务器上执行:

# 打开SSH配置文件
sudo nano /etc/ssh/sshd_config

找到下面这几行,改成本文的样子(注意把原来的注释#去掉,或者改成对应的配置):

# 禁止root直接用密码登录(先改这个,防止自己连不上)
PermitRootLogin prohibit-password
# 禁止所有用户用密码登录
PasswordAuthentication no
# 禁止空密码登录(本来就是默认的,确认一下)
PermitEmptyPasswords no

改完保存退出,然后重启SSH服务让配置生效:

# 重启OpenSSH服务
sudo systemctl restart sshd

这时候你再测试一下,用本地电脑连服务器:

# 测试密钥登录,替换成你的服务器IP
ssh root@你的服务器IP

要是不用输密码就直接连上,说明配置成功了;要是连不上,别关当前的SSH窗口,再开一个窗口改配置(防止自己被锁在外面)。

2.3 配置的优缺点和注意事项

优点:彻底杜绝密码被破解的风险,安全级别非常高; 缺点:要是你的私钥丢了,你自己也连不上服务器,所以一定要备份私钥,比如存到U盘或者加密的云盘里; 注意事项:改SSH配置前,一定要先测试密钥登录能正常使用,再关密码登录;另外,PermitRootLogin prohibit-password的意思是root可以用密钥登录,但不能用密码登录,要是你想完全禁止root登录,改成PermitRootLogin no,然后建一个普通用户,给这个普通用户开sudo权限,这样更安全。

三、再加一道“防火墙”:用fail2ban挡住恶意攻击

哪怕你关了密码登录,还是会有黑客扫描你的服务器,找漏洞,fail2ban就是专门干这个的:它会监控服务器的日志,发现有恶意行为(比如短时间内多次尝试登录),就临时把这个IP封掉,相当于给大门装了一个监控摄像头,发现可疑人员就把他拦在外面。

3.1 fail2ban的工作原理

fail2ban会读系统的日志文件,比如SSH的登录日志,要是发现同一个IP在10分钟内有5次登录失败,就会调用系统的防火墙(比如ufw或者iptables),把这个IP封1小时,过了1小时再自动解封,这样既不会误伤自己,又能挡住恶意攻击。

3.2 具体配置步骤(技术栈:Ubuntu系统的fail2ban服务+ufw防火墙)

首先安装fail2ban:

# 安装fail2ban
sudo apt update && sudo apt install fail2ban -y

安装完后,fail2ban会自动启动,并且开机自启,但是默认的配置可能不够严格,我们要改一下。

首先,fail2ban的配置文件分两部分:主配置文件/etc/fail2ban/jail.conf(这个不要改,因为升级的时候会被覆盖),自定义配置文件/etc/fail2ban/jail.local(这个是我们要改的,不会被覆盖)。

所以先把主配置文件的内容复制到自定义配置文件:

# 把jail.conf的内容复制到jail.local
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

然后打开自定义配置文件:

# 打开fail2ban的自定义配置文件
sudo nano /etc/fail2ban/jail.local

找到[DEFAULT]部分(全局配置,对所有的监控项生效),改下面的参数:

# 全局配置部分(找到[DEFAULT]开头的部分)
[DEFAULT]
# 封禁的时长,单位是秒,这里设为3600秒(1小时)
bantime = 3600
# 统计的时间范围,单位是秒,这里设为600秒(10分钟)
findtime = 600
# 触发封禁的失败次数,这里设为5次
maxretry = 5
# 防火墙用ufw(因为Ubuntu默认的防火墙是ufw)
banaction = ufw

然后找到[sshd]部分(专门监控SSH登录的配置),改成本文的样子:

# 找到[sshd]开头的部分,改成下面的配置
[sshd]
# 启用这个监控项
enabled = true
# 日志路径,SSH的登录日志在这个地方
logpath = %(sshd_log)s
# 端口,SSH的默认端口是22(要是你改了端口,这里要改成你改后的端口)
port = 22
# 触发封禁的失败次数,这里可以比全局的更严格,设为3次
maxretry = 3

改完保存退出,然后重启fail2ban服务让配置生效:

# 重启fail2ban服务
sudo systemctl restart fail2ban

然后测试一下:故意用错误的密码连服务器3次,然后用fail2ban的命令看一下有没有封这个IP:

# 查看fail2ban的状态,看有没有被封禁的IP
sudo fail2ban-client status sshd

要是能看到你测试的IP被列在Banned IP list里,说明配置生效了。

3.3 配置的优缺点和注意事项

优点:能自动挡住批量扫描、暴力猜解的攻击,配置简单,不用自己手动封IP; 缺点:要是你不小心输错密码多次,你的IP也会被封,所以maxretry不要设得太低;另外,要是你改了SSH的端口,一定要在fail2ban的配置里改端口,不然fail2ban监控的还是旧端口,就没用了; 注意事项:fail2ban默认会监控SSH,你还可以加其他的监控项,比如监控nginx的日志,挡住扫网站漏洞的攻击,但是生产环境的核心是先保SSH的安全,所以先把SSH的监控配好。

四、最后一道防线:配置系统自动更新,补漏洞

服务器的系统和软件会不断有新的漏洞被发现,要是你不及时更新,黑客就会用这些漏洞攻击你的服务器,所以必须配置自动更新,让系统自动下载安装安全补丁,相当于给服务器定期体检,补好身体的漏洞。

4.1 自动更新的配置逻辑

Ubuntu的自动更新是用unattended-upgrades这个工具,它可以配置成只安装安全补丁,或者安装所有的更新,生产环境建议只安装安全补丁,因为其他的更新可能会有兼容性问题,影响业务的正常运行。

4.2 具体配置步骤(技术栈:Ubuntu系统的unattended-upgrades工具)

首先安装unattended-upgrades:

# 安装unattended-upgrades
sudo apt update && sudo apt install unattended-upgrades -y

安装完后,打开配置文件:

# 打开自动更新的配置文件
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades

找到下面的部分,改成本文的样子(只保留安全补丁的更新源):

# 找到Unattended-Upgrade::Allowed-Origins部分,改成下面的配置
Unattended-Upgrade::Allowed-Origins {
        "${distro_id}:${distro_codename}";
        "${distro_id}:${distro_codename}-security";
        // 注释掉下面的行,不安装非安全的更新
        // "${distro_id}:${distro_codename}-updates";
        // "${distro_id}:${distro_codename}-proposed";
        // "${distro_id}:${distro_codename}-backports";
};

然后找到下面的参数,改成本文的样子(配置自动重启):

# 找到下面的参数,改成true,自动重启服务器(要是安全补丁需要重启生效)
Unattended-Upgrade::Automatic-Reboot "true";
# 重启的时间,设为凌晨2点,这个时间业务量小,影响小
Unattended-Upgrade::Automatic-Reboot-Time "02:00";
# 重启前发邮件通知(要是你配置了邮件服务的话,这里改成你的邮箱)
Unattended-Upgrade::Mail "your-email@example.com";

改完保存退出,然后打开另一个配置文件,配置自动更新的时间:

# 打开自动更新的时间配置文件
sudo nano /etc/apt/apt.conf.d/20auto-upgrades

改成下面的配置:

# 配置自动更新的周期
APT::Periodic::Update-Package-Lists "1"; # 每天更新一次软件包列表
APT::Periodic::Download-Upgradeable-Packages "1"; # 每天下载可更新的软件包
APT::Periodic::AutocleanInterval "7"; # 每7天清理一次旧的软件包
APT::Periodic::Unattended-Upgrade "1"; # 每天执行自动更新

改完保存退出,然后测试一下自动更新的配置:

# 测试自动更新的配置,不会真的安装更新,只是检查配置是否正确
sudo unattended-upgrades --dry-run --debug

要是没有报错,说明配置生效了。

4.3 配置的优缺点和注意事项

优点:不用手动更新,能及时补安全漏洞,避免被黑客利用漏洞攻击; 缺点:自动重启可能会影响业务,所以一定要把重启时间设为业务量最小的时间段,比如凌晨;另外,要是你安装了自己编译的软件,自动更新不会管这些软件的漏洞,所以你还要定期手动检查这些软件的更新; 注意事项:配置自动更新前,一定要先备份服务器的数据,万一更新出问题,能恢复数据;另外,要是你的服务器是集群的一部分,自动重启可能会影响集群的正常运行,所以要把自动重启改成手动,或者配置成集群能自动接管故障节点。

五、生产环境的整体配置逻辑和总结

这四个配置是层层递进的:账户锁定是基础的防撞锁,密钥登录是彻底的大门锁,fail2ban是外围的监控,自动更新是内部的漏洞补漏,四个配置加起来,才能把服务器的安全级别提到生产环境的要求。

5.1 应用场景

这些配置适合所有新上线的Ubuntu服务器,尤其是公网可访问的服务器,比如网站服务器、API服务器、数据库服务器等;要是你的服务器是内网的,也可以配置,但是可以把参数设得宽松一点,比如maxretry设为10次,bantime设为300秒。

5.2 整体的优缺点

优点:所有配置都是系统自带或者免费的工具,不用花额外的钱;配置都是可调整的,能根据自己的需求改参数;安全覆盖的范围广,从登录到漏洞补漏都有; 缺点:需要你仔细配置,要是改了SSH端口,要同步改fail2ban的配置;要是你备份不好私钥,可能会连不上服务器;自动重启可能会影响业务;

5.3 整体的注意事项

  1. 改任何配置前,一定要备份原文件,比如改SSH配置前备份/etc/ssh/sshd_config,改PAM配置前备份/etc/pam.d/common-auth
  2. 配置任何安全项前,一定要测试,比如配完密钥登录,先测试能正常连,再关密码登录;配完fail2ban,先测试能正常封IP;
  3. 定期检查安全配置,比如每个月检查一次账户锁定的参数,检查一次fail2ban的封禁记录,检查一次自动更新的日志;
  4. 不要依赖单一的安全配置,比如配了密钥登录,还要配fail2ban和自动更新,多个安全配置加起来,才能挡住更多的攻击。