拿到一台全新的Ubuntu云服务器,默认状态下的安全防护几乎等于裸奔。最常见的攻击不是针对你个人,而是自动化扫描脚本在互联网上地毯式搜索弱口令和漏洞。不做任何加固直接部署业务,快则几分钟,慢则几小时,就会被植入挖矿木马或被当成跳板。下面这份清单按照操作优先级排列,每一条都是实战中验证过的必要步骤。

锁定SSH访问:改端口只是第一步

默认的22端口是扫描器重点关照对象。修改SSH端口能过滤掉90%以上的自动化攻击噪音,但这只是障眼法,核心在于密钥认证和权限控制。先别急着改端口,确保密钥登录可用,否则把自己锁在服务器外面就麻烦了。

在本地生成密钥对:

ssh-keygen -t ed25519 -C "your-server-name"

将公钥上传到服务器:

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your-server-ip

确认密钥可以正常登录后,编辑SSH配置文件:

sudo nano /etc/ssh/sshd_config

修改以下关键参数。Port改为一个高位端口号,比如22222或更高,避免与其他服务冲突。PermitRootLogin设为no,禁止root直接登录,这是最基础也是最重要的防线。PasswordAuthentication设为no,彻底关闭密码认证,只允许密钥登录。PubkeyAuthentication设为yes,确保密钥认证开启。AuthorizedKeysFile指向正确的公钥存储位置。AllowUsers指定仅允许特定用户登录,这是白名单机制,比黑名单安全得多。

修改完成后重启SSH服务:

sudo systemctl restart sshd

保持当前终端窗口不要断开,另开一个新终端测试新端口和密钥是否能正常登录。确认无误后再关闭旧连接。如果出现问题,旧窗口还保留着会话可以回滚配置。

防火墙策略:从零信任开始构建

Ubuntu默认的ufw工具本质上是iptables的友好封装。原则很简单:先拒绝所有入站流量,再按需开放端口。这比默认允许再逐个封禁要安全得多。

sudo ufw default deny incoming
sudo ufw default allow outgoing

开放修改后的SSH端口:

sudo ufw allow 22222/tcp

如果运行Web服务,开放HTTP和HTTPS:

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

确认规则无误后启用防火墙:

sudo ufw enable

用sudo ufw status verbose查看当前规则列表,确保每个开放的端口都有明确用途。生产环境里每多开一个端口,就多一个潜在攻击面。定期审查规则,关掉不再使用的端口。

系统更新自动化与内核安全

刚上线的系统可能存在已知漏洞,第一时间更新所有软件包:

sudo apt update && sudo apt upgrade -y

建议安装无人值守更新,让安全补丁自动安装,避免人为遗忘:

sudo apt install unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades

编辑/etc/apt/apt.conf.d/50unattended-upgrades,确认安全更新源已启用。重点勾选“${distro_id}:${distro_codename}-security”这一行。可以设置自动清理旧内核,防止/boot分区被占满。

内核参数也需要调优。编辑/etc/sysctl.conf或创建/etc/sysctl.d/99-security.conf,加入以下内容:

# 防止SYN洪水攻击
net.ipv4.tcp_syncookies = 1
# 禁止IP源路由
net.ipv4.conf.all.accept_source_route = 0
# 忽略ICMP重定向
net.ipv4.conf.all.accept_redirects = 0
# 启用反向路径过滤
net.ipv4.conf.all.rp_filter = 1

执行sudo sysctl -p使其生效。这些参数能防御常见的网络层攻击手法。

用户权限与审计体系

创建一个普通用户用于日常操作,而不是直接用root。这个用户需要sudo权限来执行管理命令:

sudo adduser yourusername
sudo usermod -aG sudo yourusername

检查/etc/sudoers文件,确保只有必要的用户拥有sudo权限。可以用visudo命令安全地编辑该文件。建议开启sudo操作日志记录,在/etc/sudoers中添加:

Defaults logfile="/var/log/sudo.log"

这样每次sudo操作都会被记录下来,事后审计有据可查。

检查系统中是否存在无密码的用户账户:

sudo awk -F: '($2 == "") {print $1}' /etc/shadow

如果有输出,说明存在空密码账户,必须立即设置密码或禁用该账户。

Fail2ban:动态防御的必备工具

防火墙是静态规则,Fail2ban提供动态响应能力。它监控日志文件,发现暴力破解行为后自动封禁攻击IP。安装很简单:

sudo apt install fail2ban -y

创建本地配置文件覆盖默认设置:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

编辑jail.local,重点配置SSH防护。在[sshd]段落下设置:enabled = true,port改为你修改后的SSH端口号,maxretry设为3,bantime设为3600或更长,findtime设为600。这意味着10分钟内失败3次就封禁1小时。可以根据实际情况调整,但不要把maxretry设得太大,3次足够正常用户纠正输入错误了。

重启服务并设置开机自启:

sudo systemctl enable fail2ban
sudo systemctl restart fail2ban

用sudo fail2ban-client status sshd查看封禁状态。如果看到封禁列表里有IP,说明已经在发挥作用了。

禁用不必要的服务和进程

最小化原则:只运行业务必需的服务。列出所有监听端口:

sudo ss -tlnp

仔细审查每个监听的服务。常见的可以关闭的服务包括:avahi-daemon(零配置网络服务,服务器环境用不到)、cups(打印服务)、rpcbind(远程过程调用,NFS才需要)。关闭方式:

sudo systemctl disable --now servicename

同时检查开机自启项:

sudo systemctl list-unit-files --state=enabled

禁用不需要的自启服务,减少攻击面也节省系统资源。

日志审计与入侵检测

安全加固不是一次性工作,持续的监控才能及时发现异常。首先确认rsyslog服务正常运行:

sudo systemctl status rsyslog

安装logwatch可以生成每日日志摘要报告:

sudo apt install logwatch -y

配置邮件发送报告,或者手动查看:

sudo logwatch --detail High --range today

对于更高要求的环境,可以考虑安装AIDE做文件完整性检查:

sudo apt install aide -y
sudo aideinit

AIDE会建立文件系统快照,检测关键系统文件是否被篡改。初始化后记得将数据库移到安全位置。

还有一个容易被忽略的点:检查crontab中是否有异常定时任务。攻击者常在crontab中植入持久化脚本:

sudo ls -la /var/spool/cron/crontabs
sudo cat /etc/crontab

逐条审查,不认识的条目要追查到底。

应用层安全配置

如果服务器运行数据库,务必修改默认端口并设置强密码。MySQL或PostgreSQL安装后应立即执行安全脚本:

sudo mysql_secure_installation

移除匿名用户、禁止远程root登录、删除测试数据库。对于Redis这类内存数据库,务必设置requirepass密码,并绑定到127.0.0.1,禁止外部访问。

Web应用层面,检查Nginx或Apache的配置,隐藏版本号信息。Nginx在http块中添加server_tokens off;Apache在配置中设置ServerTokens Prod和ServerSignature Off。这些信息虽然不算致命漏洞,但减少信息泄露能提高攻击者的侦察成本。

如果使用PHP,务必检查php.ini中的关键配置:expose_php = Off,disable_functions中根据需求加入exec、shell_exec、system等危险函数,allow_url_fopen和allow_url_include设为Off。

备份策略:最后一道防线

安全措施再完善也无法保证100%安全,备份是最后的保险。至少要做到关键配置文件的定期备份。可以写一个简单的备份脚本,把/etc/ssh/sshd_config、/etc/ufw/、/etc/fail2ban/、/etc/sysctl.conf等配置文件打包,配合crontab定时执行,推送到远程存储或其他服务器。

数据库备份同样重要,mysqldump或pg_dump配合cron定时任务,保留最近7天的备份文件。备份文件本身也要注意权限设置,600权限仅root可读。

以上步骤执行完毕后,建议做一次全面的安全检查。用sudo netstat -tlnp再次确认监听端口,用sudo last查看登录记录,用sudo faillog -a查看失败登录尝试。每一项都正常,这台Ubuntu服务器才算达到了基本的安全基线。安全是一个持续的过程,保持更新、定期审查、关注安全公告,这些习惯比任何一次性配置都重要。