VPS安全加固完整指南:从SSH配置到UFW防火墙策略(2026)

📝 1082 字 · ☕ 4 分钟阅读

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可能还在尝试登录你的服务器。

FAQ:常见问题

改了SSH端口后自己连不上怎么办?

这是最常见的翻车现场。解决方案:大多数VPS提供商(如Linode、DigitalOcean、Vultr)都提供Web控制台(VNC/IPMI),登陆后把端口改回去或检查firewalld/ufw规则。如果连Web控制台也连不上,重启到单用户模式修复。所以务必在修改配置前留一个备用SSH会话。

UFW和firewalld选哪个更好?

Ubuntu/Debian默认用UFW,CentOS/RHEL默认用firewalld。两者底层都是netfilter/iptables或nftables,功能上没有本质区别。建议跟发行版走——Ubuntu用UFW,RHEL系用firewalld。混着用可能造成规则冲突。本文基于Ubuntu 24.04 LTS,所以推荐UFW。

用了SSH密钥登录后还需要配置fail2ban吗?

需要。密钥登录确实很难被破解,但服务器上可能还有其他服务(如Web应用、邮件服务)存在密码登录入口。而且日志里每天几千次失败的SSH连接请求本身就是一种压力。fail2ban能在攻击发生前就阻断IP,减少系统日志噪音,也能在某些密码登录遗留场景中提供防护。一句话:防御深度没有上限

📤 分享这篇文章