云服务器拿到手之后,默认配置离“能扛住真实互联网环境”还有很长一段距离。很多攻击和入侵并不是因为漏洞多高级,而是因为默认端口、默认账号、宽松权限和没做隔离。下面直接按操作顺序讲清楚每一环该改什么、怎么改、为什么这么改。

第一步:禁用root密码登录,改用密钥对

root账号是几乎所有自动化攻击的第一目标。只要你的SSH端口暴露在公网,每天都会有大量脚本尝试用常见密码撞库。正确做法是先创建一个普通用户,给它sudo权限,然后关闭root的SSH登录。

# 创建新用户
adduser deploy
# 加入sudo组
usermod -aG sudo deploy
# 切换到新用户,确认sudo可用
su - deploy
sudo whoami

接下来生成本机密钥对,把公钥写入服务器。不要用密码登录,密码登录既慢又不安全,而且无法防止暴力破解。

# 本地执行,生成密钥
ssh-keygen -t ed25519 -C "deploy@your-server"
# 上传公钥
ssh-copy-id -i ~/.ssh/id_ed25519.pub deploy@你的服务器IP

确认能通过密钥登录后,编辑SSH配置文件。

sudo nano /etc/ssh/sshd_config

修改或确认以下参数:

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2

保存后重启SSH服务。注意先保留一个已登录的会话,防止配置错误把自己锁在外面。

sudo systemctl restart sshd

第二步:修改默认SSH端口并限制来源IP

把22改成高位端口并不能提升加密强度,但能过滤掉90%以上的无差别扫描。对于不需要对外开放SSH的服务器,最安全的方式是用安全组或防火墙直接限制来源IP。如果必须从多地点登录,至少把端口改掉。

sudo nano /etc/ssh/sshd_config
# 找到Port 22,改成例如
Port 22900

同时建议在云服务商的安全组里只放行你当前出口IP访问这个端口,而不是对0.0.0.0/0开放。安全组是第一道闸门,服务器内部iptables或ufw是第二道。

# 如果使用ufw
sudo ufw allow 22900/tcp
sudo ufw enable

改完端口后,本地连接时需要指定-p参数。别忘记在云控制台同步更新安全组规则,否则新端口不通。

第三步:启用自动安全更新

大部分被攻破的服务器并不是因为0day,而是因为已知漏洞没有及时修补。手动登录更新太被动,应该配置无人值守更新。Debian/Ubuntu系使用unattended-upgrades。

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

选择“是”启用自动更新。然后可以编辑配置文件,只更新安全源。

sudo nano /etc/apt/apt.conf.d/50unattended-upgrades

至少保证安全更新部分没有被注释。对于生产环境,建议在测试机先验证更新,再在业务低峰期执行。如果担心自动更新导致服务中断,可以设置只下载不安装,或者用定时任务在凌晨执行。

第四步:配置防火墙,只放行必要端口

默认策略应该是拒绝所有入站流量,只放行业务需要的端口。比如Web服务器只开80和443,数据库端口绝不对外。用ufw可以快速设置。

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 22900/tcp
sudo ufw enable

如果服务器上有多个网卡或内网服务,注意区分公网和内网接口。数据库、Redis、Memcached这类服务必须监听内网地址,比如127.0.0.1或内网网卡IP,而不是0.0.0.0。

第五步:Web服务器与PHP权限加固

Nginx或Apache默认以www-data用户运行,这个用户不应该拥有网站文件的写权限。很多一键脚本为了方便,把整个网站目录设成777,这是非常危险的。正确做法是网站文件属主为deploy,www-data只读,需要上传或缓存的目录单独授权。

sudo chown -R deploy:deploy /var/www/your-site
sudo chmod -R 755 /var/www/your-site
# 仅uploads和缓存目录可写
sudo chown -R www-data:www-data /var/www/your-site/wp-content/uploads
sudo chmod -R 775 /var/www/your-site/wp-content/uploads

PHP配置中必须关闭危险函数,尤其是exec、shell_exec、system、passthru等。编辑php.ini:

disable_functions = exec,shell_exec,system,passthru,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
expose_php = Off
display_errors = Off
log_errors = On

display_errors关闭后,错误信息不会暴露给访问者,避免泄露路径和代码结构。生产环境日志记录要开启,方便排错。

第六步:HTTPS与安全响应头

证书用Let's Encrypt即可,配置certbot自动续期。Nginx配置中强制跳转HTTPS,并加上安全响应头。

server {
    listen 80;
    server_name your-domain.com;
    return 301 https://$host$request_uri;
}
server {
    listen 443 ssl http2;
    server_name your-domain.com;
    ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header X-XSS-Protection "1; mode=block" always;
}

这些响应头能防止点击劫持、MIME类型嗅探和部分XSS攻击。如果业务不需要被嵌入iframe,X-Frame-Options可以设成DENY。

第七步:数据库安全配置

MySQL或MariaDB安装后必须运行安全脚本,移除匿名用户、测试数据库,并设置root密码。

sudo mysql_secure_installation

数据库只监听本地或内网地址。编辑mysqld.cnf:

bind-address = 127.0.0.1

如果应用和数据库在同一台服务器,这样设置最安全。如果必须远程连接,使用内网IP并限制来源IP,同时创建独立账号,只授予必要权限,禁止使用root远程连接。

CREATE USER 'appuser'@'10.0.0.5' IDENTIFIED BY '强密码';
GRANT SELECT,INSERT,UPDATE,DELETE ON appdb.* TO 'appuser'@'10.0.0.5';
FLUSH PRIVILEGES;

第八步:日志监控与入侵检测

配置好基础安全后,还需要知道服务器上正在发生什么。安装fail2ban可以自动封禁暴力破解的IP。

sudo apt install fail2ban -y
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

默认配置对SSH有效,可以根据需要添加Nginx、MySQL等jail。查看封禁情况:

sudo fail2ban-client status sshd

日志方面,至少保证auth.log、syslog和Nginx访问日志正常记录。可以用logwatch或简单的脚本定期汇总异常登录记录。对于关键目录,可以用auditd监控文件变更,尤其是/etc、/usr/bin等系统目录。

第九步:定期备份与恢复演练

安全配置做得再好,也无法100%防止数据丢失或勒索。备份必须自动化,并且要验证可恢复性。数据库每天全量备份,网站文件增量备份,备份文件同步到对象存储或另一台服务器。

# MySQL备份示例
mysqldump -u backupuser -p appdb | gzip > /backup/db-$(date +%F).sql.gz
# 同步到对象存储(以S3兼容为例)
aws s3 sync /backup s3://your-bucket/backup/

至少每月做一次恢复演练,确认备份文件能正常还原。很多团队直到出事才发现备份是坏的,这种教训代价极大。

第十步:最小化安装与定期审计

服务器上不要装任何与业务无关的软件。每多一个服务就多一个攻击面。定期检查开放端口、运行的服务和计划任务。

sudo netstat -tulpn
sudo systemctl list-unit-files --state=enabled
sudo crontab -l
sudo ls -la /etc/cron.d/

发现不认识的进程或计划任务要立刻排查。同时定期检查用户列表,确认没有多余账号,尤其是UID为0的账号。

awk -F: '($3 == 0) {print}' /etc/passwd

正常情况应该只有root一行。如果出现其他UID为0的账号,说明服务器已经被入侵或配置错误。

以上这些操作不是一次性做完就结束了。安全是一个持续过程,需要定期复查配置、更新策略、查看日志。云服务器的安全基线打好了,后续业务扩展时才有底气。最怕的是默认配置直接上线,等于把家门钥匙挂在锁孔上。