这是「把自己部署到互联网上」系列的第 16 篇。
前几篇围绕服务器安全展开:不要急着部署项目,不要长期用 root 登录,分清安全组和防火墙,不要随便开放数据库端口,也记录了服务器4小时被扫 500 多次后的判断。到这里,需要把这些内容收束成一份清单。
这不是企业级安全方案,也不是完整加固手册。它只是我给个人服务器设定的最低安全标准:在部署博客、Nginx、Docker、数据库和 HTTPS 之前,先把基础风险过一遍。
为什么需要基础安全检查
为什么需要清单?因为感觉是个小项目,心理上容易跳过基础安全。
买完服务器想马上部署,装完 Docker 想马上跑项目,域名解析好了想马上访问页面。
节奏没问题,但如果没有检查清单,就容易留下明显缺口:
root还在直接登录- SSH 还是弱密码
- 安全组开放过宽
- 数据库端口暴露公网
- 防火墙状态没确认
- 日志从没看过
- 磁盘和服务状态也没有检查习惯
这些问题短期不一定会爆,但会增加后续维护风险。
我把上线前基础安全项分成 8 类:普通用户、SSH、安全组、防火墙、数据库端口、fail2ban、日志和健康检查。
检查清单
普通用户登录。
root 账户权限太大,适合做系统初始化,不适合日常维护。创建普通用户,给普通用户 sudo 权限,日常操作尽量不用 root。
常用检查命令:
id 用户名
groups 用户名
sudo whoami
如果 groups 用户名 里包含 sudo,并且 sudo whoami 输出 root,说明基本权限可用。关键提醒是:不要在普通用户登录验证完成前,就禁用 root。安全配置要留退路。
SSH 登录策略
SSH 是服务器管理入口,不是给普通用户访问的网站入口,所以要更谨慎。
重点检查:
- 是否允许 root 直接登录
- 是否使用强密码或密钥
- 是否有大量失败登录尝试
- SSH 端口是否被安全组和防火墙正确控制
查看配置:
sudo grep -E 'PermitRootLogin|PasswordAuthentication|PubkeyAuthentication|Port' /etc/ssh/sshd_config
修改前先备份:
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
修改后先检查语法:
sudo sshd -t
再重载服务:
sudo systemctl reload ssh
有些系统服务名是 sshd:
sudo systemctl reload sshd
建议 不要关闭当前会话。新开终端确认新配置能正常登录后,再关闭旧会话。
安全组规则
安全组是云平台层面的入口规则,决定外部流量能不能到达服务器。个人博客初期,公网入口应尽量简单:SSH 管理端口、80、443。其他端口默认不对公网开放。
尤其不要把 MySQL 的 3306、PostgreSQL 的 5432、Redis 的 6379、Elasticsearch 的 9200、MongoDB 的 27017、Docker 管理端口随手开放给 0.0.0.0/0。
检查安全组时看两点:开放了哪些端口,来源范围是否过宽。如果只是临时开放,用完要关。临时规则最容易变成永久风险。
系统防火墙。
安全组在云平台入口,防火墙在服务器内部,两者不是一回事。Ubuntu 常见工具是 ufw。
查看状态:
sudo ufw status verbose
如果准备启用 ufw,先确认 SSH 已放行:
sudo ufw allow OpenSSH
如果改了 SSH 端口:
sudo ufw allow 新端口/tcp
再放行 80 和 443:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
启用后,立刻新开终端测试 SSH 是否还能登录。防火墙不是必须复杂,但当前状态必须清楚。
数据库端口。
数据库默认只服务内部应用,不直接暴露公网。Docker Compose 场景尤其要注意 ports:
ports:
- "3306:3306"
这通常表示把数据库端口映射到宿主机。如果宿主机防火墙和安全组也放行,数据库就可能公网可访问。多数单机部署里,应用容器和数据库容器在同一个 Docker 网络中,不需要把数据库端口映射到宿主机,应用可以通过服务名访问数据库。
检查监听:
sudo ss -lntp
检查 Docker 映射:
docker ps
如果看到:
0.0.0.0:3306->3306/tcp
就要确认这是不是预期结果。本地工具要连接数据库时,优先考虑 SSH 隧道,而不是直接把数据库端口放到公网。
fail2ban。
fail2ban 不是万能工具,但对个人服务器实用。它可以根据日志识别异常登录尝试,并临时封禁来源 IP。
安装:
sudo apt update
sudo apt install fail2ban
查看状态:
fail2ban-client --version
# 如果没装,进行安装
sudo apt install -y fail2ban
# 启动并开机自启:
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
# 检查状态
sudo systemctl status fail2ban
#查看 SSH 防护 jail:
sudo fail2ban-client status sshd
不同系统里 jail 名称可能不同,有的叫 ssh,有的叫 sshd。fail2ban 的作用是减少低级爆破噪音,不能替代强密码、密钥登录、安全组、防火墙和数据库端口控制。
自定义SSH防护配置
现在可以做一个自定义 SSH 防护配置,让策略更明确。创建配置文件:
sudo vim /etc/fail2ban/jail.d/sshd.local
#写入
[sshd]
enabled = true
port = ssh
filter = sshd
backend = systemd
maxretry = 5
findtime = 10m
bantime = 1h
意思就是 10 分钟内失败 5 次,就封禁 1 小时
检查
sudo fail2ban-client status sshd
# 结果
Status for the jail: sshd
|- Filter
| |- Currently failed: 0
| |- Total failed: 0
| `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
|- Currently banned: 1
|- Total banned: 1
`- Banned IP list: 60.163.139.198
再补两个常用的查看命令
# 查看被封禁的 IP:
sudo fail2ban-client status sshd
# 手动解封某个 IP:
sudo fail2ban-client set sshd unbanip 1.2.3.4
日志检查。
至少要知道关键日志怎么看。SSH 服务日志:
sudo journalctl -u ssh --no-pager -n 100
如果服务名是 sshd:
sudo journalctl -u sshd --no-pager -n 100
系统日志:
sudo journalctl --no-pager -n 100
Ubuntu 常见认证日志:
sudo tail -n 100 /var/log/auth.log
后面部署 Nginx 后,还要看访问日志和错误日志:
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log
如果 Nginx 在容器里,就看容器日志:
docker logs 容器名
日志检查不需要一开始做得很重,但出问题时必须知道去哪里看。
健康检查。
服务器健康还需经常检查自身状态,磁盘快满了,内存紧张,服务一直重启,日志正在增长。
常用命令包括:
df -h # 查看磁盘空间,重点看 / 分区使用率
free -h # 查看内存和 swap
uptime # 查看运行时间和负载
top # 查看进程
sudo ss -lntp # 查看运行时间和负载
systemctl status 服务名 # 查看服务状态
docker ps # 查看容器状态
如果需要更直观地看进程资源,可以安装 htop:
sudo apt install htop
这些命令能帮助快速判断:磁盘是否充足,内存是否紧张,负载是否异常,服务是否运行,端口是否符合预期。
总结
对以上步骤简单总结下,就是:
- 日常使用普通用户;
- SSH 管理入口可控;
- 安全组只开放必要端口;
- 防火墙状态明确;
- 数据库默认内部访问;
- fail2ban 作为补充防护;
- 知道日志在哪里;
- 会检查磁盘、内存、负载、端口和服务状态。
这记不简单检查不能解决所有问题。它不包含系统补丁、备份策略、入侵检测、权限审计、密钥管理、Web 漏洞、WAF、容器安全、数据库备份和恢复演练。后面这些会继续做,不适合一开始就全部压上来。
对个人博客第一阶段来说,建立基本安全边界。先让服务器不是裸奔,再逐步迭代。
下一篇我会做一次阶段复盘:买完服务器后,我才知道上线前最重要的是安全。这篇会把上几篇内容串起来,复盘下为什么在真正部署项目前,要先处理这些看不见的工作。
本文由 楸木 原创,转载请注明出处。