VPS安全加固完整指南:从SSH配置到UFW防火墙策略(2026)
买了一块VPS,把默认密码改了就觉得安全了?兄弟,醒醒——互联网上的扫描器24小时不停地在扫22端口,从你装好系统的那一刻起,就有人在尝试暴力破解你的SSH。本神人今天就带你走一遍VPS安全加固的完整流程,从SSH锁死、防火墙配置到入侵检测,一条龙搞定。
第一步:SSH安全加固——锁死大门
SSH是VPS的大门,90%的攻击都是从SSH暴力破解开始的。我们先把它加固到连黑客看了都摇头。
1.1 修改SSH默认端口
默认22端口就是靶子。换个冷门端口,扫描成本直接拉高一个数量级。
$ sudo sed -i 's/^#Port 22/Port 2222/' /etc/ssh/sshd_config
$ sudo systemctl restart sshd
$ sudo systemctl status sshd
● ssh.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2026-05-20 08:30:00 UTC
Main PID: 12345 (sshd)
Tasks: 1 (limited: 2280)
Memory: 1.2M
CPU: 10ms
CGroup: /system.slice/ssh.service
└─12345 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"
重要:在断开当前连接前,另开一个终端测试新端口能连上!
$ ssh -p 2222 user@your-server-ip
1.2 禁止root直接登录
root是每个Linux系统的超管账户,攻击者只要猜对root密码就能为所欲为。禁止root直接SSH登录,先用普通用户登录再sudo提权。
$ sudo adduser vpsadmin
$ sudo usermod -aG sudo vpsadmin
$ sudo sed -i 's/^#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
$ sudo systemctl restart sshd
1.3 配置SSH密钥登录
密码登录再复杂也有被爆破的风险。密钥登录用的是公钥加密,理论上无法暴力破解。
# 本地机器生成密钥对
$ ssh-keygen -t ed25519 -C "vps-$(date +%Y%m%d)"
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/user/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_ed25519
Your public key has been saved in /home/user/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx vps-20260520
# 上传公钥到VPS
$ ssh-copy-id -p 2222 vpsadmin@your-server-ip
Number of key(s) added: 1
# 禁用密码登录
$ sudo sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
$ sudo sed -i 's/^#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config
$ sudo systemctl restart sshd
1.4 配置fail2ban——自动封禁暴力破解
即使用了密钥登录,也不代表不会有遗落的密码登录服务被攻击。fail2ban会监控SSH日志,发现多次失败尝试后自动封禁IP。
$ sudo apt update && sudo apt install fail2ban -y
$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
$ sudo cat /etc/fail2ban/jail.local | grep -A 15 '^\[sshd\]' | head -20
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
bantime = 3600
findtime = 600
$ sudo systemctl restart fail2ban
$ sudo systemctl status fail2ban
● fail2ban.service - Fail2Ban Service
Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2026-05-20 08:35:00 UTC
Docs: man:fail2ban(1)
$ sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
| |- Currently failed: 0
| |- Total failed: 0
| `- File list: /var/log/auth.log
`- Actions
|- Currently banned: 0
|- Total banned: 0
`- Banned IP list:
第二步:UFW防火墙——设好安检关卡
UFW(Uncomplicated Firewall)是iptables的前端封装,配置简单且功能强大。把不需要的端口统统关掉。
2.1 安装并启用UFW
$ sudo apt install ufw -y
$ sudo ufw default deny incoming
$ sudo ufw default allow outgoing
# 只开放必要的端口(注意替换成你改过的SSH端口)
$ sudo ufw allow 2222/tcp comment 'SSH'
$ sudo ufw allow 80/tcp comment 'HTTP'
$ sudo ufw allow 443/tcp comment 'HTTPS'
$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip
To Action From
-- ------ ----
2222/tcp ALLOW IN Anywhere
80/tcp ALLOW IN Anywhere
443/tcp ALLOW IN Anywhere
2222/tcp (v6) ALLOW IN Anywhere (v6)
80/tcp (v6) ALLOW IN Anywhere (v6)
443/tcp (v6) ALLOW IN Anywhere (v6)
如果跑数据库(MySQL/PostgreSQL),千万别把3306/5432暴露到公网——绑定到127.0.0.1就好。
2.2 限制SSH来源IP(进阶)
如果你有固定的办公公网IP,可以只允许那个IP访问SSH,其他全部拒绝。这是最高安全策略。
$ sudo ufw delete allow 2222/tcp
$ sudo ufw allow from 203.0.113.0/24 to any port 2222 proto tcp comment 'SSH from office'
$ sudo ufw reload
$ sudo ufw status
Status: active
To Action From
-- ------ ----
2222/tcp ALLOW IN 203.0.113.0/24
80/tcp ALLOW IN Anywhere
443/tcp ALLOW IN Anywhere
2.3 查看UFW日志
$ sudo tail -n 20 /var/log/ufw.log
May 20 08:40:01 vps kernel: [UFW BLOCK] IN=eth0 OUT= MAC=xx:xx:xx:xx:xx:xx SRC=103.235.46.39 DST=your-ip LEN=40 TOS=0x00 PREC=0x00 TTL=245 ID=54321 PROTO=TCP SPT=44322 DPT=3306 WINDOW=1024 RES=0x00 SYN URGP=0
May 20 08:40:15 vps kernel: [UFW BLOCK] IN=eth0 OUT= MAC=xx:xx:xx:xx:xx:xx SRC=185.220.101.42 DST=your-ip LEN=40 TOS=0x00 PREC=0x00 TTL=241 ID=12345 PROTO=TCP SPT=38295 DPT=6379 WINDOW=65535 RES=0x00 SYN URGP=0
看看这些日志:有人在扫你的3306(MySQL)和6379(Redis)端口。UFW全部挡在外面了。
第三步:系统级安全配置
3.1 自动安全更新
安全漏洞几乎每个月都有新的。配置自动安装安全更新,防止已知漏洞被利用。
$ sudo apt install unattended-upgrades -y
$ sudo dpkg-reconfigure --priority=low unattended-upgrades
# 选择 Yes
$ sudo cat /etc/apt/apt.conf.d/50unattended-upgrades | grep -E "Allowed|auto|Fix|^//" | head -20
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}";
"${distro_id}:${distro_codename}-security";
"${distro_id}ESMApps:${distro_codename}-apps-security";
"${distro_id}ESM:${distro_codename}-infra-security";
};
# 测试配置
$ sudo unattended-upgrades --dry-run --debug 2>&1 | tail -5
2026-05-20 08:45:00,001 INFO No packages found that can be upgraded unattended and no pending auto-removals
3.2 检查监听端口
运行中的服务如果在监听外网端口而你并不知道,那就是个安全隐患。
$ sudo ss -tlnp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:2222 0.0.0.0:* users:(("sshd",pid=12345,fd=3))
LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=23456,fd=6))
LISTEN 0 128 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=23456,fd=7))
LISTEN 0 128 127.0.0.1:3306 0.0.0.0:* users:(("mysqld",pid=34567,fd=24))
看到区别了吗?SSH、HTTP、HTTPS监听0.0.0.0(所有网卡),这是正常的。但MySQL的3306只绑在127.0.0.1(本地回环)——这才是正确姿势。如果看到0.0.0.0:3306,立刻去改MySQL配置。
3.3 配置日志审计
$ sudo apt install auditd -y
$ sudo auditctl -w /etc/ssh/sshd_config -p wa -k ssh_config_change
$ sudo auditctl -w /etc/passwd -p wa -k user_db
$ sudo auditctl -l
-w /etc/ssh/sshd_config -p wa -k ssh_config_change
-w /etc/passwd -p wa -k user_db
$ sudo ausearch -k ssh_config_change --start today 2>/dev/null | head -20
----
time->Thu May 20 08:30:00 2026
type=PROCTITLE msg=audit(1720000000.123:456): proctitle=736564002D69002F6574632F7373682F737368645F636F6E666967
type=PATH msg=audit(1720000000.123:456): item=0 name="/etc/ssh/sshd_config" inode=78901 dev=08:01 mode=0100644 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0
type=SYSCALL msg=audit(1720000000.123:456): arch=c000003e syscall=82 success=yes exit=0 a0=7ffe3c0f5000 a1=4 a2=1fff a3=7ffe3c0f4610 items=1 ppid=1 pid=1234 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=1 comm="sed" exe="/usr/bin/sed" subj=--- key="ssh_config_change"
第四步:配置rkhunter + chkrootkit——检测入侵
做好了防御,还得有检测手段。rkhunter和chkrootkit是经典的rootkit检测工具。
$ sudo apt install rkhunter chkrootkit -y
# 更新rkhunter数据库
$ sudo rkhunter --propupd
$ sudo rkhunter --check --skip-keypress
[ Rootkit Hunter version 1.4.6 ]
Checking system commands...
Performing 'strings' command checks
Checking 'strings' command [ OK ]
Checking for rootkits...
Checking for 'Rootkits'...
Performing check of known rootkit files and directories
Checking for 'ADM Worm' [ Not found ]
Checking for 'Ajakit Rootkit' [ Not found ]
...
System checks summary
=====================
File properties checks...
Required commands check failed [ Warning ]
Rootkit checks...
Rootkit 'Rootkit' [ Not found ]
# chkrootkit快速扫描
$ sudo chkrootkit | grep -v "not infected"
ROOTDIR is '/'
Checking `bifrost'... not found
Checking `console'... not found
...
Checking `lkm'... chkproc: nothing deleted
chkdirs: nothing detected
每周跑一次扫描,或者配置cron自动执行并邮件通知。
第五步:快速安全检查清单
加固完成之后,跑个快速自查确认万无一失:
# 1. 检查SSH配置
$ sudo sshd -T | grep -E "(port|permitrootlogin|passwordauthentication|pubkeyauthentication)"
port 2222
permitrootlogin no
passwordauthentication no
pubkeyauthentication yes
# 2. 检查UFW状态
$ sudo ufw status verbose | head -5
Status: active
# 3. 检查fail2ban状态
$ sudo fail2ban-client status sshd | grep "Total banned"
|- Total banned: 42
# 4. 检查未授权用户
$ sudo cat /etc/passwd | grep -E "(/bin/bash|/bin/sh)" | grep -v "^#"
root:x:0:0:root:/root:/bin/bash
vpsadmin:x:1000:1000:,,,:/home/vpsadmin:/bin/bash
看到fail2ban已经帮忙封了42个IP了吗?如果没有fail2ban,这42个IP可能还在尝试登录你的服务器。