特别提醒:
进行以下操作前请先确认已经配置软件源、系统全量更新、普通用户授权sudo、设置好时区和时间,由于我在系统安装好第一时间就进行了以上设置,这里就不再累赘了。没有设置好的请看我上一篇文章的第三部分(基础设置)。本次介绍的初级安全配置,其他更高阶的安全等其他配置,将在后续文章中介绍。本次演示案例linux发行版是Debian 12(bookworm)。
一、系统自动安全更新
在Debian 12系统中设置仅自动安全更新(不包含全量系统更新),最可靠的方案是通过unattended-upgrades工具实现,以下是完整配置步骤。
1.安装必要的组件
sudo apt update&& sudo apt install unattended-upgrades-y
2.交互式启用自动更新
sudo dpkg-reconfigure --priority=low unattended-upgrades
在弹出的交互界面中选择Yes,系统会自动生成
/etc/apt/apt.conf.d/20auto-upgrades 配置文件并设置Unattended-Upgrade "1",
该文件控制着自动更新的执行频率。
配置自动更新计划:
sudo nano /etc/apt/apt.conf.d/20auto-upgrades 配置内容如下: # 每天更新软件包列表(1=启用,0=禁用) APT::Periodic::Update-Package-Lists "1"; # 每天执行安全更新(1=启用,0=禁用) APT::Periodic::Unattended-Upgrade "1"; # 每天自动下载可更新包, # Unattended-Upgrade为1,Download-Upgradeable-Packages就不用了 # APT::Periodic::Download-Upgradeable-Packages "1"; # 每周清理旧包缓存,一周一次 # 该清理只删除已下载的.deb包缓存,不影响已安装软件。 APT::Periodic::AutocleanInterval "7"; |
3.配置更新源
为了确保只自动安装安全更新,而不进行全量系统更新,
需要编辑unattended-upgrades的核心配置文件 /etc/apt/apt.conf.d/50unattended-upgrades。
# 修改前请务必先备份好配置文件
sudo cp /etc/apt/apt.conf.d/50unattended-upgrades/etc/apt/apt.conf.d/50unattended-upgrades.bak.$(date +%Y%m%d_%H%M%S)
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
找到Unattended-Upgrade::Allowed-Origins (或 Origins-Pattern) 部分,
确保仅保留安全更新源,注释掉其他所有更新源。参考配置如下:
Unattended-Upgrade::Origins-Pattern{
"${distro_id}:${distro_codename}-security";
// "${distro_id}:${distro_codename}-updates";
// "${distro_id}:${distro_codename}-proposed-updates";
// "${distro_id}:${distro_codename}-backports";
};
注意:
保持启用${distro_id}:${distro_codename}-security,注释掉其他行。
其他必要配置:
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";# 内核自动清理 Unattended-Upgrade::Automatic-Reboot"false"; # 禁止自动重启(服务器必选) Unattended-Upgrade::Automatic-Reboot-Time "02:00"; # 若启用设置空闲时间重启 # Unattended-Upgrade::Remove-Unused-Dependencies"true"; # 自动卸载无用依赖 |
说明:
配置生效,不需要重启服务。
该服务为oneshot 类型,由定时器触发,下次执行时会自动读取新配置。
不过若不放心,可执行sudo systemctl restart unattended-upgrades 也无害。
4.测试配置
模拟运行(验证规则有效性,无实际操作):
sudo unattended-upgrade --dry-run --debug 2>&1 | grep -i "Allowed origins"
确认输出中label只有 Security。
查看实际会升级的包:
sudo unattended-upgrade --dry-run --debug 2>&1 | grep -A 20 "Packages that will be upgraded"
如果输出为空或只显示类似(none),说明当前没有可用的安全更新。
如果有列出软件包,检查包名或版本号中是否带有+deb12uX 或来自 bookworm-security。
不应出现大量常规更新(例如openssh-server 的新版本如果不是安全修复,就不应出现)。
模拟运行查看总体输出: sudo unattended-upgrade --dry-run --debug 输出末尾会显示类似: No packages found that can be upgraded unattended 或者列出会升级的包。同时注意输出中是否有WARNING或 ERROR 提示依赖问题, 若没有说明安全更新可以正常安装。 |
5.检查服务状态
先查定时任务,确保系统每天会自动触发更新:
systemctl status apt-daily.timer apt-daily-upgrade.timer
正常状态:active (waiting) 表示定时任务已开启
再查核心服务,确保自动更新程序正常运行:
sudo systemctl status unattended-upgrades
正常状态:active (running) 表示服务正常
二、配置防火墙
主要对端口进行白名单设置,目前三种主流的配置工具:
UFW,简单易用,适合新手;
iptables,功能强大,适合高级用户;
nftables,语法现代,性能更好,Debian 12默认防火墙框架。
本案例用nftables工具。
1.启用nftables服务
sudo apt install -y nftables
sudo systemctl enable --now nftables
2.修改配置文件
# 修改前请务必先备份好配置文件
sudo cp /etc/nftables.conf /etc/nftables.conf.bak.$(date +%Y%m%d_%H%M%S)
sudo nano /etc/nftables.conf
# 配置文件修改参考案例如下:
flush ruleset table inet filter { chain input { type filter hook input priority filter; policy drop; # 放行本地环回 iifname "lo" accept; # 放行已建立连接 ct state established,related accept; # 放行 SSH 22, 2222 和 HTTP/HTTPS 80,443 # 为什么SSH设置了2个端口??? # 因为想把默认端口22改成2222,万一没改成功22也不能用了, # 所以先2个端口都放行,等确认2222端口正常后再去掉22端口 tcp dport { 22, 2222, 80, 443 } accept; # 从 指定网卡 放行 # iifname "eth0" tcp dport { 80, 443 } accept; } chain forward { type filter hook forward priority filter; policy drop; # 转发默认拒绝,根据需要添加放行规则 } chain output { type filter hook output priority filter; policy accept; # 出站放行 } } |
关键提示:
默认策略 (policy drop):
是实现白名单机制的核心,它确保了所有未明确允许的流量都会被拒绝。policy drop必须加在input和forward链,output保持accept避免断网。
顺序敏感:
规则的顺序至关重要。通常最通用的放行规则(如放行established,related状态)放在前面。
接口名称:
请务必将示例中的eth0替换为您服务器实际的网络接口名(可通过ip link命令查看)。
3.重启服务加载新规则
# 重启前应先验证配置文件语法是否正确
sudo nft -c -f /etc/nftables.conf
sudo systemctl restart nftables
说明:
重启nftables服务通常不会中断现有SSH 连接,因为ct state established,related accept规则会保留已建立的连接。但若配置文件有误导致服务启动失败,则规则可能被清空(此时默认无防火墙限制)。因此语法验证很重要。
4.验证规则
sudo nft list ruleset
sudo systemctl status nftables
nftables 状态为active (exited) 表明规则已成功加载
5.设置开机自启动
# sudo systemctl enable nftables # 第1步已使用enable --now,则此步骤可省略
sudo systemctl is-enabled nftables# 如果显示enabled就无需操作
三、配置SSH
1.普通用户授权sudo禁用root远程登录
sudo adduser 普通用户名
sudo usermod -aG sudo 普通用户名
su - 普通用户名
sudo whoami
第一次使用sudo 会提示输入密码,输出应为 root。
禁用root远程登录,配置文件找到或添加:
PermitRootLogin no
注意:
必须删除行首的#注释,否则配置不生效。 全局检查配置冲突: 执行sudo grep -r PermitRootLogin /etc/ssh/,确保所有相关文件中只有PermitRootLogin no,无其他yes配置。若有/etc/ssh/sshd_config.d/下的自定义配置(如云服务器初始化文件),需同步修改为no。 |
2.禁止空密码账户登录
# Debian 12 默认已禁用,但需显式确认。
sudo grep -E "^PermitEmptyPasswords" /etc/ssh/sshd_config
如果没有输出或显示PermitEmptyPasswords no,则已安全;
如果显示PermitEmptyPasswords yes,则需修改。
PermitEmptyPasswords no
3.禁用密码认证,启用密钥认证
PasswordAuthentication no
PubkeyAuthentication yes
注意:
这是防暴力破解最有效的手段,但务必先确保您的公钥已添加到服务器的 ~/.ssh/authorized_keys,否则会把自己锁在门外。
4.限制可登录的用户或组
仅允许指定的普通用户登录,减少攻击面。
AllowUsers 用户名# 多个用户用空格隔开
注意:
如果你只允许了user用户,那么root也无法登录(即使PermitRootLogin设置为yes也会被AllowUsers覆盖)。
5.设置最大认证尝试次数
sudo grep -i "^MaxAuthTries" /etc/ssh/sshd_config # 如果没有输出则使用默认值6
MaxAuthTries 3 # 建议放在靠近PasswordAuthentication等认证相关配置附近
6.设置空闲超时自动断开
推荐值:
ClientAliveInterval 300# 每300秒向客户端发送一次存活请求
ClientAliveCountMax 2# 最多发送 2 次请求后断开连接
实际空闲超时时间= ClientAliveInterval × (ClientAliveCountMax + 1) ≈ 15 分钟
7.设置会话超时自动断开
ChannelTimeout session=10m # 空闲10分钟没有键盘输入就断开
特别提醒:不能在等号前后加空格
注意:
设置的是整个 SSH 会话的空闲超时(而不是针对通道)。如果不确定自己的 OpenSSH 版本是否支持 ChannelTimeout,可以运行 ssh -V 查看。版本低于 9.0 则不支持该指令,需要注释掉或升级 OpenSSH。
8.启用严格模式
检查用户目录和关键文件的权限,防止因权限错误导致安全风险(默认已开启)。
sudo grep -E "^StrictModes" /etc/ssh/sshd_config # 如果没有输出,则已安全。
StrictModes yes# 启用严格模式
9.修改默认端口
Port 端口号
10.修改配置流程如下
# 修改前请务必先备份好配置文件 sudo cp /etc/ssh/sshd_config/etc/ssh/sshd_config.bak.$(date +%Y%m%d_%H%M%S) # 修改配置文件 sudo nano /etc/ssh/sshd_config # 配置项举例 PermitRootLogin no # 禁用root远程登录 PermitEmptyPasswords no # 禁止空密码账户登录 AllowUsers 用户名 # 限制可登录的用户,多个用户用空格隔开 MaxAuthTries 3 # 最大认证尝试次数 ClientAliveInterval 300 # 空闲超时自动断开,存活请求间隔 ClientAliveCountMax 2 # 空闲超时自动断开,发送次数 ChannelTimeout session=10m # 空闲10分钟没有键盘输入就断开 StrictModes yes # 启用严格模式 Port 端口号 # 修改SSH默认端口号 # 语法检查如果没有输出任何错误,说明配置正确 sudo sshd -t # 重新读取配置文件,推荐用 reload sudo systemctl reload ssh # 不会断开已建立的 SSH 连接,新连接使用新配置,旧连接保持原有设置继续运行 # 下面的命令重启SSH服务,会断开所有现有SSH 连接 #(包括你正在使用的这个会话,除非你通过其他方式保持了连接 sudo systemctl restart ssh |
四、禁用不必要的服务和端口
系统会默认预装/启动一些无用的服务,每多一个服务就多一个攻击入口。禁用不必要的网络服务和后台进程,是Linux安全加固的关键一步。这能有效减少系统的攻击面。
1.服务预览
1).绝对不能关的服务
sshd(SSH)、
ufw / nftables(防火墙)、
dbus / polkit / systemd-journald(系统核心)、
network-manager 或 systemd-networkd(网络)。
注意:
上述服务是系统正常运行或远程管理所必需的,但在特定配置下部分服务可能未启用。请勿主动禁用正在运行的服务,尤其是 sshd。
2).常见可“精简”服务清单
下表列出了一些Debian 系统中常见的、但在纯净服务器环境下通常不必要的服务。请逐项核对你的系统清单。
服务名称 | 用途说明 | 处置建议 |
bluetooth.service | 蓝牙设备管理 | ❌ 可禁用。服务器基本不需要蓝牙。 |
avahi-daemon.service | 零配置网络发现 (mDNS/DNS-SD) | ❌ 可禁用。服务器不需要这个功能。 |
cups.service | 打印服务 | ❌ 可禁用。服务器基本不需要打印。 |
ModemManager.service | 移动宽带管理 | ❌ 可禁用。服务器不会使用 3G/4G 上网卡。 |
postfix.service 或 exim4.service | 邮件传输代理 (MTA) | ❌ 可禁用。如果不发邮件可禁用,若需要本地邮件通知,可保留并配置为仅本地-33。 |
nfs-*.service | NFS 文件共享服务 | ❌ 可禁用。如果不使用 NFS 共享。 |
smbd.service / nmbd.service | Samba 文件共享服务 | ❌ 可禁用。如果不使用 SMB/CIFS 协议。 |
inetd.service或openbsd-inetd.service / vsftpd.service 或 proftpd.service | Telnet/FTP 明文传输服务 | ❌ 必须禁用。极不安全,应使用 SSH/SFTP 替代-33。 |
sshd.service | SSH 服务 | ✅ 必须保留。这是你远程管理服务器的唯一入口。 |
cron.service | 系统日志轮转、定期任务依赖 | ✅ 建议保留。系统定时任务(如日志轮转)可能依赖它-11。 |
atd.service | 一次性任务 | ❓ 视情况。一次性任务,非必需可禁用 |
rsyslog.service | 系统日志服务 | ✅ 建议保留。用于记录系统和应用程序日志-30。 |
systemd-timesyncd | 网络时间同步 | ❓ 视情况。确保服务器时间准确,对于安全审计和日志记录很重要。 |
dbus.service | 系统消息总线 | ✅ 建议保留。许多核心系统服务依赖它-11。 |
apparmor.service | 强制访问控制工具 | ✅ 建议保留。为系统提供额外的安全层-11。 |
lvm2-monitor.service | LVM 监控服务 | ❓ 视情况。若你使用了逻辑卷管理 (LVM) 则需要,否则可禁用-33。 |
mdmonitor.service | 软件 RAID 监控服务 | ❓ 视情况。若你配置了软件 RAID (mdadm) 则需要,否则可禁用-33。 |
NetworkManager.service | 动态网络配置 | ❓ 视情况。服务器通常使用 systemd-networkd 或直接配置 /etc/network/interfaces,可禁用-27。 |
| | |
其他常见服务检查项,例如:
apache2、nginx、mysql、snmpd、rpcbind 等,请根据实际用途检查,如非必需应禁用。
2.全面检查
1).列出所有已知的服务单元文件:
systemctl list-unit-files --type=service
sudo systemctl list-sockets
sudo systemctl list-timers
2).查看当前正在运行的服务:
systemctl list-units --type=service --state=running
3).检查开机自启的服务:
systemctl list-unit-files --type=service --state=enabled
4).检查网络监听端口:
sudo ss -tuln -p
此命令是发现“幕后”网络服务的利器。它会列出所有正在监听的端口,并显示是哪个进程在占用。
3.逐一处理
注意: 在禁用任何服务前,请先确认该服务的用途。如果不确定,请务必先查阅资料或咨询,切勿盲目操作。 |
停止服务:
立即终止该服务的运行,但系统重启后它可能还会自启。
sudo systemctl stop <service_name>
禁用服务:
禁止该服务在系统启动时自动运行,但不会停止当前正在运行的服务。
sudo systemctl disable <service_name>
停止并禁用服务:
将停止和禁用两步合并。
sudo systemctl disable --now <service_name>
屏蔽服务:
这是一种更彻底的禁用方式,通过创建一个指向/dev/nul的符号链接来“屏蔽”它,使其无法被任何其他服务启动。建议仅在确认服务不会被任何方式启动时才使用 mask,通常 disable --now 已足够。除非你非常确定,否则谨慎使用。
sudo systemctl mask <service_name>
误操作恢复服务:
如果误操作mask,可以使用sudo systemctl unmask <service_name>命令恢复,
如果仅执行了disable --now,还原请执行:sudo systemctl enable --now <service_name>
验证服务状态:
每次操作后,最好都检查一下,确保服务确实已被正确停止和禁用。
systemctl status <service_name>
检查 socket 与 timer 激活的服务:
注意:某些服务通过 socket 或 timer 激活,即使disable也可能被拉起。
务必执行systemctl list-sockets 和 systemctl list-timers 检查,并对不需要的服务执行 mask。
特别提醒: 请务必确保sshd.service 是 enabled 状态,否则下次系统重启后你将无法通过 SSH 连接 sudo systemctl is-enabled sshd.service # 如果输出不是 'enabled',请执行: # sudo systemctl enable sshd.service |
4.禁用服务后检查
# 查看当前运行的服务(应已看不到禁用的)
systemctl list-units --type=service --state=running
# 查看开机自启(禁用的应消失或变为disabled)
systemctl list-unit-files --type=service --state=enabled
再次检查监听端口,确认不必要的端口已消失
sudo ss -tuln -p
5.卸载无用软件包
1).自动清理无用的依赖包:
这个命令非常安全,它会清理那些因依赖关系被安装但现在已经没有任何软件需要的软件包
sudo apt autoremove --purge
2).查找并清理孤立的软件包 (可选):
对于更高级的清理,可以安装deborphan 工具来查找系统中没有其他包依赖的“孤儿”包
# 安装 deborphan(如果尚未安装)
sudo apt install deborphan
# 列出所有孤儿包
deborphan
3).移除已知的不必要软件包:
对于那些提供已知无用服务的软件包,可以直接使用purge 命令将其及其配置文件一并删除。例如,卸载打印服务 cups:
sudo apt purge cups
6.建议定期检查
为了保持系统的长期健康,建议养成定期“体检”的习惯,比如每月运行一次
systemctl list-units --type=service --state=running,查看是否有新的、不必要的服务意外运行起来。
附录:阻止系统合盖后休眠
由于本人是使用废旧的笔记本电脑模拟安装了服务器系统,故此处增加了这个配置,请按需选择是否进行这项设置。
# 修改前请务必先备份好配置文件
sudo cp /etc/systemd/logind.conf /etc/systemd/logind.conf.bak.$(date +%Y%m%d_%H%M%S)
sudo nano /etc/systemd/logind.conf
在文件中找到并修改以下配置项。如果找不到,可以手动添加。
# 这个参数用于控制当笔记本使用电池供电时合盖后的系统行为 # 设置为 ignore 代表不执行任何操作 HandleLidSwitch=ignore # 这个参数用于控制当笔记本使用外部电源时合盖后的系统行为 # 设置为 ignore确保插电时也不会休眠 HandleLidSwitchExternalPower=ignore |
保存修改并退出 (Ctrl+O, Enter, Ctrl+X)。
重启systemd-logind服务,让修改生效:
sudo systemctl restart systemd-logind
如果这个命令没有立即生效,可以重启整个系统
sudo reboot
注意:
桌面环境的电源管理软件有时会覆盖系统的设置。为了确保万无一失,可以额外进行设置。
但是不同桌面环境配置不一样,由于本案例是无桌面版的纯净系统此处没有设置。
如果合盖后仍然休眠(极少见): 可以执行以下命令彻底禁用系统的休眠/挂起目标(这会完全禁止系统进入睡眠状态) sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target 注意: 此操作不可逆(除非手动unmask),会彻底禁止任何睡眠/休眠功能。 一般不需要做,只有在上述方法无效时才考虑。 |